Integration docs
Everything you need to integrate the seamless-wallet API: authentication, the core endpoints, webhook signature verification, error codes and our official SDKs.
Authentication
Every request carries your operator API key as a bearer token. Keys are environment-specific — sandbox keys can only open demo sessions.
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx
Responses are JSON. Non-2xx responses use a stable envelope: { "errorCode": number, "errorDescription": string }. Rate-limit headers (X-RateLimit-*) and a correlation X-Request-Id are returned on every call.
Create a session
POST /v1/sessions
Authorization: Bearer sk_live_…
Content-Type: application/json
{
"userId": "player-123",
"gameId": "skyrush",
"currency": "USD",
"language": "en",
"mode": "real"
}
# → 201
{
"sessionId": "sess_…",
"launchUrl": "https://launcher.provider.gg/launch/skyrush?token=…",
"token": "…",
"expiresAt": "2026-06-03T12:00:00.000Z"
}Core endpoints
All paths are relative to your environment base URL.
| Method | Path | Description |
|---|---|---|
| GET | /v1/games | List entitled games |
| GET | /v1/games/:id | Game detail & limits |
| POST | /v1/sessions | Create a launch session |
| GET | /v1/rounds | List rounds (filterable) |
| GET | /v1/rounds/:id | Round detail + receipt |
| GET | /v1/transactions | List wallet transactions |
| GET | /v1/reports/daily | Daily aggregated report |
| POST | /v1/players/:id/limits | Set RG limits |
| POST | /v1/players/:id/exclude | Self-exclude a player |
| GET | /v1/webhooks | List webhook subscriptions |
| POST | /v1/webhooks | Create/rotate a subscription |
Verify webhooks — Node.js
import { createHmac, timingSafeEqual } from 'node:crypto';
// Express handler. Use the RAW body, not the parsed JSON.
app.post('/webhooks/provider', (req, res) => {
const sig = req.header('X-Provider-Signature') ?? '';
const ts = req.header('X-Provider-Timestamp') ?? '';
const raw = req.rawBody; // Buffer/string of the exact payload
// Reject replays older than 5 minutes.
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(401);
const expected = createHmac('sha256', WEBHOOK_SECRET)
.update(`${ts}.${raw}`)
.digest('hex');
const ok = sig.length === expected.length &&
timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
if (!ok) return res.sendStatus(401);
// ... handle event ...
res.sendStatus(200);
});Verify webhooks — Python
import hmac, hashlib, time
def verify(raw_body: bytes, signature: str, timestamp: str, secret: str) -> bool:
if abs(time.time() - int(timestamp)) > 300:
return False
msg = f"{timestamp}.".encode() + raw_body
expected = hmac.new(secret.encode(), msg, hashlib.sha256).hexdigest()
return hmac.compare_digest(signature, expected)The same scheme is implemented in our SDKs, so you rarely need to write this by hand.
Error codes
| Code | Name | Meaning |
|---|---|---|
| 1000 | INVALID_REQUEST | Malformed or missing parameters |
| 1002 | INVALID_SIGNATURE | Bad bearer token or HMAC |
| 2001 | INSUFFICIENT_FUNDS | Player wallet cannot cover the bet |
| 2002 | PLAYER_NOT_FOUND | Unknown player |
| 3001 | GAME_DISABLED | Game not entitled for operator |
| 4001 | TRANSACTION_NOT_FOUND | No such round/transaction |
| 5000 | INTERNAL_ERROR | Transient server error — retry |
Official SDKs
Same signing contract across every language.
TypeScript / Node@provider/operator-api-sdk
npm i @provider/operator-api-sdk
Pythonprovider-operator-sdk
pip install provider-operator-sdk
PHPprovider/operator-sdk
composer require provider/operator-sdk
Javacom.provider:operator-sdk
implementation "com.provider:operator-sdk:1.0.0"