Canonical user journeys for the Seller API (GET /api/seller/v1/openapi). Each recipe lists scopes, call order, and idempotency so humans, agents, and generated clients stay aligned.
New to the API? Follow 30-minute quickstart first (health → partners → products → order → webhooks). For storefront call sequences, see Store integration profiles.
OpenAPI (canonical): GET /api/seller/v1/openapi (e.g. https://api.avrix.io/api/seller/v1/openapi).
Interactive docs (canonical): GET /api/seller/v1/docs on the same host.
Unversioned URLs (/api/seller/openapi, /api/seller/docs) redirect to the v1 paths; prefer the v1 URLs in new integrations.
All paths below are under /api/seller/v1/ unless noted. Prefer response field data for lists; legacy top-level keys are deprecated.
Recipe: browse-catalog#
| Field | Value |
|---|---|
| Description | Discover partners and products, then load detail and regional pricing. |
| Scopes | seller:products:read |
| Idempotency | Not applicable (GET only). |
Order of calls
- GET /partners — connected vendors (
data[]:publisherCompanyIdlegacy field name, …). - GET /products — paginate with
cursor/limit; optionalpartner,q,status,updatedSince(ISO 8601 incremental sync). - GET /products/{productId} — editions, releases, SKUs; optional
expand=base. - GET /products/{productId}/pricing — per release / country; optional
country=US,DE.
Incremental sync: Store the latest of each product’s updatedAt / createdAt (from detail or list) or the webhook product.updated payload updatedAt, then call GET /products?updatedSince=... on a schedule to fetch deltas. Full scans are optional.
Very large catalogs: Prefer partner (iterate per vendor), q, or slug to parallelize jobs. Pagination is keyset (stable pages). See Catalog sync & caching.
Recipe: check-before-pull#
| Field | Value |
|---|---|
| Description | Verify allocation + inventory headroom before pulling keys. |
| Scopes | seller:products:read (for SKU identity) and seller:keys:pull for pull endpoints. |
| Idempotency | Not applicable for GET /availability. |
Order of calls
- Obtain
skuCodeorskuIdfrom product detail (GET /products/{productId}). GET /availability?skuCode=...or?skuId=...— readdata.available,allocationRemaining,inventoryAvailable(sum ofdedicatedAvailable+sharedPoolAvailable),maxFulfillableQuantity, andbackorderEligible.- For a cart line quantity
q, add&quantity=q— usedata.canFulfillbefore enabling Pay; whencannotFullyFulfill(aliasallOrNothingWillFail) is true, POST /orders returns 409 NO_AVAILABLE_KEYS with zero keys — orders are all-or-nothing, never partial.partialFulfillmentExpectedis the deprecated name for the same boolean and does not mean partial delivery. - Optional checkout race reduction: after Order preview, call POST /orders/hold when
whoami.capabilities.checkoutHoldEnabledis true.
Recipe: pull-keys#
| Field | Value |
|---|---|
| Description | Pull keys from an allocation (non-order flow). |
| Scopes | seller:keys:pull |
| Idempotency | Required for safe retries: Idempotency-Key header on POST /keys/pull (same rules as orders). |
Order of calls
- Optional: GET /availability (recipe
check-before-pull). - POST /keys/pull with body per OpenAPI — include
Idempotency-Key(UUID or 1–64 alphanumeric characters).
Recipe: create-order#
| Field | Value |
|---|---|
| Description | Create an order and receive keys (primary purchase flow). |
| Scopes | seller:keys:pull (and typically seller:products:read to resolve SKUs). |
| Idempotency | Required: Idempotency-Key on POST /orders — retries must reuse the same key to receive the cached response. |
External stores (game shops, first-party storefronts): send a full body for reconciliation and finance evidence: orderReference, metadata, and especially integrationOrderContext (declared retail country, currency, gross/net minors). Production keys require commercial evidence fields; sandbox keys do not: see Sandbox and environments.
Order of calls
POST /orders/preview— do not charge unlesscanFulfillis true.- Optional:
POST /orders/holdthen passcheckoutHoldIdonPOST /orderswhen checkout hold is enabled (whoami.capabilities.checkoutHoldEnabled). POST /orderswithIdempotency-Keyand yourorderReference.
Recipe: pre-order#
| Field | Value |
|---|---|
| Description | Purchase a SKU that is not yet released: keys are reserved until release, then fulfilled automatically. |
| Scopes | seller:keys:pull |
| Idempotency | Idempotency-Key on POST /orders (or /orders/bulk). Idempotency-Key on POST /orders/cancel to cancel reservations safely. |
Order of calls
- Optional:
GET /availability— pre-order SKUs may show reserved paths per product rules. POST /orders— responsetype:pre-orderwhen keys are reserved (not plaintext in response).- Optional:
POST /orders/cancelwith{ "orderReference": "<your id>" }— releases reservations; webhookorder.returned. - Otherwise: wait for release —
order.preorder_fulfilled/order.fulfilledwhen keys are delivered (cron-driven unlock).
Recipe: get-order#
| Field | Value |
|---|---|
| Description | Reconcile a store order id against Avrix pulls and reservations. |
| Scopes | seller:products:read |
| Idempotency | GET only. |
Order of calls
GET /orders?orderReference=<your store order id>— aggregated lines (fulfilled pulls, active pre-order reservations).
Recipe: return-keys#
| Field | Value |
|---|---|
| Description | Return keys after fulfillment (refund/chargeback flows). See Key return policy. |
| Scopes | seller:refunds:write (legacy seller:keys:pull accepted during the deprecation window) |
| Idempotency | Idempotency-Key on POST /keys/return. |
Order of calls
POST /keys/returnwith requiredkeyIds(from the fulfilled order response ororder.fulfilledwebhook) and optionalreason. The body does not acceptorderReference.- Alternatively
POST /refundswithtype,refundReferenceand eitherkeyIdsorquantity+orderReference— the latter quarantines the newestquantitylive keys sold under that reference (partial refunds without tracking key ids by position).
Recipe: recover-keys#
| Field | Value |
|---|---|
| Description | Your store lost the POST /orders response (crash between the pull and your own database write) and needs the keys it already paid for. |
| Scopes | seller:keys:pull (or seller:orders:write) |
| Idempotency | Not required — the call never pulls new inventory; every call is audited as a key reveal. |
Order of calls
GET /orders?orderReference=<your store order id>— confirmsstatus: "fulfilled"(never returns plaintext).POST /orders/recover-keys{ "orderReference": "<your store order id>" }— returns the livekeysandkeyIdssold under that reference. Returned / refunded keys are excluded;404 NOT_FOUNDmeans nothing is live under the reference.- Re-posting
POST /orderswith the sameorderReferenceand the same quantity replays the same keys as well (documented idempotent replay); preferrecover-keysbecause it needs no price binding.
Recipe: list-history#
| Field | Value |
|---|---|
| Description | Audit key pulls and orders via transactions. |
| Scopes | seller:products:read |
| Idempotency | GET only. |
Order of calls
GET /transactions— paginate withcursor, filterorderReference,from,toas needed (one row per key pulled).
Recipe: promotions#
| Field | Value |
|---|---|
| Description | Review and respond to platform shares and custom deals. |
| Scopes | seller:promotions:read for GET; seller:promotions:respond for accept / decline / respond. |
| Idempotency | POST accept/decline/respond — use unique logical operations; confirm idempotency in OpenAPI per operation if added later. |
Order of calls
GET /promotions/summaryGET /promotions/shares→GET /promotions/shares/{shareId}→POST .../acceptor.../declineGET /promotions/deals→GET /promotions/deals/{responseId}→POST .../respond
Recipe: webhooks#
| Field | Value |
|---|---|
| Description | Register HTTPS endpoints for Seller API events. |
| Scopes | seller:webhooks:read, seller:webhooks:write |
| Idempotency | Not specified for webhook CRUD; use unique URLs per endpoint. |
Order of calls
GET /webhooksPOST /webhooksto createDELETE /webhooks/{id}to remove
Optional
POST /webhooks/{id}/test— queue atest.pingdelivery to verify URL + signature.PATCH /webhooks/{id}— updateurl/events, orrotateSecret: truefor a new signing secret.POST /webhooks/{id}/enable— re-enable after automatic disable (circuit breaker).POST /webhooks/{id}/deliveries/{deliveryId}/retry— retry a failed delivery.
Recipe: usage#
| Field | Value |
|---|---|
| Description | Aggregate API call counts from audit logs (per endpoint, errors). |
| Scopes | seller:products:read |
| Idempotency | GET only. |
Order of calls
GET /usage?from=...&to=...(ISO 8601 UTC; defaults to last 7 days).
Recipe: manage-api-keys#
| Field | Value |
|---|---|
| Description | List, create, or revoke seller API keys via the API. |
| Scopes | seller:keys:write on the calling key |
| Idempotency | Follow OpenAPI for POST /keys; protect create with your own deduplication if needed. |
Order of calls
GET /keysPOST /keys/DELETE /keys/{id}
Create behavior (POST /keys)
- Body:
name(required), optionalallowed_ips(string array), optionalincludeFinanceScope. - New keys receive the server default scope set intersected with the calling key’s scopes (children never exceed the parent ceiling). See API key management.
Generated TypeScript client#
Prefer a typed client generated from OpenAPI, or plain fetch. See Client & helpers.
Related#
- Order preview — read-only checkout estimate before
POST /orders - Catalog sync & caching — snapshot + allocations sync pattern
- Webhooks — push-first fulfillment and catalog deltas
- 30-minute quickstart — end-to-end golden path through these recipes
- SDK & helpers — generated TypeScript client and transport helpers