Authentication
Bearer tokens, modes and installation context.
Base URL:
https://api.spuke.com/v1/app
Every request carries an installation access token:
curl "https://api.spuke.com/v1/app/v1/payments?limit=10" \
-H "Authorization: Bearer spk_at_live_…"
The token identifies the app and the merchant. There is no merchant id parameter — you cannot address a merchant that has not installed you.
Getting a token
Tokens come from the OAuth flow at install time (authorization_code, PKCE supported) and are renewed with the refresh_token grant. See Installs & OAuth.
| Property | Value |
|---|---|
| Access token | spk_at_live_… / spk_at_test_…, valid 1 hour (expires_in: 3600) |
| Refresh token | spk_rt_live_… / spk_rt_test_…, single use and rotating — store the new one on every refresh |
| Mode | Baked into the token, cannot be switched |
| Scopes | Exactly what the merchant approved |
| Reissue | Issuing a new access token revokes the installation's previous access tokens |
Because refresh tokens rotate, refreshing twice with the same token invalidates the installation's tokens — serialise your refresh calls.
Failure modes
| Status | error.type |
Do this |
|---|---|---|
| 401 | invalid_token |
Refresh, then retry once |
| 403 | insufficient_scope |
Request the scope in a new version; do not retry |
| 403 | installation_suspended |
Back off, retry later, keep data |
| 404 | not_found |
Object does not exist for this merchant |
| 404 | unknown_endpoint |
Path typo or unsupported resource |
| 405 | method_not_allowed |
v1 is read-only; only GET |
| 429 | rate_limit_exceeded |
Honour Retry-After |
Error bodies are uniform:
{ "error": { "type": "insufficient_scope", "message": "Missing required scope: payments:read" } }
Server-side only
The client secret and refresh tokens must never reach a browser or a mobile binary. Public clients use PKCE and keep only the short-lived access token.