# Rate limits

Per-organization and per-endpoint quotas, response headers, and how to handle 429s.

Salfio enforces two parallel rate limits on authenticated `/v1` traffic:

- **Per organization** — 100 requests per minute across all endpoints.
- **Per endpoint** — 50 requests per minute, per normalized route.

Whichever limit is hit first returns `429`. Both limits are enforced consistently across all Salfio API instances — splitting traffic across multiple clients does not increase your quota.

## Response headers

Every successful `/v1` response includes:

| Header | Example | Meaning |
|----|----|----|
| `X-RateLimit-Limit` | `100` | The ceiling for the window (the lower of org / endpoint) |
| `X-RateLimit-Remaining` | `87` | Requests remaining in the current window |
| `X-RateLimit-Reset` | `1714058400` | Unix timestamp (seconds) when the window resets |

These headers are **not** returned on unauthenticated (`401`) responses — we do not want to help unauthenticated callers probe.

## 429 Too Many Requests

When you exceed a limit, Salfio returns:

    HTTP/1.1 429 Too Many Requests
    Retry-After: 37
    Content-Type: application/json

    {
      "error": {
        "code": "rate_limited",
        "message": "Rate limit exceeded. Retry after 37 seconds.",
        "details": {
          "scope": "organization",
          "limit": 100,
          "window_seconds": 60
        }
      }
    }

- **`Retry-After`** — seconds to wait before retrying. Always respect this. Salfio may temporarily raise it during incidents.
- **`error.details.scope`** — `"organization"` or `"endpoint"`. Helps you know whether to back off one call site or your whole integration.

## Handling strategy

- **Idempotent reads:** exponential backoff with jitter, capped at `Retry-After`. Five retries is plenty.
- **Writes:** do not blindly retry. On a conflict, fetch the current state and decide whether the write is still needed.
- **Bulk sync:** respect `X-RateLimit-Remaining` and pre-emptively sleep rather than burning against the limit — `429` costs you a round-trip.

## Higher limits

The ceilings above are the defaults for every organization. Custom limits are not exposed on `/v1` — contact support if your integration needs a higher quota.

## Related pages

- [Administrator Tools](./administrator-tools.md)
- [Agent Tools](./mcp-external-servers.md)
- [Assign a Slack channel to a client over the API](./guides-assign-slack-channel.md)
- [Authenticated health check](./api-reference-gethealth.md)
- [Authentication](./api-authentication.md)
- [Cards](./cards.md)
- [Changelog](./changelog.md)
- [Changelog](../changelog.md)
- [Connect a workspace](./getting-started-connect-workspace.md)
- [Connect an integration](./getting-started-connect-integration.md)

# Agent Instructions

This portal answers questions programmatically. To receive a synthesized,
source-cited answer instead of crawling page by page, append the `?ask=`
query parameter to any page URL on this site:

    /guides/quickstart?ask=how+do+I+authenticate

Optional parameters:

- `&goal=<what-you-are-trying-to-do>` steers the answer toward your
  objective (e.g. `&goal=write+a+python+client`).
- `&version=<label>` scopes the answer to a mounted version when the
  portal publishes more than one.

The response is `text/markdown`: the answer followed by a `# Sources` list
of the portal pages it was grounded in. Status codes are the contract:

- `200` — the answer; `402` — the portal owner’s plan or answer credits are
  exhausted (surface this to your operator; do NOT retry); `429` — you are
  rate-limited; back off for the `Retry-After` seconds; `503` — the answer
  lane is temporarily unavailable; fall back to crawling the `.md` pages.

For the full corpus map read `llms.txt` at the site root; for the tool
surface (search + page fetch as MCP tools) see `/mcp`.
