Rate Limits
- Request rate limit caps how fast you can call the API
- Monthly record quota caps how much distinct data you can extract over a calendar month.
They are measured separately and return separate 429 codes - branch on code, not on the HTTP status alone.
Both limits are keyed to your account (seat), not to an individual key. Issuing extra keys does not raise either budget - all of an account's keys draw from the same rate-limit window and the same monthly quota.
Request rate limit
-
200 requests per minute, per account, across all of that account's keys.
-
Applies to every bearer-token API - both the Public Company API (
/api/v1,/api/v2) and the Private Data API (/api/private/v1). -
The window is a fixed 60-second bucket. When you exceed it, further requests return
429 RATE_LIMITEDuntil the window rolls over.
A throttled response includes headers telling you how long to wait:
| Header | Meaning |
|---|---|
Retry-After | Seconds until the current window resets. |
X-RateLimit-Limit | The per-minute ceiling (200). |
X-RateLimit-Remaining | Requests left in the window (0 on a 429). |
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit of 200 requests/minute exceeded. Retry in 12s."
}
}Handling it: on a 429 RATE_LIMITED, sleep for Retry-After seconds and retry. A simple client-side cap of a few requests per second leaves comfortable headroom.
Monthly record quota
The Private Data API additionally meters the distinct records you pull each calendar month. (The Public Company API is not metered this way - it is governed only by the request rate limit above.)
-
20,000 distinct records per account, per calendar month.
-
A record is one company, one deal, or one investor. All three types share the single 20,000 budget. Repeats are only removed within the same type, so the same underlying organisation appearing as both a company and an investor counts once as each.
-
Re-pulling a record you have already fetched this month is free. The quota counts distinct records: only records you have not pulled yet this month draw down the budget. Your app can request the same companies, deals or investors as often as it needs - for example each time a user opens a page - without spending quota a second time.
-
The counter resets at 00:00 UTC on the 1st of each month.
What each request is charged
A request is charged for the records it returns: one per deal, company or investor. The companies and investors nested inside a deal (its target, buyers and investors) are references, not profiles, and are not charged. Only records you have not pulled yet this month count.
| Endpoint | Charged records |
|---|---|
POST /transactions, GET /transactions/{id} | Each deal returned. Its target, buyers and investors are not charged. |
GET /companies/{id}/fundings, /sellside, /buyside | Each deal returned. Its target, buyers and investors are not charged. |
GET /investors/{id}/investments | Each deal returned. Its target, buyers and investors are not charged. |
GET /companies/{id}, GET /investors/{id} | The one company or investor. The profile's deal_activity (companies) or stats (investors) block is not charged. |
POST /companies, GET /investors/{id}/portfolio | Each company returned |
POST /investors, GET /companies/{id}/investors, GET /investors/{id}/co_investors | Each investor returned. The shared deals listed on a co-investor are not charged. |
/companies/resolve, /investors/resolve (GET and POST) | Nothing |
GET /lookup/*, POST /transactions/aggregate | Nothing |
A page of 100 new transactions costs 100 records. Opening the full profile of a deal's target (GET /companies/{id}) or of one of its investors (GET /investors/{id}) is charged separately, as that company or investor. Asking for fewer fields with fields= does not change the charge. Keep limit small while you build and test.
Only successful (200) responses are charged. A request that fails - a 400 for an unknown filter value, a 403, 404, 429 or 500 - costs nothing. See Errors.
Records used by each call
Every successful Private Data API response reports what that call cost in meta.usage, so you can track spend per call without a separate request:
{
"data": [ ... ],
"meta": {
"page": 1,
"limit": 10,
"returned": 10,
"total": 37,
"has_more": true,
"usage": {
"records_billable": 10,
"records_charged": 4
}
}
}| Field | Meaning |
|---|---|
records_billable | Distinct companies, deals and investors in this response that count toward the quota, per the table above. |
records_charged | How many of those you had not pulled yet this month: what this call took from your quota. Re-pulled records are free, so this can be lower than records_billable, down to 0. |
A call that returns no billable records - resolve, lookups, aggregates, or an empty page - reports { "records_billable": 0, "records_charged": 0 }. meta.usage is added to every endpoint's meta, including profile and resolve responses that otherwise have no meta. Error responses don't carry it.
Your monthly standing (limit, used, remaining, reset) is in the quota headers below, not in the body.
Intended use
The Private Data API is licensed for showing Multiples data inside your product. It is not a bulk download service. Our Terms of Service do not allow systematic retrieval of the data, building a database similar to Multiples, or using the data with a large language model unless we expressly permit it. Automated jobs that page through full lists to copy the dataset break these terms, and we may suspend the keys they use.
Quota headers
Responses that held billable records also carry your monthly standing as headers, as does the MONTHLY_RECORD_LIMIT error:
| Header | Meaning |
|---|---|
X-Records-Limit | The monthly ceiling (20000). |
X-Records-Used | Distinct records charged so far this month, including this request. |
X-Records-Remaining | Records left before the cap. |
X-Records-Reset | Unix timestamp (seconds) of the next reset - 00:00 UTC on the 1st. |
The API tab of your account page shows the same count, split into companies, deals and investors.
When the quota is exhausted
If a request would pull new records beyond the remaining budget, the whole request is rejected with 429 MONTHLY_RECORD_LIMIT - no partial data is returned, and nothing is charged. The same X-Records-* headers are included so you can see exactly how much room is left.
{
"error": {
"code": "MONTHLY_RECORD_LIMIT",
"message": "Monthly limit of 20000 distinct records reached: this request needs 100 new record(s) but only 80 remain this month. Re-requesting records you've already pulled this month is free; request fewer new records, or wait for the reset on the 1st."
}
}Handling it: request fewer new records (a smaller limit, or a narrower filter), fall back to records you have already pulled this month (those never count), or wait for the monthly reset. If your workload legitimately needs a higher ceiling, contact us at hi@multiples.vc.