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 area–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. UsePOST /v4/offerings/{offering_id}/set-mainto switch the main — it atomically clears the previous main inside a single transaction.tag=1onPOST /offeringsandPATCH /offerings/{id}is rejected with400(typed codecannot_set_main_directly). To make an offering the project’s main, create or patch it withouttagand callPOST /offerings/{id}/set-mainafterward — that endpoint flips the main flag atomically. Patching the project’s current main offering withtag: 0(or any non-main value) is rejected with422(typed codecannot_demote_main). To switch which offering is main, callPOST /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. Treat0andnullas equivalent on read. Tag is read-only viaPATCH; useset-mainto promote andset-mainon a different offering to implicitly demote the current main. OnPOSTonly0andnullare accepted (andtag=1is rejected as above). The very first offering created in an empty project is auto-promoted totag: 1even iftagis omitted in the request. - Experiment-variant offerings — Offerings owned by the experiments service are excluded from
GET /offeringsand return404fromGET /offerings/{offering_id}.PATCH,DELETE, andset-mainon an experiment-variant id return422with typed codescannot_patch_experiment_variant,cannot_delete_experiment_variant, andcannot_setmain_experiment_variantrespectively.
Offering object
| Field | Type | Description |
|---|---|---|
object | string | Always offering. |
id | string | Offering identifier. |
url | string | Canonical API path (/v4/offerings/{id}). |
tag | integer | null | 1 = main, 0 or null = regular. |
product_ids | string[] | Product UIDs in display order. |
created_at | string | ISO 8601 UTC creation timestamp. |
updated_at | string | ISO 8601 UTC last-update timestamp. |
Available endpoints
| Method | Endpoint | Description | Status |
|---|---|---|---|
| GET | /offerings | List offerings | New |
| POST | /offerings | Create an offering | New |
| GET | /offerings/{offering_id} | Get an offering | New |
| PATCH | /offerings/{offering_id} | Update an offering (partial) | New |
| DELETE | /offerings/{offering_id} | Delete an offering | New |
| POST | /offerings/{offering_id}/set-main | Mark this offering as the project’s main offering | New |
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.| Code | HTTP | Description |
|---|---|---|
not_found | 404 | Offering does not exist in this project, or the id belongs to an experiment-variant offering filtered out by GET. |
offering_already_exists | 409 | POST /offerings was called with an id that already exists in this project. |
product_not_in_project | 400 | product_ids references a product UID that is not registered in the project. |
cannot_set_main_directly | 400 | tag: 1 was sent on POST /offerings or PATCH /offerings/{id}. Call POST /offerings/{id}/set-main instead. |
cannot_demote_main | 422 | PATCH /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_variant | 422 | PATCH /offerings/{id} was called against an offering owned by the experiments service. |
cannot_delete_experiment_variant | 422 | DELETE /offerings/{id} was called against an offering owned by the experiments service. |
cannot_setmain_experiment_variant | 422 | POST /offerings/{id}/set-main was called against an offering owned by the experiments service. |