Rate Limits#

Afosto applies rate limits to all API calls. Limits are dynamically applied and based on several factors including request volume, query complexity, and tenant activity.

·
Note:Exact rate limit thresholds are not published — they adapt to platform conditions to ensure fair usage across all tenants.

When you hit a rate limit#

When a rate limit is exceeded, the API returns an error in the standard GraphQL error format:

{
  "errors": [
    {
      "message": "Too many requests",
      "extensions": {
        "code": "RATE_LIMITED"
      }
    }
  ]
}

Best practices#

  • Cache responses — Avoid re-fetching data that hasn't changed. Cache order lists, product data, and other read-heavy resources on your side.
  • Request only what you need — Include only the fields your application actually uses. Smaller queries are cheaper and faster.
  • Back off on errors — When you receive a RATE_LIMITED error, wait before retrying. Use exponential backoff: wait 1s, then 2s, then 4s, etc.
  • Avoid polling — Use webhooks to react to events instead of repeatedly querying the API for changes.
  • Batch where possible — Some operations can be combined into a single request. For example, fetch all required order fields in one query instead of multiple separate calls.

Exponential backoff example#

async function fetchWithRetry(query: string, variables: object, maxRetries = 4) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const res = await fetch('https://afosto.app/graphql', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ query, variables }),
    })

    const json = await res.json()
    const rateLimited = json.errors?.some(
      (e: { extensions?: { code?: string } }) => e.extensions?.code === 'RATE_LIMITED'
    )

    if (!rateLimited) return json

    const delay = Math.pow(2, attempt) * 1000
    await new Promise((resolve) => setTimeout(resolve, delay))
  }

  throw new Error('Rate limit exceeded after retries')
}
Query Runnerhttps://afosto.app/graphql

No query loaded

Click play on any code block in the docs to load a query here.