The header name is
api-key — lowercase, hyphenated. X-API-Key is rejected.What an API key represents
An API key is bound to one merchant account. The merchant is the parent; their sub-users hang off that parent. A key authorises:- All
/merchant/*operations on that merchant - Sub-user-context routes (
/user/*,/market/*,/auth/ws-token) when combined with anOn-Behalf-Ofheader to pick which sub-user to act as
On-Behalf-Of, sub-user-context routes run against the merchant
itself: POST /market/buy without the header buys for the merchant’s own
spot wallet and uses the merchant’s primary Steam trade URL. With the
header, the same call is scoped to a sub-user.
See Acting on behalf of a sub-user for the full
mechanics.
What API keys cannot do
Some operations live in the dashboard only and are gated behind session-based JWT auth. API keys get a403 FORBIDDEN on:
- API key CRUD (creating, rotating, revoking other keys)
- Webhook URL config, secret rotation, delivery inspection
- Adjusting merchant fees (read-only over the API)
- Account settings (password, email change, 2FA, account deletion)
- Audit log queries and CSV exports
IP allowlists
When you create or rotate a key in the dashboard, you can pin it to one or more source IPs. Requests from any other IP fail with:Storing and rotating keys
- Treat the raw key like a password. The server only stores a hash; once you lose the raw value, you must rotate.
- Rotate by creating a new key in the dashboard and revoking the old one. Keep both active for the deploy window so callers can roll over.
- Set per-environment keys (production vs staging vs CI) with separate IP allowlists. Don’t reuse keys across environments.
TypeScript clients
The fastest path is the official@skinshark/sdk package, which handles
the headers, envelope unwrapping, retries, and typed errors for you. Keep
reading if you’d rather build your own wrapper.
With @skinshark/sdk
baseUrl (e.g. https://api-staging.skinshark.gg),
timeoutMs, retries, userAgent, and a debug hook. See
SDK & TypeScript types for the full surface.
With raw fetch
A minimal, typed wrapper that fails fast on envelope errors:Common error keys
| Code | HTTP | Key | Meaning |
|---|---|---|---|
| 1104 | 401 | MISSING_API_KEY | No api-key header sent. |
| 1105 | 401 | INVALID_API_KEY | Key not found. |
| 1106 | 401 | API_KEY_REVOKED | Key was active but has been revoked. |
| 1305 | 403 | API_KEY_IP_DENIED | Source IP not on the allowlist. |
| 1301 | 403 | ACCOUNT_SUSPENDED | The merchant account is suspended. |
| 1300 | 403 | FORBIDDEN | Trying to call a dashboard-only endpoint, or On-Behalf-Of set on a /merchant/* route. |
| 1307 | 404 | USER_NOT_FOUND | On-Behalf-Of references a sub-user not owned by this merchant. |