Authentication
Workspace-scoped API keys in the X-Api-Key header — scopes, allow-lists, rotation, and the platform's transport guarantees.
Every request is authenticated with a workspace-scoped API key. This page covers the key's anatomy and transport, the scope catalog, network allow-lists, rotation, and the guarantees the platform makes in return.
The API key
Keys are issued from the merchant dashboard (Developers → API keys) and have three parts:
- a fixed prefix,
xkey_, so keys are recognizable in logs and secret scanners; - a public lookup segment;
- a secret segment shown once at issuance. Xegora stores only a hash — a lost key cannot be recovered, only replaced.
Send the full plaintext key on every request:
X-Api-Key: xkey_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
There is no cookie, session, or OAuth handshake on this surface — the header is the whole story. Requests without a valid key receive 401 Unauthorized; a valid key without the required scope receives 403 Forbidden.
Scopes — least privilege by design
Each key carries an explicit scope set chosen at issuance. Grant only what the integration needs:
| Scope | Grants | Used by |
|---|---|---|
products.read | Browse the catalog and fetch product images | GET /products, GET /products/{id}, GET /catalog-product-images/{ref} |
quotes.create | Price a purchase | POST /quotes |
orders.create | Place orders (spends wallet funds) | POST /orders |
orders.read | Read orders and reveal fulfillment | GET /orders, GET /orders/{id}, POST /orders/{id}/fulfillment |
wallet.read | Balance, deposit address (read), deposit history, withdrawal quotes/listing | GET /wallet/*, POST /withdrawals/quotes, GET /withdrawals |
wallet.deposit-address.write | Request the workspace's BSC-USD deposit address | PUT /wallet/deposit-addresses/bsc-usd |
wallet.withdraw | Request or cancel a payout of your own funds | POST /withdrawals, POST /withdrawals/{id}/cancellation |
Two scopes deserve special attention:
orders.createspends money. A storefront that only displays the catalog should not hold it.wallet.withdrawmoves money out. It is deliberately separate fromwallet.read, so a leaked read-only or ordering key can never trigger a payout. Withdrawals also never name a destination — funds can only go to the payout details registered on your workspace, after a business-day hold, and are cancellable until paid. See Withdrawals.
A practical split for most integrations:
| Key | Scopes | Lives in |
|---|---|---|
| Storefront key | products.read, quotes.create | Your web/backend catalog layer |
| Purchasing key | orders.create, orders.read | Your order-processing service |
| Treasury key | wallet.read, wallet.deposit-address.write, wallet.withdraw | Your finance tooling only |
Network allow-lists and expiry
At issuance you can bind a key to:
- CIDR allow-list — requests from any other source address are rejected outright. Strongly recommended for production keys with money-moving scopes.
- Expiry — an absolute expiration instant. Expired keys authenticate nothing.
Revocation from the dashboard is immediate.
Key hygiene
- Store keys in a secret manager, never in source control, mobile apps, or browser code. The Integration API is a server-to-server surface; calling it from a browser would expose the key.
- Rotate by issuing a new key, deploying it, then revoking the old one — both are valid during the overlap, so rotation needs no downtime.
- Scope one key per system, not one key for everything; a compromise then has a known blast radius.
- Watch for
401/403spikes in your logs — they are the earliest sign of a revoked, expired, or wrongly scoped key.
Transport guarantees
- HTTPS only. The API is served exclusively over TLS at
https://integration.xegora.com. - Workspace isolation. The workspace is derived from the key on every request. There is no parameter to name another workspace, so cross-tenant access is structurally impossible.
- Rate limiting. 120 requests per minute per workspace (fixed window). Excess requests receive
429 Too Many Requestswith aRetry-Afterheader — see Errors & Retries. - No secrets in transit by default. Order bodies and webhooks never contain fulfillment artifacts; codes exist only in the response of an explicit, audited reveal call, always delivered
Cache-Control: no-store. - Auditability. Every mutating call is attributed to the exact API key that made it, and every response carries a
correlationIdyou can quote to support.
Updated about 2 hours ago