docs

Errors and retries

Which errors to retry, how long to wait, and how to make a retry safe with an idempotency key.

Most errors mean the request itself must change, and sending it again gives the same answer. A few mean "not now": those are worth retrying, after the wait the API tells you.

You need: an API key in TYPESAFE_API_KEY. Set TYPESAFE_BASE_URL only if you call a gateway other than https://api.sieve.one.

Retry or fix

StatusRetry?What to do
400, 404, 405, 413, 415, 422NoFix the request: model name, body shape, size or encoding. The body says what is wrong.
401NoCheck the key. A missing, mistyped, expired or revoked key is always 401.
403NoThe key is valid but not allowed: IP allowlist, access level, model list, or a suspended organisation.
429 with retry-afterYesA rate limit. Wait retry-after seconds, then retry.
429 without retry-afterNot soonNo credit left or a daily limit reached. Top up or wait for the daily reset.
500, 504YesRetry with exponential backoff.
503, 529Yes, unless x-should-retry: falseModel briefly unavailable or overloaded. Wait retry-after if present. x-should-retry: false means it was switched off on purpose.

Every response carries a request ID: x-typesafe-request-id on System One and /v1/models, x-request-id on /v1/decisions. Log it, and quote it when you write to support@sthanika.ai. The full list of bodies is on Errors.

Match on the status code and error type

error_type (System One) and error.type / error.code (/v1/decisions) are stable. The message is for people and may be reworded.

Make retries safe

Send an Idempotency-Key header with a value you generate once per logical request and reuse on every retry of it. A second request with the same key from the same API key within 60 seconds of a success gets the first response back (with Sieve-Idempotent-Replayed: true) instead of being answered and billed again. Without the header, identical bodies from the same key within 60 seconds are also de-duplicated.

A retry loop

The examples use only the standard library of each language. They retry 429 (only with retry-after), 500, 503, 504, 529 and network errors, at most four attempts, and stop at once on everything else.

import json
import os
import random
import time
import urllib.error
import urllib.request
import uuid

BASE_URL = os.environ.get("TYPESAFE_BASE_URL", "https://api.sieve.one")
API_KEY = os.environ["TYPESAFE_API_KEY"]
RETRYABLE = {429, 500, 503, 504, 529}


def system_one(body, max_attempts=4):
    data = json.dumps(body).encode()
    idempotency_key = str(uuid.uuid4())  # the same key on every attempt
    for attempt in range(1, max_attempts + 1):
        request = urllib.request.Request(
            f"{BASE_URL}/v1/systemone",
            data=data,
            method="POST",
            headers={
                "Authorization": f"Bearer {API_KEY}",
                "Content-Type": "application/json",
                "Idempotency-Key": idempotency_key,
            },
        )
        try:
            with urllib.request.urlopen(request, timeout=60) as response:
                return json.load(response)
        except urllib.error.HTTPError as error:
            detail = error.read().decode()
            retry_after = error.headers.get("retry-after")
            request_id = error.headers.get("x-typesafe-request-id")
            give_up = (
                error.code not in RETRYABLE
                or attempt == max_attempts
                or error.headers.get("x-should-retry") == "false"
                or (error.code == 429 and retry_after is None)  # no credit or a daily limit
            )
            if give_up:
                raise RuntimeError(f"HTTP {error.code} (request {request_id}): {detail}") from None
            delay = float(retry_after) if retry_after else min(2 ** attempt, 20) * random.uniform(0.5, 1.0)
        except (urllib.error.URLError, TimeoutError):
            if attempt == max_attempts:
                raise
            delay = min(2 ** attempt, 20) * random.uniform(0.5, 1.0)
        time.sleep(delay)


answer = system_one({
    "model": "sieve-latest",
    "state": "I was charged twice. Please fix this ASAP.",
    "questions": {"billing": {"type": "noul", "instructions": "Is this message about billing?"}},
})
print(answer["answers"]["billing"]["noul"])

The TypeSafe SDKs already retry for you (2 retries by default, on 408, 429 and 5xx including 529, honouring retry-after). They also retry a 429 for an empty balance, which keeps failing until credit is added, so handle that case in your code. See SDKs. Use the loop above when you call the HTTP API directly.

