SciFig

API reference

Authentication and idempotency

Credentials, scopes, Idempotency-Key and request IDs for every SciFig API call.

Bearer authentication#

Send Authorization: Bearer <credential> on every request except GET /pricing, GET /openapi.json and GET /openapi.yaml. Credentials in query parameters or other headers are ignored.

  • API keys start with sk_live_. Create them under Settings → Developer; the key is shown once. Keep it on a server and never ship it in a browser or mobile app. We email you 7 days before a key expires.
  • OAuth access tokens start with sf_at_. MCP clients receive them after you approve the client; you can disconnect a client under Settings → Developer → Connected apps.
  • A missing, invalid, expired or revoked credential returns 401 UNAUTHORIZED. An account that cannot use the API (for example, one being deleted) returns 401 ACCOUNT_UNAVAILABLE.
  • Revoking a key stops new requests with it; jobs it already created keep running and stay readable with another credential of the same account.

Scopes#

ScopeGrantsAPI key type
figures:readGET /jobs, GET /jobs/{id}, GET /files/{file_id}, GET /creditsRead-only key; may never expire
figures:generateEverything in figures:read plus every POST endpointGenerate key; expires after 30 days, 90 days or 1 year; needs an active subscription or a credit-pack balance above zero

A request outside the credential’s scope returns 403 SCOPE_DENIED. Use a separate key per application and environment so that you can revoke one without affecting the others.

Idempotency#

  • Every create request (POST /images/*, /charts/*, /flowcharts/*) requires an Idempotency-Key header of 1–255 visible ASCII characters. A random UUID per request is the simplest choice. Uploads to POST /files may send one too (see files).
  • The same key with the same body returns the same job and never reserves credits again. For chart uploads the bytes of the data file are part of the body.
  • The same key with a different body returns 409 IDEMPOTENCY_CONFLICT. Concurrent requests with the same key never create two jobs: each returns the same job, or 409 IDEMPOTENCY_IN_PROGRESS with Retry-After: 1 while the first one is still being admitted.
  • Retry with the same key after a timeout, a network error, a 429 or a 503: it is the only way to be sure a job is not created twice.
  • Once the job exists, a retryable error (429, 503, 409 IDEMPOTENCY_IN_PROGRESS) or 500 INTERNAL_ERROR carries details.job_id. Retry with the same key or poll GET /jobs/{job_id}; do not switch to a new key, which would create and charge a second job. A job that was accepted but could not be read back is answered with 202 and status queued.
  • A refused request (for example 402 INSUFFICIENT_CREDITS) keeps that answer for its key. After topping up or upgrading, send it again with a new key.

OAuth clients#

  • MCP clients use OAuth 2.1 with PKCE. Access tokens (sf_at_…) are valid for 1 hour. A client that asks for the offline_access scope also receives a refresh token (sf_rt_…) valid for 30 days, so it stays connected until you disconnect it; without offline_access you sign in again when the access token expires.
  • Refresh tokens rotate: each refresh returns a new one. Presenting a refresh token that was already used is treated as reuse and revokes the tokens issued from it, so the client has to sign in again.
  • Dynamic client registration accepts a body of at most 16 KB, with limits on the length of each field and the number of redirect URIs. Token endpoint authentication is none (public clients with PKCE) or client_secret_basic.
  • A client registered but never authorized is deleted after 24 hours.
  • An authorization request with prompt=login or max_age asks for a fresh sign-in. If you are already signed in, SciFig asks you to confirm before signing you out and back in.
  • Rate limits for OAuth credentials count per client and per account, so other users of the same assistant do not use up your limits.

Request IDs#

Every response carries X-Request-Id; error bodies repeat it as error.request_id. It identifies the request in our logs without exposing anything else, so it is safe to log and to include when you contact support.