Limits and errors
The API's request limits and rate-limit headers, what every error code means, and the rules for periods, currencies, rounding and pages.
Request limits
| Limit | Value |
|---|---|
| Per minute | 60 requests |
| Per day | 10,000 requests |
Both count for the whole account: all your keys and connected AI assistants together.
- The minute limit refills continuously: one request comes back every second, up to 60.
- The daily limit is a 24-hour window, not a calendar day. The
X-RateLimit-Reset-Dayheader says when it ends.
Rate-limit headers
Every answer to a request with a valid key carries:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per minute (60) |
X-RateLimit-Remaining | Requests left right now |
X-RateLimit-Reset | Seconds until the minute limit is full again |
X-RateLimit-Limit-Day | Requests allowed per day (10,000) |
X-RateLimit-Remaining-Day | Requests left today |
X-RateLimit-Reset-Day | Seconds until the daily window ends |
When a limit is reached, the answer is 429 rate_limited with a Retry-After
header: wait that many seconds, then send the request again.
Every answer, error or not, also carries X-Request-Id.
The shape of an error
Errors follow the standard "problem details" format (application/problem+json):
{
"type": "https://trueroyalties.com/docs/api/errors#invalid_request",
"title": "Invalid request",
"status": 400,
"code": "invalid_request",
"detail": "end_date must be on or after start_date.",
"issues": [
{
"path": "end_date",
"code": "invalid_value",
"message": "end_date must be on or after start_date."
}
],
"request_id": "req_8fK2mQ7xLp3nR9sT1vWy"
}- Test
codein your script. It never changes;detailis written for people and may be reworded. issueslists each invalid parameter. It only appears oninvalid_request.- Quote
request_idwhen you contact support.
Error codes
invalid_request · 400 — A parameter is not valid: an unknown value, a date
that does not exist, a period that is too long, a page cursor that is not ours.
issues says which parameter and why.
api_key_in_query · 400 — The key was sent in the URL. Send it in the
Authorization header, and revoke that key: it may already be in a log.
unauthorized · 401 — No key, or a key that is wrong or revoked. The answer
does not say which, on purpose.
subscription_inactive · 403 — The account's subscription has ended. The API
works again as soon as the subscription is active.
insufficient_scope · 403 — The key is not allowed to read. Every key created
today can read, so you should never see this code.
not_found · 404 — There is no endpoint at this path, or the thing you asked
for does not exist in your account. A series that belongs to another account
gets the same answer.
wrong_host · 404 — The request went to trueroyalties.com. Use
https://author.trueroyalties.com/api/v1.
method_not_allowed · 405 — The API only answers GET, because it is
read-only. The Allow header lists what it accepts.
rate_limited · 429 — A limit is reached. Wait the number of seconds in
Retry-After.
internal_error · 500 — Something failed on our side. Try again later; if it
keeps happening, send us the request_id.
timeout · 504 — The answer took longer than 30 seconds. Ask for a shorter
period.
Periods
The reports take either a relative range or two dates — never both.
range:today,yesterday,last_7_days,last_14_days,last_30_days,last_60_days,last_90_days,this_month,last_month,this_year,last_year,all_time. Without any period, you getlast_30_days, like the dashboard.start_dateandend_date(YYYY-MM-DD, both days included) go together. A period can be up to 366 days long. An end date after today counts as today.all_timeonly works on/reports/books.timezone(for exampleEurope/Paris) decides which day is "today" for arange. Without it, the API uses UTC.
Every report returns the period it actually used. /account, /books and
/series take no period.
Currencies and rounding
currencycan beUSD,GBP,EUR,JPY,CAD,INR,PLN,SEK,BRL,MXNorAUD. By default, your reporting currency (or USD if it is not one of these).- Amounts are numbers rounded to the currency's smallest unit: cents, or whole yen. Net profit is calculated before rounding, so the rounded lines of a report can differ from its rounded total by a cent.
- Ratios are decimals: a
marginof0.25means 25 %. nullmeans "does not exist", never zero. A margin without royalties isnull, not0.- Free downloads never count as royalties. They have their own endpoint,
/free-units.
Filters and pages
- Filters take comma-separated values:
marketplaces=US,UK,DE. An unknown value is refused with400 invalid_request, naming it.GBis accepted for the United Kingdom. - Long lists come in pages.
limitsets the page size, from 1 to 100 (50 by default). Whenhas_moreistrue, sendnext_cursorback ascursorto get the next page.