See what an error looks like

Send an unknown model to see a 400 without spending credit:

curl -i https://api.sieve.one/v1/systemone \
  -H "Authorization: Bearer $TYPESAFE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "nope", "state": "x", "questions": {"q": {"type": "noul", "instructions": "y"}}}'
{ "detail": { "error_type": "api_usage_error", "message": "Unknown model: nope" } }

On /v1/decisions the same mistake uses the OpenAI shape:

{ "error": { "message": "Unknown model: nope", "type": "invalid_request_error", "param": "model", "code": "model_not_found" } }

Errors in the console

The console and its API answer every error with one shape:

{ "error": { "code": "TOPUP_BELOW_MINIMUM", "message": "That amount is below the minimum top-up. Enter a larger amount.", "fields": { "amount": "The minimum top-up is 500 INR, before GST." } } }
  • code is stable: one meaning per code. Match on it, not on message.
  • message is a short sentence that says what to do. It may be reworded.
  • fields names the form fields to fix. retryAfter (also the Retry-After header) says how many seconds to wait.
  • Error pages show a request ID. Quote it when you contact support.
CodeHTTPMessageWhat to do
INVALID_CREDENTIALS401Email or password is incorrect. Try again, or reset your password.Retry, or reset the password.
WRONG_PASSWORD400That password is incorrect. Try again.Re-enter the current password.
INVALID_CODE400That code didn't work. Check it and try again.Enter a fresh code.
EMAIL_NOT_VERIFIED403Verify your email first. Check your inbox for the link.Open the verification link.
PASSWORD_TOO_WEAK400Choose a stronger password, like a phrase of four or more words.Choose a longer phrase.
PASSWORD_TOO_SHORT400Use at least 8 characters (12+ recommended).Use 8+ (12+ recommended).
PASSWORD_TOO_LONG400Use at most 128 characters.Shorten it.
INVALID_EMAIL400Enter a valid email address, like name@company.com.Fix the address.
PASSWORD_CONTAINS_EMAIL400Don't use your email address in your password.Choose another password.
PASSWORD_TOO_COMMON400That password is too common. Try a longer phrase.Choose another password.
PASSWORD_BREACHED400That password has appeared in a data breach. Choose another.Choose another password.
TOKEN_EXPIRED410This link has expired. Ask for a new one below.Request a new link.
TOKEN_ALREADY_USED410This link has already been used. Ask for a new one if needed.Request a new link if needed.
TOKEN_INVALID400This link isn't valid. Ask for a new one below.Request a new link.
RATE_LIMITED429Too many requests. Wait a moment, then try again.Wait retryAfter seconds.
GATEWAY_UNAVAILABLE503The Sieve API isn't responding. Try again in a moment.Retry shortly.
OAUTH_STATE_MISMATCH400Sign-in timed out or was opened in another tab. Try again.Start sign-in again in one tab.
OAUTH_EMAIL_UNVERIFIED400Your provider didn't confirm your email. Try another way to sign in.Use another sign-in method.
OAUTH_FAILED400We couldn't sign you in with that provider. Try again.Retry or use email and password.
SESSION_EXPIRED401Your session has expired. Please sign in again.Sign in again.
REAUTH_REQUIRED403For your security, sign in again to do this.Sign in again, then retry.
FORBIDDEN403You don't have permission to do that.Follow redirect, or reload the page.
OWNER_ONLY403Only admins can do this. Ask an admin of your organisation.Ask an organisation admin.
LAST_OWNER409An organisation needs at least one admin. Make someone else an admin first.Make someone else an admin first.
NOT_FOUND404That item no longer exists. Reload the page.Reload the page.
VALIDATION400Some fields need fixing. Check the highlighted fields.Fix the named fields.
INVITE_ONLY403Sign-up is invite-only for now. Ask an admin of your organisation to invite you.Ask an admin for an invite.
DISPOSABLE_EMAIL400Disposable emails aren't allowed. Use a work or personal email.Use a work or personal email.
INVITE_INVALID400This invite has expired or been cancelled. Ask for a new one.Ask for a new invite.
INVITE_WRONG_ACCOUNT403This invite is for a different email. Sign in with that address.Sign in as the invited email.
ALREADY_MEMBER409You're already a member of this organisation.Nothing; open the org.
ORG_LIMIT409You can belong to at most 10 organisations. Leave one first.Leave an organisation first.
PASSKEY_CANCELLED400Passkey request cancelled. Try again when you're ready.Retry when ready.
PASSKEY_FAILED400That passkey didn't work. Try again, or use your password.Retry, or use the password.
PASSKEY_EXISTS409This passkey is already registered on your account.Nothing to do.
INTERNAL500Sieve hit an unexpected error. Try again, or contact support.Retry; contact support with the request ID.
ACCOUNT_SUSPENDED403This account is suspended. Contact Sieve support to restore access.Contact support.
PASSWORD_CHECK_UNAVAILABLE503We couldn't check that password right now. Try again in a minute.Retry in a minute.
BODY_NOT_JSON415Send the request body as JSON.Send JSON.
BODY_TOO_LARGE413The request is too large. Send less data and try again.Send less data.
BODY_MALFORMED400The request body isn't valid JSON. Fix it and try again.Fix the JSON.
NOT_ORG_MEMBER403You're not a member of this organisation. Switch organisation.Switch organisation or reload.
MEMBER_NOT_FOUND404That person is no longer a member. Reload the page.Reload the members page.
CANNOT_REMOVE_SELF409You can't remove yourself. Use Leave organisation instead.Use Leave organisation.
MEMBER_LIMIT_REACHED409This organisation is full (200 members). Ask an admin to make room.Ask an admin to remove someone.
INVITE_NOT_FOUND404That invite no longer exists. Reload the page.Reload the page.
INVITE_PENDING_LIMIT409100 invites are pending. Cancel some before inviting more.Cancel old invites.
KEY_NOT_FOUND404That key no longer exists. Reload the page.Reload the keys page.
KEY_NOT_ACTIVE409This key is already revoked or expired. Reload the page.Reload; create a new key.
KEY_CREATOR_LEFT409This key's creator left the organisation. Revoke it instead.Revoke it; create a service key.
TOPUPS_DISABLED403Self-serve top-ups aren't available yet. Contact us to add credits.Contact support to add credits.
TOPUP_BELOW_MINIMUM400That amount is below the minimum top-up. Enter a larger amount.Enter a larger amount.
TOPUP_REJECTED400We couldn't start this top-up. Check the amount and try again.Fix the amount or contact support.
TOPUP_CHANGED409This top-up changed while it was being sent. Reload and try again.Reload and retry.
TAX_PROFILE_REQUIRED409Add your legal name, address and state in Billing → Tax, then try again.Complete Billing → Tax.
TAX_PROFILE_UNAVAILABLE503Tax profiles are unavailable. Contact support before adding credits.Contact support.
ORG_INACTIVE403This organisation isn't active. Contact support to restore it.Contact support.
PAYMENT_LIMIT_REACHED429Too many unfinished payments. Finish one, or try again in an hour.Finish one payment or wait.
PAYMENTS_UNAVAILABLE503Payments are unavailable right now. Try again in a minute.Retry in a minute.
AUTO_RECHARGE_UNAVAILABLE403Auto-recharge isn't available yet. Add credits by hand for now.Top up by hand.
EXPORT_COOLDOWN429An export was already requested. Try again after 24 hours.Wait for the cooldown.
EXPORT_NOT_FOUND404This export expired or was removed. Request a new one.Request a new export.
DELETION_BLOCKED409Deletion is blocked. Resolve the listed items, then try again.Resolve the listed items.
DELETION_NOT_PENDING409No pending deletion request was found.Nothing to do.
DELETION_ALREADY_SCHEDULED409Deletion is already scheduled.Nothing to do; cancel if needed.
SETTLEMENT_IN_PROGRESS409Payments are still settling. Wait for them to finish, then retry.Wait a few minutes, retry.
WALLET_FROZEN409The wallet is frozen. Contact support before closing this organisation.Contact support.
FINANCIAL_RECORDS_UNAVAILABLE503Financial records are unavailable. Try again later or contact support.Retry later or contact support.
SUPPORT_REQUEST_LIMIT429Too many support requests this hour. Reply to our email to add details.Reply to the support email instead.

Next steps

Last updated