Skip to main content
An Offering is a named bundle of products that the SDK consumes to render a paywall or purchase flow. Offerings decouple the products a user sees from the product IDs in your app code — you can change the contents of an offering without shipping a new build. At most one offering per project is marked as the main offering and is returned to the SDK by default when no specific id is requested.

Key concepts

  • Offering ID — Stable identifier you choose (e.g., onboarding, winback). Used in the API path and in related resources (experiments, scheduled reports). Up to 64 characters; allowed characters are a–z, A–Z, 0–9, ., _, -, :, and spaces. Immutable after create.
  • Products — An ordered list of product UIDs attached to the offering. The SDK renders them in the order you define. Each UID must already exist in the same project; product UIDs are up to 255 characters from the same charset as offering ids.
  • Main offering — At most one offering per project carries tag: 1. Use POST /v4/offerings/{offering_id}/set-main to switch the main — it atomically clears the previous main inside a single transaction. tag=1 on POST /offerings and PATCH /offerings/{id} is rejected with 400 (typed code cannot_set_main_directly). To make an offering the project’s main, create or patch it without tag and call POST /offerings/{id}/set-main afterward — that endpoint flips the main flag atomically. Patching the project’s current main offering with tag: 0 (or any non-main value) is rejected with 422 (typed code cannot_demote_main). To switch which offering is main, call POST /offerings/{new-main-id}/set-main — the previous main is cleared in the same transaction.
  • Tag — On read: 1 = main offering, 0 = regular offering previously demoted from main, null = regular offering that has never been tagged. Treat 0 and null as equivalent on read. Tag is read-only via PATCH; use set-main to promote and set-main on a different offering to implicitly demote the current main. On POST only 0 and null are accepted (and tag=1 is rejected as above). The very first offering created in an empty project is auto-promoted to tag: 1 even if tag is omitted in the request.
  • Experiment-variant offerings — Offerings owned by the experiments service are excluded from GET /offerings and return 404 from GET /offerings/{offering_id}. PATCH, DELETE, and set-main on an experiment-variant id return 422 with typed codes cannot_patch_experiment_variant, cannot_delete_experiment_variant, and cannot_setmain_experiment_variant respectively.

Offering object

FieldTypeDescription
objectstringAlways offering.
idstringOffering identifier.
urlstringCanonical API path (/v4/offerings/{id}).
taginteger | null1 = main, 0 or null = regular.
product_idsstring[]Product UIDs in display order.
created_atstringISO 8601 UTC creation timestamp.
updated_atstringISO 8601 UTC last-update timestamp.

Available endpoints

MethodEndpointDescriptionStatus
GET/offeringsList offeringsNew
POST/offeringsCreate an offeringNew
GET/offerings/{offering_id}Get an offeringNew
PATCH/offerings/{offering_id}Update an offering (partial)New
DELETE/offerings/{offering_id}Delete an offeringNew
POST/offerings/{offering_id}/set-mainMark this offering as the project’s main offeringNew
PATCH replaces product_ids with the supplied list — pass [] to detach all products, or omit the field to leave the list unchanged.

Authentication

All v4 endpoints require a Secret Key. See Authentication.

Errors

The Offerings API follows the standard error envelope and codes documented on Handling Errors.
CodeHTTPDescription
not_found404Offering does not exist in this project, or the id belongs to an experiment-variant offering filtered out by GET.
offering_already_exists409POST /offerings was called with an id that already exists in this project.
product_not_in_project400product_ids references a product UID that is not registered in the project.
cannot_set_main_directly400tag: 1 was sent on POST /offerings or PATCH /offerings/{id}. Call POST /offerings/{id}/set-main instead.
cannot_demote_main422PATCH /offerings/{id} tried to set tag: 0 (or any non-main value) on the project’s current main offering. Promote a different offering via set-main to switch instead.
cannot_patch_experiment_variant422PATCH /offerings/{id} was called against an offering owned by the experiments service.
cannot_delete_experiment_variant422DELETE /offerings/{id} was called against an offering owned by the experiments service.
cannot_setmain_experiment_variant422POST /offerings/{id}/set-main was called against an offering owned by the experiments service.