Abra API: Promotions
Last updated: September 29, 2026
A promotion puts one or more discounts in front of shoppers: it sets who sees them on the storefront (visibility), when they run and on which channels. The discounts themselves are managed with Abra API: Discounts. A store can have one live PUBLIC promotion per channel, so read Promotion publishing rules before you publish one. For what each visibility means, see Public Promotions, Abra Links (Private Promos) and Customer Account Visibility.
Beta. The Abra API is in beta, so its behavior may change. If something doesn't work as described, contact us at help@abrapromotions.com.
The promotion object
Promotion endpoints return promotions in this shape, in the data field of the response.
Name | Description |
|---|---|
string | Abra ID of the promotion. Use it in |
string | Name of the promotion. |
string or null | URL-friendly form of the title, used in the promotion's Abra link. |
string or null | Store path the promotion's link opens, or |
string | Where the promotion comes from: |
string |
|
string |
|
string or null | Start time (ISO 8601), or |
string or null | End time (ISO 8601), or |
boolean | Whether the dates come from the attached discounts. |
array of strings or null | Channels of a PUBLIC promotion. |
string or null | List results only: the promotion's storefront link. For a PUBLIC promotion it has |
string or null | List results only: for a promotion that isn't PUBLIC, the same link with a |
array of objects | Attached discounts. List results leave out each discount's |
array of objects | Storefront blocks of the promotion, set up in the Abra app. Left out of list results. |
string | When the promotion was created (ISO 8601). |
string | When the promotion last changed (ISO 8601). |
discounts[]
Name | Description |
|---|---|
string | Abra ID of the discount. |
string | Title of the discount. |
string |
|
string or null | How the discount applies, for example |
string or null | The discount's |
object or null | The discount's settings; see Abra API: Discount types. Left out of list results. One of 13 shapes, chosen by |
string |
|
string or null | Start time (ISO 8601), or |
string or null | End time (ISO 8601), or |
string or null | Shopify ID (GID) of the discount. |
string |
|
List promotions
GET /v1/partner/promotions
Returns the store's promotions, newest first, one page at a time (see Pagination). Filter with status, visibility, search (part of the title, not case-sensitive) and discountId (promotions that contain any of the given discount IDs). status, visibility and discountId take comma-separated lists. For visibility, customer_account matches every customer-tag visibility.
Sort with sort=field:direction. The fields are createdAt (the default), updatedAt, title and status, and the direction is asc or desc (the default).
List results are lighter than a single promotion: they leave out blockGroups and each discount's discountValue. Get the promotion by ID for the full object.
Query parameters
Name | Description |
|---|---|
integer | The page to return. The first page is 1. Defaults to |
integer | The number of promotions per page. Between 1 and 100. Defaults to |
string | Comma-separated list of statuses. Matches promotions whose status is in the set. Each value is one of |
string | Comma-separated list of visibilities (PRIVATE, PUBLIC, TAG-<tag>, or customer_account to match any customer-tag visibility). Matches promotions whose visibility is in the set. |
string | Returns only promotions whose title contains this text. The match is not case-sensitive. |
string | The sort order, as |
string | Comma-separated list of discount Abra IDs. Returns promotions that contain at least one of them. |
Example request
curl "$ABRA_API_BASE/v1/partner/promotions" \
-H "Authorization: Bearer $ABRA_API_TOKEN"Response
200 OK. data is an array of promotions. Their fields are listed in The promotion object. pagination describes the page:
Name | Description |
|---|---|
number | Current page number. |
number | Number of items per page. |
number | Total number of items. |
number | Total number of pages. |
boolean | Whether there is a next page. |
boolean | Whether there is a previous page. |
Errors
Status | Code | Description |
|---|---|---|
|
| A query value is invalid, for example |
|
|
|
|
| The |
|
| The token is missing, expired or revoked. |
Create a promotion
POST /v1/partner/promotions
Creates a promotion. Every field is optional. Without a title, the promotion takes the title of its first discount, or an Untitled- code. If the title is already used in the store, a number is added, for example Summer Sale-1.
Attach discounts in discounts by their Shopify discount ID (shopifyDiscountId on a discount). A Shopify discount that Abra doesn't know yet is imported from Shopify. While useDiscountDates is true (the default), the promotion's dates come from its discounts and any startsAt or endsAt you send is ignored.
New promotions are PRIVATE unless you set visibility. A store can have one live PUBLIC promotion per channel; see Promotion publishing rules.
A PUBLIC promotion that starts now and conflicts with a live PUBLIC promotion on the same channel is not rejected. The request succeeds, but the new promotion is saved as EXPIRED and ends up PRIVATE. Check status in the response, or send forceReplacePublicPromotion: true to expire the live promotion instead. For a promotion that starts later, see Promotion publishing rules.
Request body
Name | Description |
|---|---|
string | Name of the promotion, 2 to 64 characters, not starting with |
string | Who sees the promotion on the storefront: |
array of strings | Channels a PUBLIC promotion runs on: |
string or null | Start time (ISO 8601). Ignored while |
string or null | End time (ISO 8601), after |
boolean | When |
boolean | When |
string or null | Store path the promotion's link opens, starting with |
string | Used by the Abra app; leave unset. |
string | Sets the status directly ( |
array of objects | Discounts to attach, by Shopify discount ID. Fields listed under |
array of objects | Used by the Abra app; leave unset. |
discounts[]
Name | Description |
|---|---|
string, required | Shopify ID (GID) of the discount, for example |
Example request
curl -X POST "$ABRA_API_BASE/v1/partner/promotions" \
-H "Authorization: Bearer $ABRA_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Summer Sale 2026",
"visibility": "PRIVATE",
"startsAt": "2026-06-01T00:00:00.000Z",
"endsAt": "2026-08-31T23:59:59.000Z",
"useDiscountDates": true,
"discounts": [
{
"shopifyDiscountId": "gid://shopify/DiscountCodeNode/1234567890"
}
]
}'Response
201 Created. Returns the promotion in data. Its fields are listed in The promotion object.
Errors
Status | Code | Description |
|---|---|---|
|
| A field is invalid, for example a title under 2 characters or |
|
| The token is missing, expired or revoked. |
|
| A |
|
| The store has reached Shopify's metafield limit, so the promotion isn't saved. Delete unused promotions or discounts, or contact support. |
Get a promotion
GET /v1/partner/promotions/{id}
Returns one promotion with its discounts and storefront blocks. {id} is the promotion's Abra ID (its id field).
Path parameters
Name | Description |
|---|---|
string, required | The promotion ID ( |
Example request
curl "$ABRA_API_BASE/v1/partner/promotions/$PROMOTION_ID" \
-H "Authorization: Bearer $ABRA_API_TOKEN"Response
200 OK. Returns the promotion in data. Its fields are listed in The promotion object.
Errors
Status | Code | Description |
|---|---|---|
|
| The token is missing, expired or revoked. |
|
| No promotion with this ID in the store. |
Update a promotion
PUT /v1/partner/promotions/{id}
Changes the fields you send and leaves the rest as they are. Sending discounts replaces the whole list of attached discounts, and [] removes them all. If useDiscountDates is true and you send a non-empty discounts, the dates are worked out again from the new discounts.
A promotion whose end date has passed becomes EXPIRED, which also makes it PRIVATE with no channels. Changing visibility, channels and dates is how you publish, schedule or take down a promotion; see Promotion publishing rules.
forceReplacePublicPromotion has no effect here. If the promotion has started and is PUBLIC after the update, and another PUBLIC promotion is live on the same channel, the update succeeds, but the promotion is then saved as EXPIRED and PRIVATE, and the response can still show it as PUBLIC. Deactivate the live promotion or make it PRIVATE first, and get the promotion again after the update to check it.
Path parameters
Name | Description |
|---|---|
string, required | The promotion ID ( |
Request body
Name | Description |
|---|---|
string | New name, 2 to 64 characters, not starting with |
string | Who sees the promotion on the storefront: |
array of strings | Channels a PUBLIC promotion runs on: |
string or null | Start time (ISO 8601). Ignored when |
string or null | End time (ISO 8601), after |
boolean | When |
boolean | Has no effect on this endpoint. Deactivate the live PUBLIC promotion, or make it |
string or null | Store path the promotion's link opens, starting with |
string | Used by the Abra app; leave unset. |
string | Sets the status directly ( |
array of objects | Replaces the whole list of attached discounts, by Shopify discount ID. |
array of objects | Used by the Abra app; leave unset. |
Example request
curl -X PUT "$ABRA_API_BASE/v1/partner/promotions/$PROMOTION_ID" \
-H "Authorization: Bearer $ABRA_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"endsAt": "2026-09-30T23:59:59.000Z"}'Response
200 OK. Returns the promotion in data. Its fields are listed in The promotion object.
Errors
Status | Code | Description |
|---|---|---|
|
| A field is invalid. See |
|
| The token is missing, expired or revoked. |
|
| No promotion with this ID in the store. |
|
| Another request is changing this promotion. Try again. |
|
| A |
Delete a promotion
DELETE /v1/partner/promotions/{id}
Deletes the promotion and removes its storefront data from Shopify. Returns 204 with no body.
Its discounts are not deleted; they stay in Abra and Shopify. To end them as well, send the body {"deactivateAssociatedDiscounts": true}, which expires them in Shopify and Abra.
Path parameters
Name | Description |
|---|---|
string, required | The promotion ID ( |
Request body
The request body is optional.
Name | Description |
|---|---|
boolean | Also expire the promotion's discounts in Shopify and Abra. They aren't deleted. Defaults to |
Example request
curl -X DELETE "$ABRA_API_BASE/v1/partner/promotions/$PROMOTION_ID" \
-H "Authorization: Bearer $ABRA_API_TOKEN"Response
204 No Content. The response has no body.
Errors
Status | Code | Description |
|---|---|---|
|
| The token is missing, expired or revoked. |
|
| No promotion with this ID in the store. |
|
| Another request is changing this promotion. Try again. |
Deactivate a promotion
POST /v1/partner/promotions/{id}/deactivate
Ends the promotion now without deleting it. It becomes EXPIRED and PRIVATE with no channels, useDiscountDates is turned off, and its start and end dates are set to one minute before the request. Returns the updated promotion.
With deactivateAssociatedDiscounts: true in the body, its discounts are also expired in Shopify and Abra. To run the promotion again, update it with new dates and visibility.
Path parameters
Name | Description |
|---|---|
string, required | The promotion ID ( |
Request body
The request body is optional.
Name | Description |
|---|---|
boolean | Also expire the promotion's discounts in Shopify and Abra. Defaults to |
Example request
curl -X POST "$ABRA_API_BASE/v1/partner/promotions/$PROMOTION_ID/deactivate" \
-H "Authorization: Bearer $ABRA_API_TOKEN"Response
200 OK. Returns the promotion in data. Its fields are listed in The promotion object.
Errors
Status | Code | Description |
|---|---|---|
|
| The token is missing, expired or revoked. |
|
| No promotion with this ID in the store. |
|
| Another request is changing this promotion. Try again. |
Bulk update promotions
POST /v1/partner/promotions/bulk
Runs one action on several promotions, listed by Abra ID in ids. activate starts each promotion now with no end date and turns useDiscountDates off; visibility stays as it is, and a PUBLIC promotion follows the same publishing rules as an update. deactivate ends each promotion now and makes it PRIVATE with no channels. delete deletes each promotion, like Delete a promotion.
With deactivateAssociatedDiscounts: true, deactivate and delete also expire the promotions' discounts in Shopify and Abra. The response is always {"data": {"ok": 1}}.
The response doesn't say which promotions changed. IDs that aren't in the store, or that fail, are skipped without an error, so get the promotions afterwards to confirm the result.
Request body
Name | Description |
|---|---|
array of strings, required | Abra IDs of the promotions. At least 1 item. |
string, required |
|
boolean | With |
Response
200 OK. Bulk action completed.
Errors
Status | Code | Description |
|---|---|---|
|
|
|
|
| The token is missing, expired or revoked. |
This page is generated from the Abra API specification (build bc96ccc) ยท ref ce790be72c93. Edits made in Pylon are overwritten.