Guides

    About 8 minutes

    DESIGN FOR RATE LIMITS.

    Read the limits on your key before a job starts, slow down from response headers, and retry without duplicating a write.

    account:read

    Steps

    1. 1. Get a key

      Workspace admins issue keys in the app at /app/api-keys. Start with a sandbox key: it is bound to a showroom workspace and can never touch live data. Keep the secret server-side.

      export QN_API_KEY="qn_sandbox_…"
      curl "$QN_BASE/me" -H "Authorization: Bearer $QN_API_KEY"
    2. 2. Read the allowance

      Call GET /limits before a large sync. It returns the burst and daily windows that apply to the current key, so the integration does not need a hardcoded allowance.

      curl "$QN_BASE/limits" \
        -H "Authorization: Bearer $QN_API_KEY"
    3. 3. Use the response headers

      Read RateLimit-Remaining and RateLimit-Reset on every response. When a 429 arrives, wait for Retry-After. The TypeScript and Python clients do this automatically for safe retries.

    4. 4. Make writes repeatable

      Send an Idempotency-Key with event and actuals writes. A retry with the same key returns the original result instead of creating a second write.

      curl -X POST "$QN_BASE/events" \
        -H "Authorization: Bearer $QN_API_KEY" \
        -H "Idempotency-Key: job_2026_09_20_batch_01" \
        -H "Content-Type: application/json" \
        --data @events.json

    Done when

    The integration completes without exceeding the declared windows, and replaying a write with the same idempotency key does not create a duplicate.