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

id

string

Abra ID of the promotion. Use it in {id} paths.

title

string

Name of the promotion.

slug

string or null

URL-friendly form of the title, used in the promotion's Abra link.

landingPath

string or null

Store path the promotion's link opens, or null.

origin

string

Where the promotion comes from: ABRA, or an integration (SOCIAL_SNOWBALL, ROSTER).

status

string

ACTIVE (running), SCHEDULED (starts later), EXPIRED (ended) or RESTRICTED.

visibility

string

PUBLIC, PRIVATE, or TAG- followed by customer tags.

startsAt

string or null

Start time (ISO 8601), or null.

endsAt

string or null

End time (ISO 8601), or null for no end date.

useDiscountDates

boolean

Whether the dates come from the attached discounts.

publicTargets

array of strings or null

Channels of a PUBLIC promotion. null or empty counts as onlineStore and tapcart. Each value is one of onlineStore, tapcart or pos.

url

string or null

List results only: the promotion's storefront link. For a PUBLIC promotion it has abraclear=1; otherwise it has abralink set to the slug. null in other responses, and when Abra doesn't know the store's domain.

previewUrl

string or null

List results only: for a promotion that isn't PUBLIC, the same link with a preview_theme_id parameter when Abra knows the store's theme. For a PUBLIC promotion it's the same as url. null in other responses, and when Abra doesn't know the store's domain.

discounts

array of objects

Attached discounts. List results leave out each discount's discountValue. Fields listed under discounts[] below.

blockGroups

array of objects

Storefront blocks of the promotion, set up in the Abra app. Left out of list results.

createdAt

string

When the promotion was created (ISO 8601).

updatedAt

string

When the promotion last changed (ISO 8601).

discounts[]

Name

Description

id

string

Abra ID of the discount.

title

string

Title of the discount.

discountClass

string

PRODUCT, ORDER or SHIPPING.

typeName

string or null

How the discount applies, for example DiscountCodeApp or DiscountAutomaticApp.

discountValueType

string or null

The discount's discountValue.type.

discountValue

object or null

The discount's settings; see Abra API: Discount types. Left out of list results. One of 13 shapes, chosen by type.

status

string

ACTIVE, SCHEDULED or EXPIRED.

startsAt

string or null

Start time (ISO 8601), or null.

endsAt

string or null

End time (ISO 8601), or null.

shopifyDiscountId

string or null

Shopify ID (GID) of the discount.

managedBy

string

ABRA for discounts on Abra's functions, SHOPIFY for attached native discounts.

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

page

integer

The page to return. The first page is 1. Defaults to 1.

limit

integer

The number of promotions per page. Between 1 and 100. Defaults to 25.

status

string

Comma-separated list of statuses. Matches promotions whose status is in the set. Each value is one of ACTIVE, EXPIRED, SCHEDULED or RESTRICTED.

visibility

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.

search

string

Returns only promotions whose title contains this text. The match is not case-sensitive.

sort

string

The sort order, as field:direction. field is createdAt, updatedAt, title or status. direction is asc or desc, and is desc when you leave it out. Defaults to createdAt:desc.

discountId

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

page

number

Current page number.

limit

number

Number of items per page.

total

number

Total number of items.

totalPages

number

Total number of pages.

hasNextPage

boolean

Whether there is a next page.

hasPreviousPage

boolean

Whether there is a previous page.

Errors

Status

Code

Description

400

VALIDATION_FAILED

A query value is invalid, for example limit above 100 or an unknown status. See issues.

400

SORT_FIELD_INVALID

sort uses a field that can't be sorted on.

400

SORT_DIRECTION_INVALID

The sort direction isn't asc or desc.

401

UNAUTHORIZED

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

title

string

Name of the promotion, 2 to 64 characters, not starting with TAG-. Defaults to the first discount's title, or an Untitled- code. A number is added if the title is already used in the store.

visibility

string

Who sees the promotion on the storefront: PUBLIC (every visitor), PRIVATE (shoppers who open its Abra link) or TAG- followed by comma-separated Shopify customer tags (logged-in customers with those tags). Defaults to PRIVATE.

publicTargets

array of strings

Channels a PUBLIC promotion runs on: onlineStore, tapcart and pos. Empty or unset counts as onlineStore and tapcart. A store can have one live PUBLIC promotion per channel.

startsAt

string or null

Start time (ISO 8601). Ignored while useDiscountDates is true.

endsAt

string or null

End time (ISO 8601), after startsAt. null means no end date. Ignored while useDiscountDates is true.

useDiscountDates

boolean

When true (the default), the promotion runs from the earliest start among its discounts that haven't ended to the latest end, with no end date if any discount has none. Without discounts, it starts now. Set it to false to use startsAt and endsAt; without a startsAt, the promotion is saved as EXPIRED.

forceReplacePublicPromotion

boolean

