Error Handling

SignalStack returns consistent JSON error responses and appropriate HTTP status codes. This guide covers every error you might encounter and how to handle them in your application.

Error response format

Code
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "The 'claim' field is required and must be a non-empty string.",
    "docs": "https://signal-stack-ten.vercel.app/docs/api-reference/verify-claim",
    "request_id": "vrf_a1b2c3d4e5f6"
  }
}
FieldTypeDescription
error.codestringMachine-readable error code
error.messagestringHuman-readable description of the issue
error.docsstring (optional)Link to relevant documentation
error.request_idstringUnique request identifier for support/debugging

HTTP status codes

StatusCodeMeaningAction
200OKRequest succeeded
400INVALID_REQUESTMalformed request body or missing required fieldsFix request payload
401UNAUTHORIZEDMissing or invalid API keyCheck Authorization header
403FORBIDDENAPI key lacks permission for this endpointUpgrade plan or use correct key
404NOT_FOUNDEndpoint or resource not foundCheck URL
409CONFLICTRequest conflicts with current stateRetry with updated state
422VALIDATION_ERRORRequest body fails validationCheck field constraints
429RATE_LIMITEDRate limit exceededRetry after Retry-After
500INTERNAL_ERRORUnexpected server errorRetry with exponential backoff
502UPSTREAM_ERRORUpstream data source unavailableRetry after a delay
503SERVICE_UNAVAILABLETemporary service disruptionRetry with backoff

Common error codes

CodeHTTP StatusTypical Cause
INVALID_REQUEST400Missing required field, invalid JSON, wrong type
UNAUTHORIZED401Missing/wrong Authorization header, revoked key
FORBIDDEN403Key lacks endpoint access (e.g. media on Starter plan)
VALIDATION_ERROR422URL format invalid, claim too long, source unsupported
INSUFFICIENT_CREDITS402Account has insufficient credits for the request
RATE_LIMITED429Request rate exceeds plan limit
SOURCE_UNAVAILABLE502Requested data source is temporarily unreachable
CONTENT_TOO_LARGE413Document/media content exceeds size limit (50 MB)

Rate limiting headers

When you hit a rate limit (429), the response includes these headers:

Code
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1700000000
Retry-After: 3600
HeaderDescription
X-RateLimit-LimitMaximum requests per window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterSeconds to wait before retrying

Retry strategies

Use exponential backoff with jitter for retries:

Code
# Python — exponential backoff with jitter
import time
import random

def verify_with_retry(client, max_retries=5):
    for attempt in range(max_retries):
        try:
            return client.verify.claim(claim="...")
        except signalstack.RateLimitError as e:
            wait = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(min(wait, 60))
        except signalstack.ServerError as e:
            if attempt == max_retries - 1:
                raise
            wait = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(min(wait, 120))
    raise signalstack.MaxRetriesExceeded()
Code
// TypeScript — retry with backoff
async function verifyWithRetry(
  client: SignalStack,
  options: VerifyClaimOptions,
  maxRetries = 5,
) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await client.verify.claim(options)
    } catch (err) {
      if (err instanceof RateLimitError) {
        const wait = Math.min(2 ** attempt + Math.random(), 60)
        await sleep(wait * 1000)
      } else if (err instanceof ServerError) {
        if (attempt === maxRetries - 1) throw err
        const wait = Math.min(2 ** attempt + Math.random(), 120)
        await sleep(wait * 1000)
      } else {
        throw err
      }
    }
  }
  throw new MaxRetriesExceeded()
}

Which errors are safe to retry?

StatusSafe to retry?Notes
429YesUse Retry-After header or exponential backoff
500YesInternal error, retry with backoff (max 3)
502YesUpstream source unavailable, retry with backoff
503YesService unavailable, retry with backoff
400NoFix request payload before retrying
401NoFix API key before retrying
403NoUpgrade plan or use correct key
422NoFix validation errors in request

Next steps