Freeport Seller API
Version 2026-09-09 · openapi.json
One API for every lane and every kind of seller software.
Send your key as Authorization: Bearer fp_live_…. Money is a decimal string in the row's currency, ids are prefixed ULIDs, times are ISO 8601 UTC. Every response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset; a 429 carries Retry-After. Errors are { "error": { "code", "message", "requestId" } }.
Conventions
Scopes
A key carries the scopes it was minted with. Every route names the one it needs; a key without it gets a 403 with the scope in the body.
catalog:readlistings:readlistings:writeorders:readorders:writechat:readchat:writeaccount:readaccount:writewebhooks:manage
Rate limits
Per key, per minute, sliding. New sellers get the base budget, standard sellers twice it, trusted sellers three times. Every response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset; a 429 carries Retry-After.
| Bucket | Base per minute |
reads | 600 |
writes | 120 |
bulk | 20 |
chat | 30 |
Idempotency
Send Idempotency-Key on any write you might retry. The same key with the same request replays the first answer for a day with Idempotent-Replayed: true; the same key with a different request is refused with idempotency_key_reused.
Errors
Every refusal is { "error": { "code", "message", "requestId" } }. The code is stable and worth switching on; the message is for a person; the request id is what to quote to support.
Account
The seller behind the key.
GET /v1/me/balance
Your balance
Summed from the ledger, never stored: what is spendable now, and what is still held while orders complete and the payout hold runs.
Scope account:read. Spends the reads budget (600 a minute for a new seller).
scope account:readbucket reads
Responses
| Status | Meaning | Body |
200 | The balance | Balance |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/fees/quote
What an order would cost
Priced by the same resolver as checkout. The seller side is exact; the buyer side leaves out the first-order waiver, since which buyer is unknown. A tool pricing across marketplaces wants this before it lists, not after the first sale.
Any key. Spends the reads budget (600 a minute for a new seller).
bucket reads
Query
| Name | Type | Required | Notes |
category | currency · item · account · service · topup · giftcard | yes | |
subtotal | string | yes | |
currency | string | | |
game | string | | |
Responses
| Status | Meaning | Body |
200 | The quote | FeeQuote |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/me
The seller behind the key
Scope account:read. Spends the reads budget (600 a minute for a new seller).
scope account:readbucket reads
Responses
| Status | Meaning | Body |
200 | The seller | Me |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
PATCH /v1/me
Holiday mode on or off
Holiday mode hides every listing at once: the switch a farm flips when the deliverers go home.
Scope account:write. Spends the writes budget (120 a minute for a new seller).
scope account:writebucket writesidempotency key
Body
| Field | Type | Required | Notes |
holiday_mode | boolean | | |
presence | online · offline | | |
Responses
| Status | Meaning | Body |
200 | The seller, after the change | Me |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
Catalog
Games, lanes, realms and packages, by id and slug.
GET /v1/catalog/games
Every active game
Any key. Spends the reads budget (600 a minute for a new seller).
bucket readsETag
Responses
| Status | Meaning | Body |
200 | Games, most popular first | object |
304 | Unchanged since the ETag you sent | |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/catalog/games/{slug}
One game: lanes, realms with faction, packages, vocabulary
Any key. Spends the reads budget (600 a minute for a new seller).
bucket readsETag
Responses
| Status | Meaning | Body |
200 | The game | GameDetail |
304 | Unchanged | |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/catalog/resolve
Your names to our ids
Ranks games, categories and servers against the names you keep. A named faction is decisive on a realm. Never creates anything.
Any key. Spends the reads budget (600 a minute for a new seller).
bucket reads
Body
| Field | Type | Required | Notes |
game | string | yes | |
category | string | | |
server | string | | |
faction | string | | |
Responses
| Status | Meaning | Body |
200 | Up to five candidates each, best first | Resolution |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/catalog/changes
Games, lanes, realms and packages added or renamed since a moment
Any key. Spends the reads budget (600 a minute for a new seller).
bucket reads
Query
| Name | Type | Required | Notes |
since | string (date-time) | yes | |
limit | integer | | |
Responses
| Status | Meaning | Body |
200 | Oldest first | CatalogChanges |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
Listings
Your stock on the shelf.
GET /v1/listings
Your listings
Scope listings:read. Spends the reads budget (600 a minute for a new seller).
scope listings:readbucket reads
Query
| Name | Type | Required | Notes |
status | draft · active · paused · removed | | |
game | string | | |
external_id | string | | |
cursor | string | | |
limit | integer | | |
Responses
| Status | Meaning | Body |
200 | Newest change first | object |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/listings
Create a listing
Game, category, server and package by our id or our slug. The title is generated when absent.
Scope listings:write. Spends the writes budget (120 a minute for a new seller).
scope listings:writebucket writesidempotency key
Body
| Field | Type | Required | Notes |
game | string | yes | |
category | string | yes | |
server | string | | |
package | string | | |
title | string | | |
tiers | array of object | | fields| Field | Type | Required | Notes |
min_qty | integer | yes | | price | string | yes | |
|
description | string | | |
price | string | yes | |
currency | string | | |
unit_label | string | | |
price_per_qty | integer | | |
min_qty | integer | | |
max_qty | integer | | |
stock_qty | integer | | |
low_stock_alert_qty | integer | | |
delivery_eta_minutes | integer | | |
attributes | map of string | | |
external_id | string | | |
status | draft · active | | |
Responses
| Status | Meaning | Body |
201 | Created | Listing |
400 | Refused | Error |
401 | No key, or a key that is not live here | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
PUT /v1/listings/by-external-id/{externalId}
Create or update by your own id for the line
Creates on first sight, updates after. A listing never moves to another game, category, server or package: that is a new external id.
Scope listings:write. Spends the writes budget (120 a minute for a new seller).
scope listings:writebucket writesidempotency key
Body
| Field | Type | Required | Notes |
game | string | yes | |
category | string | yes | |
server | string | | |
package | string | | |
title | string | | |
tiers | array of object | | fields| Field | Type | Required | Notes |
min_qty | integer | yes | | price | string | yes | |
|
description | string | | |
price | string | yes | |
currency | string | | |
unit_label | string | | |
price_per_qty | integer | | |
min_qty | integer | | |
max_qty | integer | | |
stock_qty | integer | | |
low_stock_alert_qty | integer | | |
delivery_eta_minutes | integer | | |
attributes | map of string | | |
external_id | string | | |
status | draft · active | | |
Responses
| Status | Meaning | Body |
200 | Updated | Listing |
201 | Created | Listing |
401 | No key, or a key that is not live here | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/listings/{id}
One listing
Scope listings:read. Spends the reads budget (600 a minute for a new seller).
scope listings:readbucket reads
Responses
| Status | Meaning | Body |
200 | The listing | Listing |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
PATCH /v1/listings/{id}
Change price, stock, status or anything else
Scope listings:write. Spends the writes budget (120 a minute for a new seller).
scope listings:writebucket writesidempotency key
Body
| Field | Type | Required | Notes |
title | string | | |
tiers | array of object | | fields| Field | Type | Required | Notes |
min_qty | integer | yes | | price | string | yes | |
|
description | string | | |
price | string | | |
currency | string | | |
unit_label | string | | |
price_per_qty | integer | | |
min_qty | integer | | |
max_qty | integer | | |
stock_qty | integer | | |
low_stock_alert_qty | integer | | |
delivery_eta_minutes | integer | | |
attributes | map of string | | |
external_id | string | | |
status | draft · active · paused · removed | | |
Responses
| Status | Meaning | Body |
200 | The listing, after the change | Listing |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
PUT /v1/listings/{id}/tiers
Replace the volume ladder
Up to three rungs, each starting above the one before and cheaper than it; the listing's own price is the price at its minimum order. Checkout picks the rung an order's quantity reaches and freezes that unit price on the order. An empty list clears the ladder.
Scope listings:write. Spends the writes budget (120 a minute for a new seller).
scope listings:writebucket writesidempotency key
Body
| Field | Type | Required | Notes |
tiers | array of object | yes | fields| Field | Type | Required | Notes |
min_qty | integer | yes | | price | string | yes | |
|
Responses
| Status | Meaning | Body |
200 | The listing, with its ladder | Listing |
400 | Refused | Error |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/listings/{id}/codes
The code vault, counted
How many codes a gift-card or top-up listing holds, by state. Never the codes themselves.
Scope listings:read. Spends the reads budget (600 a minute for a new seller).
scope listings:readbucket reads
Responses
| Status | Meaning | Body |
200 | Counts | CodeVault |
400 | Refused | Error |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/listings/{id}/codes
Stock codes
Up to a thousand a call, encrypted at rest. A code already in the vault is a duplicate and not stocked twice; one withdrawn earlier comes back. Stock rises by what was added. From then on an order on this listing is accepted and delivered the moment it is paid, with the codes attached for the buyer; a vault short of the order quantity leaves that order for you to deliver by hand.
Scope listings:write. Spends the bulk budget (20 a minute for a new seller).
scope listings:writebucket bulkidempotency key
Body
| Field | Type | Required | Notes |
codes | array of string | yes | |
Responses
| Status | Meaning | Body |
200 | What landed | CodeVaultAdded |
400 | Refused | Error |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/listings/{id}/codes/withdraw
Take unsold codes off the shelf
The codes named, or every unsold one when none are. Stock falls by the same count.
Scope listings:write. Spends the writes budget (120 a minute for a new seller).
scope listings:writebucket writes
Body
| Field | Type | Required | Notes |
codes | array of string | | |
Responses
Orders
The order feed and the three moves a seller makes.
GET /v1/orders
Your orders, or everything that moved since a moment
Without updated_since: newest change first. With it: a feed, oldest first, that you walk forward with the cursor.
Scope orders:read. Spends the reads budget (600 a minute for a new seller).
scope orders:readbucket reads
Query
| Name | Type | Required | Notes |
state | paid · accepted · delivering · delivered · completed · disputed · refunded · partially_refunded · cancelled · expired | | |
updated_since | string (date-time) | | |
cursor | string | | |
limit | integer | | |
Responses
| Status | Meaning | Body |
200 | A page of orders | object |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/orders/changes
Has anything moved
Send back the ETag as If-None-Match. A 304 costs no database work, so poll at the pace in Poll-Interval with a clear conscience.
Scope orders:read. Spends the reads budget (600 a minute for a new seller).
scope orders:readbucket readsETag
Responses
| Status | Meaning | Body |
200 | Something moved | OrderChanges |
304 | Nothing moved | |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/orders/{id}
One order
Scope orders:read. Spends the reads budget (600 a minute for a new seller).
scope orders:readbucket reads
Responses
| Status | Meaning | Body |
200 | The order | Order |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/orders/{id}/events
The order's timeline
Scope orders:read. Spends the reads budget (600 a minute for a new seller).
scope orders:readbucket reads
Responses
| Status | Meaning | Body |
200 | Oldest first | object |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/orders/{id}/accept
Take the order
Starts the delivery window from the listing's quoted time.
Scope orders:write. Spends the writes budget (120 a minute for a new seller).
scope orders:writebucket writesidempotency key
Responses
| Status | Meaning | Body |
200 | Accepted | Order |
401 | No key, or a key that is not live here | Error |
403 | Refused | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/orders/{id}/deliver
Mark delivered
Refused with credentials_required on an account order without a handover.
Scope orders:write. Spends the writes budget (120 a minute for a new seller).
scope orders:writebucket writesidempotency key
Responses
| Status | Meaning | Body |
200 | Delivered; the buyer's confirmation window has started | Order |
401 | No key, or a key that is not live here | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/orders/{id}/decline
Decline a paid order
The buyer is refunded in full.
Scope orders:write. Spends the writes budget (120 a minute for a new seller).
scope orders:writebucket writesidempotency key
Responses
| Status | Meaning | Body |
200 | Refunded | Order |
401 | No key, or a key that is not live here | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/orders/{id}/credentials
The account handover
Stored encrypted, readable by the buyer of this order alone. Never put a password in the chat.
Scope orders:write. Spends the writes budget (120 a minute for a new seller).
scope orders:writebucket writesidempotency key
Body
| Field | Type | Required | Notes |
account_username | string | yes | |
account_password | string | yes | |
email_username | string | | |
email_password | string | | |
note | string | | |
Responses
| Status | Meaning | Body |
200 | Stored | Order |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
Chat
The thread with the buyer.
GET /v1/orders/{id}/messages
The thread with the buyer
Scope chat:read. Spends the reads budget (600 a minute for a new seller).
scope chat:readbucket reads
Responses
| Status | Meaning | Body |
200 | Oldest first | object |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/orders/{id}/messages
Send a message
The same contact detection as the site. Warnings come back to you; the message still goes.
Scope chat:write. Spends the chat budget (30 a minute for a new seller).
scope chat:writebucket chatidempotency key
Body
| Field | Type | Required | Notes |
body | string | yes | |
Responses
| Status | Meaning | Body |
201 | Sent | MessagePosted |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
Boosting
Your price curves on the services the platform standardises.
GET /v1/boost-templates
The services a game standardises
Every boost template for one game, with the knobs a curve prices: a range or number option takes a per-unit rate, a choice option takes basis points per value, a flags option takes basis points per extra you offer. offer_id is your curve on it, if you have one.
Any key. Spends the reads budget (600 a minute for a new seller).
bucket reads
Query
| Name | Type | Required | Notes |
game | string | yes | |
Responses
| Status | Meaning | Body |
200 | In the hub order | object |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/boost-offers
Your curves
Scope listings:read. Spends the reads budget (600 a minute for a new seller).
scope listings:readbucket reads
Responses
| Status | Meaning | Body |
200 | Every curve, across games | object |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
PUT /v1/boost-offers/{template}
Publish or replace your curve on a template
One curve per template: a second call replaces it and sets it active. Every rate must name an option the template defines. The cheapest configuration the curve prices is the "from" price on the hub and must be above zero. Prices are decimal USD.
Scope listings:write. Spends the writes budget (120 a minute for a new seller).
scope listings:writebucket writesidempotency key
Body
| Field | Type | Required | Notes |
pricing | object | yes | fields| Field | Type | Required | Notes |
base | string | yes | | per_unit | map of string | | | choice_bps | map of map of integer | | | flag_bps | map of integer | | | min_total | string | | |
|
eta_hours | integer | yes | |
Responses
| Status | Meaning | Body |
200 | The offer | BoostOffer |
400 | Refused | Error |
401 | No key, or a key that is not live here | Error |
403 | Refused | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
PATCH /v1/boost-offers/{id}
Pause or resume a curve
Pausing is always allowed. Resuming is starting to sell again, which a suspended account cannot do.
Scope listings:write. Spends the writes budget (120 a minute for a new seller).
scope listings:writebucket writes
Body
| Field | Type | Required | Notes |
status | active · paused | yes | |
Responses
| Status | Meaning | Body |
200 | The offer | BoostOffer |
401 | No key, or a key that is not live here | Error |
403 | Refused | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
Stock syncs
A whole sheet of stock, landed as one decision.
POST /v1/listings/batch
Up to a thousand lines in one call
The sync engine in merge mode, opened, staged and committed for you. Answers at once with a result per line for the staging; poll the sync for the result per line of the apply.
Scope listings:write. Spends the bulk budget (20 a minute for a new seller).
scope listings:writebucket bulk
Body
| Field | Type | Required | Notes |
lines | array of object | yes | fields| Field | Type | Required | Notes |
game | string | yes | | category | string | yes | | server | string | | | package | string | | | title | string | | | tiers | array of object | | fields| Field | Type | Required | Notes |
min_qty | integer | yes | | price | string | yes | |
| description | string | | | price | string | yes | | currency | string | | | unit_label | string | | | price_per_qty | integer | | | min_qty | integer | | | max_qty | integer | | | stock_qty | integer | | | low_stock_alert_qty | integer | | | delivery_eta_minutes | integer | | | attributes | map of string | | | external_id | string | yes | | status | draft · active · paused | | |
|
Responses
| Status | Meaning | Body |
202 | Staged and committed; the worker applies it | Staged |
400 | Refused | Error |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/stock/syncs
Your last fifty syncs
Scope listings:read. Spends the reads budget (600 a minute for a new seller).
scope listings:readbucket reads
Responses
| Status | Meaning | Body |
200 | Newest first | object |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/stock/syncs
Open a sync
Replace mode pauses every listing with an external id the sync does not mention; merge mode touches only the lines sent. An open sync expires after an hour.
Scope listings:write. Spends the bulk budget (20 a minute for a new seller).
scope listings:writebucket bulk
Body
| Field | Type | Required | Notes |
mode | replace · merge | | |
Responses
| Status | Meaning | Body |
201 | Open | StockSync |
401 | No key, or a key that is not live here | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/stock/syncs/{id}
One sync, with its summary once committed
Scope listings:read. Spends the reads budget (600 a minute for a new seller).
scope listings:readbucket reads
Responses
| Status | Meaning | Body |
200 | The sync | StockSync |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
PUT /v1/stock/syncs/{id}/lines
Stage up to a thousand lines
Each line is validated on its own and its game, category, server and package resolved; a bad line is reported here and counted as failed at commit, and the rest go on. The same external id staged again keeps the later line.
Scope listings:write. Spends the bulk budget (20 a minute for a new seller).
scope listings:writebucket bulk
Body
| Field | Type | Required | Notes |
lines | array of object | yes | fields| Field | Type | Required | Notes |
game | string | yes | | category | string | yes | | server | string | | | package | string | | | title | string | | | tiers | array of object | | fields| Field | Type | Required | Notes |
min_qty | integer | yes | | price | string | yes | |
| description | string | | | price | string | yes | | currency | string | | | unit_label | string | | | price_per_qty | integer | | | min_qty | integer | | | max_qty | integer | | | stock_qty | integer | | | low_stock_alert_qty | integer | | | delivery_eta_minutes | integer | | | attributes | map of string | | | external_id | string | yes | | status | draft · active · paused | | |
|
Responses
| Status | Meaning | Body |
200 | A result per line | Staged |
400 | Refused | Error |
401 | No key, or a key that is not live here | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/stock/syncs/{id}/lines
The lines, with the result each got
Scope listings:read. Spends the reads budget (600 a minute for a new seller).
scope listings:readbucket reads
Query
| Name | Type | Required | Notes |
action | created · updated · unchanged · paused · failed | | |
cursor | string | | |
limit | integer | | |
Responses
| Status | Meaning | Body |
200 | In staging order | object |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/stock/syncs/{id}/commit
Apply the sync
Returns at once; the worker applies it in short transactions, recounts your catalog pages once, and stamps a result on every line.
Scope listings:write. Spends the bulk budget (20 a minute for a new seller).
scope listings:writebucket bulk
Responses
| Status | Meaning | Body |
202 | Committing | StockSync |
401 | No key, or a key that is not live here | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
Webhooks
Where events go, signed, retried, logged.
GET /v1/webhooks
Your endpoints
Scope webhooks:manage. Spends the reads budget (600 a minute for a new seller).
scope webhooks:managebucket reads
Responses
| Status | Meaning | Body |
200 | Every endpoint, never a secret | object |
401 | No key, or a key that is not live here | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/webhooks
Add an endpoint
HTTPS only, to a public address. Up to five per account. An empty events list subscribes to everything. The secret is in this one response and nowhere else.
Scope webhooks:manage. Spends the writes budget (120 a minute for a new seller).
scope webhooks:managebucket writesidempotency key
Body
| Field | Type | Required | Notes |
url | string | yes | |
events | array of string | | |
label | string | | |
Responses
| Status | Meaning | Body |
201 | Created, with the secret | WebhookWithSecret |
400 | Refused | Error |
401 | No key, or a key that is not live here | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/webhooks/{id}
One endpoint
Scope webhooks:manage. Spends the reads budget (600 a minute for a new seller).
scope webhooks:managebucket reads
Responses
| Status | Meaning | Body |
200 | The endpoint | Webhook |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
PATCH /v1/webhooks/{id}
Change the URL, the events, the label, or re-enable it
Scope webhooks:manage. Spends the writes budget (120 a minute for a new seller).
scope webhooks:managebucket writesidempotency key
Body
| Field | Type | Required | Notes |
url | string | | |
events | array of string | | |
label | string | | |
status | active · disabled | | |
Responses
| Status | Meaning | Body |
200 | The endpoint, after the change | Webhook |
400 | Refused | Error |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
DELETE /v1/webhooks/{id}
Remove an endpoint and its delivery log
Scope webhooks:manage. Spends the writes budget (120 a minute for a new seller).
scope webhooks:managebucket writes
Responses
| Status | Meaning | Body |
204 | Gone | |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/webhooks/{id}/test
Send a ping through the real pipeline
Scope webhooks:manage. Spends the writes budget (120 a minute for a new seller).
scope webhooks:managebucket writes
Responses
| Status | Meaning | Body |
202 | Queued; it arrives within a few seconds and shows in the delivery log | Queued |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/webhooks/{id}/rotate-secret
New secret, with a day of overlap
Deliveries carry two signatures for 24 hours, one with each secret, so the receiver can be switched over without a gap.
Scope webhooks:manage. Spends the writes budget (120 a minute for a new seller).
scope webhooks:managebucket writesidempotency key
Responses
| Status | Meaning | Body |
200 | The endpoint, with the new secret | WebhookWithSecret |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
GET /v1/webhooks/{id}/deliveries
The delivery log
Scope webhooks:manage. Spends the reads budget (600 a minute for a new seller).
scope webhooks:managebucket reads
Query
| Name | Type | Required | Notes |
status | pending · succeeded · failed · exhausted | | |
cursor | string | | |
limit | integer | | |
Responses
| Status | Meaning | Body |
200 | Newest first | object |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/webhooks/{id}/deliveries/{deliveryId}/replay
Send a delivery again, now
Scope webhooks:manage. Spends the writes budget (120 a minute for a new seller).
scope webhooks:managebucket writes
Responses
| Status | Meaning | Body |
200 | Queued as a fresh attempt | Delivery |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
Sandbox
The synthetic buyer, on the sandbox only.
POST /v1/sandbox/orders
Buy from yourself
The synthetic buyer places and pays for an order on one of your listings through the real checkout, so order.paid reaches your endpoint by the production path. Then accept and deliver it as you would any order, and drive the buyer from the routes below. Sandbox only.
Scope orders:write. Spends the writes budget (120 a minute for a new seller).
scope orders:writebucket writesidempotency keysandbox only
Body
| Field | Type | Required | Notes |
listing_id | string | yes | |
quantity | integer | yes | |
character_name | string | | |
Responses
| Status | Meaning | Body |
201 | The order, paid | Order |
400 | Refused | Error |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/sandbox/orders/{id}/confirm
The buyer confirms delivery
Scope orders:write. Spends the writes budget (120 a minute for a new seller).
scope orders:writebucket writessandbox only
Responses
| Status | Meaning | Body |
200 | The order, completed | Order |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/sandbox/orders/{id}/cancel
The buyer cancels before you accept
Scope orders:write. Spends the writes budget (120 a minute for a new seller).
scope orders:writebucket writessandbox only
Responses
| Status | Meaning | Body |
200 | The order, refunded | Order |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/sandbox/orders/{id}/dispute
The buyer opens a dispute
Scope orders:write. Spends the writes budget (120 a minute for a new seller).
scope orders:writebucket writessandbox only
Body
| Field | Type | Required | Notes |
reason_code | not_delivered · partially_delivered · wrong_item · recalled · other | | |
detail | string | | |
Responses
| Status | Meaning | Body |
200 | The order, disputed | Order |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
409 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
POST /v1/sandbox/reset
Wipe your slate
Listings off the shelf, syncs and deliveries gone, the outbox cleared. Keys and endpoints stay; orders stay, because the ledger under them is append-only.
Scope account:write. Spends the bulk budget (20 a minute for a new seller).
scope account:writebucket bulksandbox only
Responses
| Status | Meaning | Body |
200 | What went | object |
401 | No key, or a key that is not live here | Error |
404 | Refused | Error |
429 | The budget for the minute is spent; wait for Retry-After | Error |
Schemas
Error
| Field | Type | Required | Notes |
error | object | yes | fields| Field | Type | Required | Notes |
code | string | yes | Stable, snake_case. What a client branches on. | message | string | yes | | requestId | string | yes | Quote this when asking for help. | details | any | | Field-level detail where there is any. |
|
Ping
| Field | Type | Required | Notes |
ok | boolean | yes | |
environment | live · test | yes | |
server_time | string (date-time) | yes | |
key | object | yes | fields| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID | label | string | yes | | scopes | array of catalog:read · listings:read · listings:write · orders:read · orders:write · chat:read · chat:write · account:read · account:write · webhooks:manage | yes | | ip_allowlist | array of string | yes | | expires_at | string or null | yes | | created_at | string (date-time) | yes | |
|
seller | object | yes | fields| Field | Type | Required | Notes |
handle | string | yes | | tier | new · standard · trusted | yes | | trading_status | string | yes | | holiday_mode | boolean | yes | |
|
limits | object | yes | fields| Field | Type | Required | Notes |
reads_per_minute | integer | yes | | writes_per_minute | integer | yes | | bulk_per_minute | integer | yes | | chat_per_minute | integer | yes | |
|
Me
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
handle | string | yes | |
display_name | string or null | yes | |
tier | new · standard · trusted | yes | |
trading_status | string | yes | `active`, or `suspended`: reads keep working, writes that start something are refused. |
holiday_mode | boolean | yes | |
presence | online · away · offline | yes | |
payout_hold_days | integer | yes | |
qualifying_orders | integer | yes | |
Balance
| Field | Type | Required | Notes |
currency | string | yes | |
available | string | yes | A decimal string in the row's currency. Never a float. |
pending | string | yes | A decimal string in the row's currency. Never a float. |
payout_hold_days | integer | yes | |
FeeQuote
| Field | Type | Required | Notes |
currency | string | yes | |
category | string | yes | |
subtotal | string | yes | A decimal string in the row's currency. Never a float. |
buyer_fee | string | yes | A decimal string in the row's currency. Never a float. |
buyer_total | string | yes | A decimal string in the row's currency. Never a float. |
seller_fee | string | yes | A decimal string in the row's currency. Never a float. |
seller_fee_bps | integer | yes | |
reserve | string | yes | A decimal string in the row's currency. Never a float. |
seller_net | string | yes | A decimal string in the row's currency. Never a float. |
Game
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
slug | string | yes | |
name | string | yes | |
platform | string or null | yes | |
updated_at | string (date-time) | yes | |
GameDetail
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
slug | string | yes | |
name | string | yes | |
platform | string or null | yes | |
updated_at | string (date-time) | yes | |
categories | array of object | yes | fields| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID | slug | string | yes | | name | string | yes | | kind | currency · item · account · service · topup · giftcard | yes | | vocabulary | array of object | yes | fields| Field | Type | Required | Notes |
key | string | yes | | label | string | yes | | options | array of string | yes | |
| packages | array of object | yes | fields| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID | slug | string | yes | | label | string | yes | | amount | integer or null | yes | | unit | string or null | yes | | region | string or null | yes | | popular | boolean | yes | |
|
|
servers | array of object | yes | fields| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID | slug | string | yes | | name | string | yes | | region | string or null | yes | | faction | string or null | yes | | attributes | map of string | yes | |
|
Candidate
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
slug | string | yes | |
name | string | yes | |
score | number | yes | |
Tier
| Field | Type | Required | Notes |
min_qty | integer | yes | From this order quantity up, in units. |
price | string | yes | A decimal string in the row's currency. Never a float. |
CatalogChanges
| Field | Type | Required | Notes |
changes | array of object | yes | fields| Field | Type | Required | Notes |
type | game · category · server · package | yes | | action | created · updated | yes | | id | string | yes | A prefixed ULID | slug | string | yes | | name | string | yes | | game_id | string or null | yes | A prefixed ULID | updated_at | string (date-time) | yes | |
|
next_since | string or null | yes | |
Listing
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
external_id | string or null | yes | |
status | draft · active · paused · removed | yes | |
taken_down | boolean | yes | |
game | object | yes | fields| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID | slug | string | yes | | name | string | yes | |
|
category | object | yes | fields| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID | slug | string | yes | | name | string | yes | | kind | string | yes | |
|
server | object or null | yes | |
package | object or null | yes | |
path | string | yes | The catalog page the listing appears on. |
title | string | yes | |
description | string or null | yes | |
price | string | yes | A decimal string in the row's currency. Never a float. |
tiers | array of Tier | yes | |
currency | string | yes | |
price_per_qty | integer | yes | How many units the price buys, for example 1000 gold. |
unit_label | string | yes | |
min_qty | integer | yes | |
max_qty | integer or null | yes | |
stock_qty | integer | yes | |
low_stock_alert_qty | integer or null | yes | |
delivery_eta_minutes | integer | yes | |
attributes | map of string | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | yes | |
Order
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
state | draft · payment_pending · paid · accepted · delivering · delivered · disputed · completed · cancelled · expired · refunded · partially_refunded | yes | |
state_updated_at | string (date-time) | yes | |
created_at | string (date-time) | yes | |
listing | object or null | yes | |
boost | object or null | yes | |
game | object or null | yes | |
server | object or null | yes | |
category_kind | string or null | yes | |
quantity | integer | yes | |
unit_label | string or null | yes | |
price_per_qty | integer | yes | |
unit_price | string | yes | A decimal string in the row's currency. Never a float. |
subtotal | string | yes | A decimal string in the row's currency. Never a float. |
buyer_fee | string | yes | A decimal string in the row's currency. Never a float. |
seller_fee | string | yes | A decimal string in the row's currency. Never a float. |
total | string | yes | A decimal string in the row's currency. Never a float. |
currency | string | yes | |
buyer | object | yes | fields| Field | Type | Required | Notes |
handle | string or null | yes | | character_name | string or null | yes | |
|
deadlines | object | yes | fields| Field | Type | Required | Notes |
accept_by | string or null | yes | | deliver_by | string or null | yes | | auto_confirm_at | string or null | yes | |
|
fee_schedule_ids | object | yes | fields| Field | Type | Required | Notes |
buyer | string or null | yes | A prefixed ULID | seller | string or null | yes | A prefixed ULID |
|
OrderEvent
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
seq | integer | yes | Strictly increasing per order; the number a webhook consumer keys on. |
type | string | yes | |
from_state | string or null | yes | |
to_state | string or null | yes | |
actor | user · admin · system | yes | |
created_at | string (date-time) | yes | |
OrderChanges
| Field | Type | Required | Notes |
changed | boolean | yes | |
counts | map of any | yes | |
Message
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
body | string or null | yes | |
image | string or null | yes | |
author | object | yes | fields| Field | Type | Required | Notes |
role | seller · buyer · system | yes | | handle | string or null | yes | |
|
created_at | string (date-time) | yes | |
MessagePosted
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
created_at | string (date-time) | yes | |
warnings | array of string | yes | |
Webhook
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
url | string (uri) | yes | |
label | string or null | yes | |
events | array of order.paid · order.accepted · order.delivering · order.delivered · order.completed · order.cancelled · order.refunded · order.expired · order.disputed · order.dispute_resolved · order.message · listing.low_stock · listing.sold_out · listing.taken_down · listing.reinstated · account.trading_status_changed · ping | yes | |
status | active · disabled | yes | |
disabled_reason | string or null | yes | |
failing_since | string or null | yes | |
previous_secret_until | string or null | yes | While set, deliveries carry a second signature made with the secret before the last rotation. |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | yes | |
WebhookWithSecret
| Field | Type | Required | Notes |
secret | string | yes | Shown once. Verify every delivery with it. |
id | string | yes | A prefixed ULID |
url | string (uri) | yes | |
label | string or null | yes | |
events | array of order.paid · order.accepted · order.delivering · order.delivered · order.completed · order.cancelled · order.refunded · order.expired · order.disputed · order.dispute_resolved · order.message · listing.low_stock · listing.sold_out · listing.taken_down · listing.reinstated · account.trading_status_changed · ping | yes | |
status | active · disabled | yes | |
disabled_reason | string or null | yes | |
failing_since | string or null | yes | |
previous_secret_until | string or null | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | yes | |
Delivery
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
event_id | string | yes | A prefixed ULID |
event_type | order.paid · order.accepted · order.delivering · order.delivered · order.completed · order.cancelled · order.refunded · order.expired · order.disputed · order.dispute_resolved · order.message · listing.low_stock · listing.sold_out · listing.taken_down · listing.reinstated · account.trading_status_changed · ping | yes | |
status | pending · succeeded · failed · exhausted | yes | |
attempts | integer | yes | |
next_attempt_at | string or null | yes | |
last_attempt_at | string or null | yes | |
response_status | integer or null | yes | |
response_snippet | string or null | yes | The first kilobyte of what your server answered. |
last_error | string or null | yes | |
duration_ms | integer or null | yes | |
created_at | string (date-time) | yes | |
Queued
| Field | Type | Required | Notes |
queued | boolean | yes | |
CodeVault
| Field | Type | Required | Notes |
available | integer | yes | Unsold, on the shelf. Also the listing stock the vault maintains. |
delivered | integer | yes | |
withdrawn | integer | yes | |
CodeVaultAdded
| Field | Type | Required | Notes |
added | integer | yes | |
duplicates | integer | yes | |
available | integer | yes | |
delivered | integer | yes | |
withdrawn | integer | yes | |
CodeVaultWithdrawn
| Field | Type | Required | Notes |
removed | integer | yes | |
available | integer | yes | |
delivered | integer | yes | |
withdrawn | integer | yes | |
BoostOption
| Field | Type | Required | Notes |
key | string | yes | |
label | string | yes | |
type | range · number · choice · flags | yes | |
min | integer | | |
max | integer | | |
unit | string | | |
choices | array of object | | fields| Field | Type | Required | Notes |
value | string | yes | | label | string | yes | |
|
flags | array of object | | fields| Field | Type | Required | Notes |
value | string | yes | | label | string | yes | |
|
BoostTemplate
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
slug | string | yes | |
name | string | yes | |
category | object | yes | fields| Field | Type | Required | Notes |
slug | string | yes | | name | string | yes | |
|
options | array of BoostOption | yes | |
offer_id | string or null | yes | A prefixed ULID |
BoostPricing
| Field | Type | Required | Notes |
base | string | yes | A decimal string in the row's currency. Never a float. |
per_unit | map of string | yes | A rate per unit, keyed by a range or number option. |
choice_bps | map of map of integer | yes | Basis points per chosen value, keyed by a choice option then its value. |
flag_bps | map of integer | yes | Basis points per extra offered. An extra missing here is not for sale. |
min_total | string or null | yes | A decimal string in the row's currency. Never a float. |
BoostOffer
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
status | active · paused | yes | |
template | object | yes | fields| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID | name | string | yes | | category | string | yes | | game | object | yes | fields| Field | Type | Required | Notes |
slug | string | yes | | name | string | yes | |
|
|
pricing | BoostPricing | yes | |
currency | string | yes | |
eta_hours | integer | yes | |
from_price | string | yes | A decimal string in the row's currency. Never a float. |
StockSync
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
mode | replace · merge | yes | |
status | open · committing · committed · expired · failed | yes | |
line_count | integer | yes | |
summary | object or null | yes | |
error | string or null | yes | |
expires_at | string (date-time) | yes | An open sync not committed by then expires. |
committed_at | string or null | yes | |
created_at | string (date-time) | yes | |
updated_at | string (date-time) | yes | |
StagingResult
| Field | Type | Required | Notes |
external_id | string or null | yes | |
status | staged · invalid | yes | |
error | object | | fields| Field | Type | Required | Notes |
code | string | yes | | message | string | yes | |
|
SyncLine
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
external_id | string | yes | |
listing_id | string or null | yes | A prefixed ULID |
action | string or null | yes | |
error | object or null | yes | |
line | map of any | yes | The line as staged. |
WebhookEvent
| Field | Type | Required | Notes |
id | string | yes | A prefixed ULID |
type | order.paid · order.accepted · order.delivering · order.delivered · order.completed · order.cancelled · order.refunded · order.expired · order.disputed · order.dispute_resolved · order.message · listing.low_stock · listing.sold_out · listing.taken_down · listing.reinstated · account.trading_status_changed · ping | yes | |
created_at | string (date-time) | yes | |
api_version | string | yes | |
data | map of any | yes | For order.* the order as GET /v1/orders/{id} returns it under `order`; for listing.* the listing under `listing`; for order.message the message under `message`. |