Pulse IntelligenceAPI Docs

Rate limits and errors

Quota defaults, rate-limit headers, and the error envelope shapes you'll encounter

Every /v1/ request is metered against your organization's quota. Whether a response carries rate-limit headers depends on whether the request reached the quota check at all — most do, but a request that fails before that point doesn't (see Rate-limit headers below for the cases). This guide covers the defaults, the headers, what a 429 looks like, and the error shapes used across the API.

Quota defaults

These are the platform defaults applied to every organization. Your organization's limits may differ — contact Pulse if you need higher limits.

LimitDefault
Queries per minute60
Queries per day10,000
Rows returned per day500,000

An org's effective quota is the default merged with any per-org override on file — any override field that's set wins over the matching default. A quota can also be blocked outright (a hard kill switch, independent of whether you have headroom left) — a blocked org's keys get a 429 on every call until access is restored.

Rate-limit headers

Rate-limit headers appear on any response where your request reached the quota check — successful calls, filter/column validation errors, and ordinary rate-limit 429s all include them.

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1735689660
  • X-RateLimit-Limit — your queries-per-minute limit for the current window.
  • X-RateLimit-Remaining — how many requests you have left in the current minute window.
  • X-RateLimit-Reset — Unix timestamp (seconds) when the current minute window resets.

These headers reflect the minute window specifically — the day-level query and row quotas aren't exposed as headers, only as the 429 you'll get once you exceed them (see below).

A request that fails before that point carries no rate-limit headers. This list isn't exhaustive — anything that short-circuits ahead of the quota check falls in the same bucket — but the cases you're most likely to run into are:

  • A 401 — authentication runs first, so a bad or missing key never reaches the quota check.
  • A 400 from a malformed JSON body — the request body is parsed before the quota check runs, so a body that fails to parse is rejected during parsing, ahead of it.
  • The blocked-organization 429 (mcp_access_blocked, below) — the access-blocked check runs before the rate counters are consulted, so this particular 429 also has no rate-limit state behind it, unlike every other 429.

When you're rate limited

HTTP 429

Once you exceed a quota, the API returns 429 with a body identifying which limit you hit:

{
  "error": {
    "code": "mcp_rate_minute",
    "message": "MCP request rate exceeded (60/minute)."
  }
}

The code tells you which specific limit was exceeded:

CodeMeaning
mcp_rate_minutePer-minute query limit exceeded.
mcp_rate_dayPer-day query limit exceeded.
mcp_daily_rowsPer-day row quota exceeded (you've read too much data today, even if individual calls stayed under the query limits).
mcp_access_blockedYour organization's API access is blocked outright — contact Pulse.

The code values above carry the mcp_ prefix from the shared internal throttle these limits are implemented on top of — the same mechanism used by Pulse's chat and MCP surfaces. It's not public-API-specific naming, but it's exactly what you'll see on the wire, so match against these strings exactly rather than assuming a public_api_-style prefix.

Retry guidance

  • Always read the rate-limit headers rather than hardcoding your own assumption of the limit — your organization's effective quota can differ from the defaults above.
  • On a 429, back off before retrying. A minute-window limit (mcp_rate_minute) clears at X-RateLimit-Reset; a daily limit (mcp_rate_day, mcp_daily_rows) doesn't clear until the next UTC day.
  • Don't tight-loop retries on 429 — you'll keep hitting the same limit until its window resets.

The error envelope

Most error responses share one shape:

{
  "error": {
    "code": "...",
    "message": "..."
  }
}

Some errors carry additional fields alongside code and message — for example, a rejected filter field also returns which field and resource triggered it. Treat code and message as the guaranteed fields and anything else as extra context.

401 is the one exception — authentication failures use DRF's stock error shape instead of the envelope above:

{ "detail": "..." }

This applies to every authentication failure (missing header, malformed key, unknown key, revoked key) — see Authentication for why they're all indistinguishable by design. Every other error status (400, 429) uses the nested {"error": {...}} envelope.

There are no resource-level 404s on this API: a well-formed request to a documented path never 404s. An unknown company or asset id, an unsupported resource, or an unrecognized options endpoint all come back as a 400 invalid_argument rather than a 404 — "not found" is treated as a bad argument, not a missing route. A wrong or slash-less path is a different story and does 404 — see the trailing-slash note in Authentication.

Common error codes

These are the codes you can actually trigger by calling the API correctly but with bad input — not an exhaustive list of every internal error type.

CodeHTTP statusWhen you'll see it
invalid_argument400General bad input — an unknown company/asset id, an unsupported resource on /v1/filters/{resource}/, an unrecognized options_path, a non-integer limit, a bad logic value, or similar.
unsupported_filter_field400A search filters entry referenced a field outside the resource's curated vocabulary (see Filters).
unsupported_column400A search columns entry referenced a field outside the resource's curated vocabulary.
query_timeout408The query took too long to execute — reachable on the full-text search endpoints (POST /v1/people/search/, POST /v1/publications/search/) under a broad enough query. Narrow your search term (or add a company/date filter on publications) and retry.

Example 400 for a filter field outside the curated vocabulary:

{
  "error": {
    "code": "unsupported_filter_field",
    "message": "Unknown or unsupported filter field for the public API: 'internal_score'.",
    "field": "internal_score",
    "resource": "companies"
  }
}

Go deeper

  • Filters covers the curated filter vocabulary that drives most 400s on the search endpoints.
  • The API Reference documents the exact 400/401/429 responses for each endpoint.

On this page