Making Requests
Every Scenema API request is a standard HTTPS call with a Bearer token in the Authorization header. This page covers the request shape, response format, and worked examples in the common languages.
Request shape
<METHOD> https://scenema.ai/api/service/<path>
Authorization: Bearer sk_your_key
Content-Type: application/json (for POST / PATCH / PUT)
<optional JSON body>- Methods follow standard REST:
GETfor reads,POSTfor create,PATCHfor partial update,DELETEfor revoke. - Request bodies are JSON. If you send a POST or PATCH without
Content-Type: application/json, the server treats the body as empty. - URL parameters are lowercase kebab-case. Path parameters are the raw resource id, no quoting.
Response shape
Every response is JSON. Success responses vary by endpoint but always parse into a stable shape documented alongside each endpoint. Error responses are consistent:
{
"error": "<human-readable message>",
"code": "<optional machine-readable code>"
}Refer to Errors for the full status code and code list.
Worked example: list your API keys
This endpoint is the canonical smoke test. It requires only auth, returns quickly, and confirms your credentials are wired correctly before you move on to heavier calls.
curl
curl -H "Authorization: Bearer $SCENEMA_KEY" \
https://scenema.ai/api/service/user/api-keysJavaScript (fetch)
const res = await fetch('https://scenema.ai/api/service/user/api-keys', {
headers: { Authorization: `Bearer ${process.env.SCENEMA_KEY}` },
});
const body = await res.json();
console.log(body.keys);Python (requests)
import os
import requests
resp = requests.get(
'https://scenema.ai/api/service/user/api-keys',
headers={'Authorization': f"Bearer {os.environ['SCENEMA_KEY']}"},
)
resp.raise_for_status()
print(resp.json()['keys'])Go (net/http)
req, _ := http.NewRequest("GET", "https://scenema.ai/api/service/user/api-keys", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("SCENEMA_KEY"))
resp, err := http.DefaultClient.Do(req)Handling rate limits gracefully
Rate-limited responses return HTTP 429 Too Many Requests with a Retry-After header carrying the number of seconds until your window rolls. Any HTTP client that respects Retry-After (curl with --retry, most library retry adapters) will handle this without extra code.
Manual pattern:
async function callWithBackoff(url, opts, maxAttempts = 5) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const res = await fetch(url, opts);
if (res.status !== 429) return res;
const retryAfter = Number(res.headers.get('retry-after') ?? '1');
await new Promise(r => setTimeout(r, retryAfter * 1000));
}
throw new Error('Rate limit backoff exhausted');
}See Rate Limits for the per-plan ceilings and the mechanics of Scenema’s fixed-window counter.
Idempotency
Read requests are always safe to retry. Mutation requests (create-a-key, revoke, disable) are idempotent by design: creating the same-named key twice produces two rows with distinct ids; revoking a key that is already gone returns 404; toggling enabled to a state it is already in is a no-op that returns 204. You can safely retry a request that failed with a network error or 5xx.
Timeouts and retries
Scenema’s HTTP path targets sub-100ms response for auth and management endpoints. Generation endpoints can take longer depending on the model. Set your client timeout accordingly:
- Auth + management endpoints: 10 seconds is generous.
- Generation endpoints: 60 seconds or longer depending on the media type. Consult the endpoint-specific docs for typical latency.
For retries on network-level errors, use exponential backoff starting at 500ms with a cap around 30 seconds. On 429 responses, always respect the Retry-After value instead of backing off blindly.