Rate Limiting & Performance

Rate limiting & Performance

To ensure the stability and reliability of the API for everyone, we enforce the following limits:

  • Frequency: You are allowed to make 2 API calls per second. You can send multiple queries in the same request to help with the limit.
  • Timeout: There is a strict 30-second execution timeout. Any request taking longer than 30 seconds to process will be terminated with an error.

Optimization & Fair Use

To prevent timeouts, you must optimize your queries to fetch only the necessary data.

  • Filter by date: Use filters like UPDATED_AT or CREATED_AT to limit the scope.
  • Limit nesting: Avoid requesting deeply nested associations on large lists without pagination.

⚠️ Important:
Resource Usage Policy

Broad, unoptimized queries (e.g., fetching full history without filters) consume excessive server resources. We reserve the right to suspend API access if we detect patterns of abuse or consistently inefficient querying.

Query Optimization Examples

Here is a comparison between a risky query and an optimized one. The key difference lies in the use of date filters in the where argument.

✅ Optimized Query (Good)

This query is fast because it uses a highly selective filter, especially on dates (UPDATED_AT or CREATED_AT), ensuring that the API only processes recent data.

query OptimizedInvoices {
  Invoices(
    where: {
      AND: [
        {
          column: STATUS,
          operator: EQ,
          value: paid
        },
        {
          OR: [
            {
              column: UPDATED_AT,
              operator: GTE,
              value: "2025-12-01 00:00:00" # Filtering by a recent date is key
            },
            {
              column: CREATED_AT,
              operator: GTE,
              value: "2025-12-01 00:00:00"
            }
          ]
        }
      ]
    }
  ) {
    data {
      id
      label
    }
  }
}

✅ Unoptimized Query (Risk of Timeout)

This query is greedy: by omitting all date filters in the where argument, it forces the system to process potentially all historical records to find a match, leading to resource exhaustion and hitting the 30-second timeout.

query UnoptimizedInvoices {
  Invoices(
    where: { # Missing date constraints here
      OR: [
        {
          column: LABEL,
          operator: LIKE,
          value: "I0%"
        }
      ]
      # Without date constraints, this query might scan millions of records.
    }
  ) {
    data {
      id
      label
      # ... plus potentially deeply nested fields on large lists
    }
  }
}