Offer

The Offer object represents a purchasable pricing option for a product.

An Offer object represents a specific pricing configuration for a Product that customers can purchase. Offers define the price, currency, region availability, and subscription terms (if applicable).

A single Product can have multiple offers to support different regions, currencies, or pricing tiers. Offers can include product keys for digital goods that are automatically delivered upon purchase. Discounts can be applied to offers to reduce the price.

Endpoints

MethodEndpointDescription
GET/v0/offers/listList and filter offers
POST/v0/offers/createCreate a new offer
GET/v0/offers/{offerId}Retrieve an offer
PATCH/v0/offers/{offerId}/updateUpdate an offer
PATCH/v0/offers/{offerId}/archiveArchive an offer
POST/v0/offers/{offerId}/keys/addAdd product keys
DELETE/v0/offers/{offerId}/keys/removeAllUnsoldRemove every unsold key
DELETE/v0/offers/{offerId}/keys/{keyId}/removeUnsoldRemove one unsold key

Showing a price with tax

An offer's price is the pre-tax amount. To display a gross price on a product page, quote it with POST /v0/tax/calculate — pass the offerId, a quantity, and the customer's country (plus state for accurate US/CA rates). You get back amountSubtotal, amountTax, amountTotal and a taxBreakdown, all in the smallest currency unit.

For business buyers, send customerType: "company" with taxId and taxNumber. The VAT-ID is checked against the EU VIES registry and the quote matches what checkout will charge — a verified EU VAT-ID returns 0% (reverse charge), anything else returns the standard destination rate. vatVerification tells you which happened and why. Read amountTax to know what will be charged, not reverseChargeEligible, which only says the destination offers reverse charge at all.

The result is a quote, not a settled charge — the authoritative tax is recomputed at checkout from full billing details.

Full reference: Calculate product price including tax.

The Offer object

objectstring

Object type identifier. Always "offer" for Offer objects.

idstringrequired

Unique identifier (UUID) for this offer.

internalIdstring | null

Your custom identifier for this offer. Use to link to your own SKU system.

namestring | null

Display name of the offer (e.g., "Standard Edition", "Premium Bundle").

descriptionstring | null

Description of what's included in this offer.

pricenumberrequired

Price in the smallest currency unit — 5999 is $59.99, not 59.99. For Subscriptions, this is the recurring price.

Responses return minor units, but create and update take the price as a decimal amount (59.99). Divide by the currency's decimal places when reading, multiply when writing. Zero-decimal currencies such as JPY have no conversion: 1999 is ¥1999 in both directions. A non-free price below the currency's smallest unit — under 0.01 for USD/PLN, under 1 for JPY, under 0.001 for three-decimal currencies — is rejected. Prices are stored in whole minor units, so a smaller amount cannot be represented.

originalPricenumber | null

Original price before any discount, in the smallest currency unit. Used to show strikethrough pricing. Same input/output asymmetry as price above: sent as a decimal amount, returned in minor units. Subject to the same currency-minimum rejection described for price above.

currencystringrequired

Three-letter ISO 4217 currency code (e.g., "USD", "EUR", "GBP").

statusstringrequired

Current offer status. Possible values: DRAFT, OPEN, CLOSED, SOLD. An offer created through the API is always OPEN — there is no publish step. DRAFT only comes from the dashboard.

limitinteger | null

Maximum number of units that can be sold. null means unlimited.

soldItemsinteger

Units sold so far. Compare against limit to know what is left. Defaults to 0.

regionstring | null

Geographic region this offer is restricted to. Common values: Global, Europe, United States, United Kingdom, North America, Latin America, Asia, EMEA, Rest of the World. null means no restriction — the offer is sold in every region.

platformstring | null

Platform for digital product activation. Common values: Steam, Xbox Live, PSN, Nintendo, Epic Games, GOG.com, Origin, Battle.net, Ubisoft Connect

gtinstring | null

Global Trade Item Number (barcode) for the product.

warningMessagestring | null

Warning or disclaimer message to display to customers.

recurringIntervalstring | null

Billing interval for Subscriptions. Possible values: day, week, month, year

recurringIntervalCountinteger | null

Number of intervals between billings. For example, 3 with month interval means billing every 3 months.

trialIntervalstring | null

Trial period interval type. Possible values: day, week, month, year

trialIntervalCountinteger | null

Number of intervals for the trial period. For example, 14 with day interval means a 14-day trial.


Example response

{
  "status": "success",
  "data": {
    "offer": {
      "object": "offer",
      "id": "990e8400-e29b-41d4-a716-446655440004",
      "internalId": "sku_standard_us",
      "name": "Standard Edition",
      "description": "Base game with all launch content",
      "price": 5999,
      "originalPrice": 6999,
      "currency": "USD",
      "status": "OPEN",
      "limit": 500,
      "soldItems": 137,
      "region": "United States",
      "platform": "Steam",
      "gtin": "1234567890123",
      "warningMessage": null,
      "recurringInterval": null,
      "recurringIntervalCount": null,
      "trialInterval": null,
      "trialIntervalCount": null
    }
  }
}

Subscription offer example

{
  "status": "success",
  "data": {
    "offer": {
      "object": "offer",
      "id": "aa0e8400-e29b-41d4-a716-446655440005",
      "internalId": "plan_pro_monthly",
      "name": "Pro Plan - Monthly",
      "description": "Full access to all features",
      "price": 2999,
      "originalPrice": null,
      "currency": "USD",
      "status": "OPEN",
      "limit": null,
      "soldItems": 42,
      "region": "Global",
      "platform": null,
      "gtin": null,
      "warningMessage": null,
      "recurringInterval": "month",
      "recurringIntervalCount": 1,
      "trialInterval": "day",
      "trialIntervalCount": 14
    }
  }
}

Last updated