Skip to main content
Use the Developer Platform promotions endpoints to manage central promotions, product assignments, and marketplace delivery. Semantics match the workspace Promotions UI (/app/{organizationId}/promotions).

Authentication

Send an OmniCommerce API key or OAuth client-credentials token:
OAuth clients must include the scope on the client. API keys created from organization settings receive all developer scopes by default. Session-authenticated calls must include organizationId in the query (GET) or JSON body (writes). OpenAPI reference: API reference · Spec: openapi.json

List promotions

Query parameters

Response

Each list item includes promotion fields plus:
  • effectiveStatus — status resolved from schedule windows
  • syncMeta — aggregated marketplace sync (lastSyncedAt, pending/failed/synced/applied/skipped counts). appliedCount includes only confirmed rows with a marketplace campaign reference.

Create promotion

Request body

For gift_with_purchase, set discountValue to 0 for a gift/sample-only offer or provide a positive value for Lazada Combo Buy. Use mechanicConfig.giftType (gift or sample), giftQuantity, the purchase threshold, and gifts[]. Lazada maps these to Flexicombo. Its eight supported wire modes are money off, percentage off, free gift, free sample, and each discount type combined with either a gift or sample. Free buy_x_get_y benefits also map to Lazada Flexicombo. Percentage- or fixed-discount benefit SKUs do not: Lazada Combo Buy discounts the qualifying order rather than the benefit SKU, so OmniCommerce reports that store as failed instead of changing the promotion’s meaning. New promotions default to active; a future start date displays as scheduled. Pass status: "draft" to save without activation. Explicit paused, ended, and archived states remain inactive. Returns 201 with { "promotion": { ... } }.

Get / update / delete

Update accepts partial fields (name, discountType, discountValue, targetStores, storeDiscounts, schedule, status, guardrails). Partial mechanicConfig updates preserve its other fields. To change only one store’s discount, use its exact connected store key:
This preserves the shared discount and every other store’s override. Set an entry’s discountValue to null to return that store to shared terms. A store must already be a campaign target (or be included in the same targetStores update). An empty array makes no changes. At most 100 distinct store keys may be supplied. Fixed amounts use the campaign’s currency. The assistant’s manage_promotions update also accepts removeProductIds with the terms and schedule. It commits these changes together for each campaign and queues marketplace synchronization after the commit. Use promotionIds for shared changes or updates[] for different changes per campaign. Each batch supports up to 50 campaigns and reports individual successes and failures. bundle_deal represents a quantity-based buy-together discount on assigned products; it does not create a combined product listing. Eligible quantities may include repeated units of the same product. An exact “one A plus one B” requirement needs a marketplace mechanic that enforces those distinct items.

Assign products

Assigning products to an active or scheduled promotion delivers them to the marketplaces automatically. A draft promotion delivers when you activate it. productDiscounts is optional. Each entry sets that product’s own percentage or fixed amount, using the campaign discount type. discountValue: null returns the product to the shared campaign discount. Omit a product to leave its current discount unchanged. Only product discounts and flash sales accept this. Shopee and TikTok publish the resulting promotional price for each product. Lazada vouchers and Shopify discounts use one amount for every product, so sync fails for those stores while any product has its own discount. A product’s own discount replaces any store discount for that product. Changing the promotion’s discount type, or changing it to a mechanic without a price, is rejected until those product discounts are cleared.
Lists current assignments.
Unassigns products and queues marketplace teardown.

Marketplace delivery

Promotions reach the marketplaces automatically. You never need a separate sync call:
  • Creating a promotion as active or scheduled, or changing its status to either, delivers it.
  • Editing an active or scheduled promotion, or assigning or removing products, delivers the change.
  • Changing status to paused, ended, or archived removes it from the marketplaces.
Check the result in the promotion’s syncMeta and delivery status.

Retry a failed delivery

Use this after a delivery failed, for example once a store is reconnected or a product is published. It brings each marketplace back in line with the promotion’s current status. Both fields are optional:
  • marketplace: retry one marketplace. Omit it to retry every promotion marketplace.
  • productIds: retry only these products. Omit it to retry every assigned product.
Returns 202:

Marketplace mapping

Products only sync to marketplaces they are published on. Other target rows are marked skipped. Imported Shopee seller vouchers are managed in Shopee Seller Centre. Importing promotions reads supported product-specific voucher codes, eligibility, minimum spend, caps, and schedules; repeat imports refresh these terms. These imported vouchers cannot be edited or pushed back from Omni. Shop-wide, affiliate, cashback, and unsupported restricted offers are excluded. Voucher redemption does not replace a product’s sale price. Marketplace selection expresses intent, not proof of delivery. Check the promotion detail delivery status after it is delivered. Applied requires a successful sync row with a marketplace campaign ID; unsupported, read-only, permission, validation, and partial-failure outcomes retain the exact reason.

Example flow