When true, any PUBLIC promotion live on the same channel is expired so this one can go live. It only has an effect when the promotion is PUBLIC and starts now. Defaults to false. Update a promotion (PUT) ignores it.

landingPath

string or null

Store path the promotion's link opens, starting with /, up to 255 characters, for example /summer-sale. null clears it.

origin

string

Used by the Abra app; leave unset.

status

string

Sets the status directly (ACTIVE, EXPIRED or SCHEDULED) instead of working it out from the dates. Usually left unset.

discounts

array of objects

Discounts to attach, by Shopify discount ID. Fields listed under discounts[] below.

blockGroups

array of objects

Used by the Abra app; leave unset.

discounts[]

Name

Description

shopifyDiscountId

string, required

Shopify ID (GID) of the discount, for example gid://shopify/DiscountCodeNode/123: the shopifyDiscountId of a discount from this API, or a discount made in Shopify.

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

400

VALIDATION_FAILED

A field is invalid, for example a title under 2 characters or endsAt before startsAt. See issues.

401

UNAUTHORIZED

The token is missing, expired or revoked.

422

DISCOUNT_NOT_RESOLVABLE

A discounts[].shopifyDiscountId isn't a discount in the store's Shopify, is a kind Abra can't attach, or couldn't be looked up in Shopify.

422

UNPROCESSABLE_ENTITY

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

id

string, required

The promotion ID (id in the promotion object).

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

401

UNAUTHORIZED

The token is missing, expired or revoked.

404

NOT_FOUND

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

id

string, required

The promotion ID (id in the promotion object).

Request body

Name

Description

title

string

New name, 2 to 64 characters, not starting with TAG-.

visibility

string

Who sees the promotion on the storefront: PUBLIC (every visitor), PRIVATE (shoppers who open its Abra link) or TAG- followed by comma-separated Shopify customer tags (logged-in customers with those tags).

publicTargets

array of strings

Channels a PUBLIC promotion runs on: onlineStore, tapcart and pos. Empty or unset counts as onlineStore and tapcart. A store can have one live PUBLIC promotion per channel.

startsAt

string or null

Start time (ISO 8601). Ignored when useDiscountDates is true and you also send a non-empty discounts.

endsAt

string or null

End time (ISO 8601), after startsAt. null removes the end date. Ignored when useDiscountDates is true and you also send a non-empty discounts.

useDiscountDates

boolean

When true and you send a non-empty discounts in the same request, the dates are worked out from those discounts: the earliest start and the latest end, with no end date if any discount has none. Sent as true without discounts, it keeps the current start date and removes the end date. Set it to false to use startsAt and endsAt.

forceReplacePublicPromotion

boolean

Has no effect on this endpoint. Deactivate the live PUBLIC promotion, or make it PRIVATE, first.

landingPath

string or null

Store path the promotion's link opens, starting with /, up to 255 characters, for example /summer-sale. null clears it.

origin

string

Used by the Abra app; leave unset.

status

string

Sets the status directly (ACTIVE, EXPIRED or SCHEDULED) instead of working it out from the dates. Usually left unset.

discounts

array of objects

Replaces the whole list of attached discounts, by Shopify discount ID. [] removes them all. Same fields as discounts[] in Create a promotion.

blockGroups

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

400

VALIDATION_FAILED

A field is invalid. See issues.

401

UNAUTHORIZED

The token is missing, expired or revoked.

404

NOT_FOUND

No promotion with this ID in the store.

409

CONFLICT

Another request is changing this promotion. Try again.

422

DISCOUNT_NOT_RESOLVABLE

A discounts[].shopifyDiscountId isn't a discount in the store's Shopify, is a kind Abra can't attach, or couldn't be looked up in Shopify.

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

id

string, required

The promotion ID (id in the promotion object).

Request body

The request body is optional.

Name

Description

deactivateAssociatedDiscounts

boolean

Also expire the promotion's discounts in Shopify and Abra. They aren't deleted. Defaults to false.

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

401

UNAUTHORIZED

The token is missing, expired or revoked.

404

NOT_FOUND

No promotion with this ID in the store.

409

CONFLICT

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

id

string, required

The promotion ID (id in the promotion object).

Request body

The request body is optional.

Name

Description

deactivateAssociatedDiscounts

boolean

Also expire the promotion's discounts in Shopify and Abra. Defaults to false.

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

401

UNAUTHORIZED

The token is missing, expired or revoked.

404

NOT_FOUND

No promotion with this ID in the store.

409

CONFLICT

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

ids

array of strings, required

Abra IDs of the promotions. At least 1 item.

action

string, required

activate, deactivate or delete.

deactivateAssociatedDiscounts

boolean

With deactivate or delete, also expire the promotions' discounts in Shopify and Abra. Defaults to false.

Response

200 OK. Bulk action completed.

Errors

Status

Code

Description

400

VALIDATION_FAILED

ids is empty or action isn't activate, deactivate or delete. See issues.

401

UNAUTHORIZED

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.