Instantiate recipe (idempotent apply)
const url = 'http://localhost:8080/v1/recipes/example/instantiate';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"overrides":{}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url http://localhost:8080/v1/recipes/example/instantiate \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "overrides": {} }'Applies the recipe for the tenant under one transaction: meters are adopted-or-created, a fresh born-unique plan is generated with the recipe’s prices, then the install badge written. It creates nothing else: no dunning policy and no webhook endpoint. Adopting a meter other plans price changes none of their prices. Idempotent per (tenant, livemode): re-posting a recipe that is installed returns the EXISTING instance with 201 and creates nothing (ADR-085; badge livemode-scoped per m0157). Two installs that run at the same time can conflict: the second gets a 409 and installs nothing. A retry returns the first install, or, for another recipe, reuses the meter it made.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Header Parameters
Section titled “Header Parameters”Makes the call safe to retry. Send a unique value (a UUID works) and
the same value on every retry. For 24 hours, a repeat with the same
key, method, path and body gets the first response again, with an
Idempotent-Replayed: true header, instead of running again. The
error cases are in docs/api-surface.md. The usage routes do not take
it: each usage event carries its own idempotency_key.
Request Body
Section titled “Request Body”object
object
Example generated
{ "overrides": {}}Responses
Section titled “Responses”Install badge (fresh, or existing on idempotent re-apply)
The install badge: the record of a recipe being applied for a tenant (scoped per livemode since m0157). Field names are recipe_key / recipe_version — NOT key/version, which the recipe template itself uses.
object
Omitted when empty.
object
Per-role map of entity IDs a recipe apply produced (including ADOPTED meters — apply reconnects to an existing meter rather than duplicating it, ADR-085). Every field is omitted when empty; clients must guard reads.
object
Operator email or API key ID. Omitted when empty.
Example generated
{ "id": "example", "tenant_id": "example", "recipe_key": "example", "recipe_version": "example", "overrides": {}, "created_objects": { "meter_ids": [ "example" ], "plan_ids": [ "example" ], "price_ids": [ "example" ] }, "created_at": "2026-04-15T12:00:00Z", "created_by": "example"}Unknown recipe key
Nothing is installed. Either a meter with the recipe’s event_name has another aggregation, so the recipe cannot use it, or another install that ran at the same time created the meter, the plan code or this recipe’s install first (retry).
Overrides failed the recipe’s overridable schema