Skip to content

Authentication & limits

Every request to the Renewr External API v2 is authenticated with an API key passed in the x-api-key header. The key identifies your tenant (no client identifier ever appears in URLs or payloads) and carries everything the server needs to authorize the call: your scopes, your daily rate limit, and an expiry date.

If you have not made your first call yet, start with Getting started.

The API key

Send the key on every request:

bash
curl https://api.renewr.example/api/v2/external/patents \
  -H "x-api-key: $RENEWR_API_KEY"

A key is a 64-character hexadecimal string. Renewr stores only a hash of it. If you lose a key, it cannot be recovered; it can only be replaced.

Obtaining and rotating keys

API keys are issued by the Renewr team: contact your account manager to request one. At creation, each key is assigned:

  • an expiry date (expiresAt): keys do not live forever; plan rotation before expiry,
  • a set of scopes (see below), snapshotted at creation; changing your grant means issuing a new key,
  • a daily call limit (see Rate limiting).

To rotate: request a new key from the Renewr team, deploy it to your integration, verify it works, then ask for the old key to be revoked. Since both keys can be valid simultaneously, rotation requires no downtime.

Keys are secrets

Treat your API key like a password. Use it server-side only. Never embed it in a browser application, a mobile app, or client-side JavaScript, and never commit it to version control. Anyone holding the key can read your portfolio and, depending on scopes, submit binding renewal instructions.

Scopes

Each key carries a list of scopes; each operation requires exactly one. A key can hold any combination: a read-only integration typically gets patents:read and invoices:read only.

ScopeUnlocks
patents:readgetPatents, getPatent, getPatentEvents, getPatentEvent, getPatentEventFees, getPatentEventsByPeriod, getInvoiceDocument, getInstructionReceiptDocument, getOfficialReceiptDocument
patents:instructions:writepostPatentInstructions
invoices:readgetInvoices, getInvoice
exchange-rate-freezes:writegetExchangeRateFreezes, getExchangeRateFreeze, putExchangeRateFreeze

Two things worth noting:

  • Documents, events and fees all sit under patents:read: the three PDF document endpoints and the cross-portfolio event period list need no extra scope.
  • All three exchange-rate-freeze operations require exchange-rate-freezes:write, including the two GETs. Freezing is a contractual capability (see Fees & FX); a key without this scope cannot even list frozen months.

Missing scope: 403 insufficient_scope

Calling an operation your key is not scoped for returns 403 with the stable code insufficient_scope and a requiredScope extension telling you exactly which scope to request:

json
{
  "type": "/errors/insufficient-scope",
  "title": "Insufficient scope",
  "status": 403,
  "detail": "The API key does not have the required scope for this operation.",
  "instance": "/api/v2/external/patent-instructions",
  "code": "insufficient_scope",
  "requiredScope": "patents:instructions:write",
  "requestId": "6f1c2a4e-8b3d-4f5a-9c7e-2d1b0a9f8e7d"
}

A key with an empty scope list grants nothing. There is no "no scopes means full access" fallback. All error responses follow the application/problem+json format described in Error handling.

403 is not always about scopes

A 403 with code forbidden (rather than insufficient_scope) is a business-level denial. One example: calling an exchange-rate-freeze endpoint when currency freezing is not enabled for your account. The fix is contractual; requesting a different scope does not resolve it. See Error handling.

Authentication failures

Two distinct 401 codes let you tell a bad key from an expired one:

CodeMeaningWhat to do
invalid_api_keyThe x-api-key header is missing, or the key is unknown.Check the header name and value; verify you are using the right key for the right environment.
api_key_expiredThe key is valid but past its expiresAt.Rotate: request a fresh key from the Renewr team.
json
{
  "type": "/errors/api-key-expired",
  "title": "API key expired",
  "status": 401,
  "detail": "API key has expired",
  "instance": "/api/v2/external/patents",
  "code": "api_key_expired",
  "requestId": "b4d0e7a2-1c9f-4e6b-8a3d-5f2e1c0b9a8d"
}

Alert on api_key_expired

Treat api_key_expired as an operational alarm. Retrying is pointless: no request will succeed until the key is replaced. Wire it to your monitoring so rotation happens before your integration goes dark.

Rate limiting

Each key has a daily call quota. Every authenticated request counts against it, and the counter resets at midnight, server local time. The reset is not at UTC midnight, and the quota does not use a rolling 24-hour window.

Every successfully authenticated response carries three headers so you always know where you stand:

HeaderMeaning
RateLimit-LimitYour key's daily quota.
RateLimit-RemainingCalls left today (the current call is already counted).
RateLimit-ResetSeconds until the next reset (midnight, server local time).

When the quota is exhausted: 429

Once the quota is spent, further calls return 429 with the stable code rate_limit_exceeded and a Retry-After header giving the number of seconds until the daily reset:

json
{
  "type": "/errors/rate-limit-exceeded",
  "title": "Rate limit exceeded",
  "status": 429,
  "detail": "Daily API call limit exceeded",
  "instance": "/api/v2/external/patent-events",
  "code": "rate_limit_exceeded",
  "requestId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"
}

The RateLimit-* trio is absent on 429

The RateLimit-Limit / RateLimit-Remaining / RateLimit-Reset headers appear on every successfully authenticated response. They are absent on the 429 itself. On a 429, read Retry-After instead.

  • On 429: stop and back off for the full Retry-After duration. The quota is daily and no request will succeed before the reset, so retrying earlier accomplishes nothing.
  • Monitor RateLimit-Remaining on normal responses and slow down proactively as it approaches zero, rather than running into the wall mid-batch.
  • Budget your polling. A monthly renewal cycle with sensible page sizes fits comfortably in a daily quota; see Syncing data for keeping call counts low. If your legitimate volume outgrows your quota, ask the Renewr team to raise your key's limit.

Request correlation: X-Request-Id

Every response carries an X-Request-Id header with a unique identifier for that request. The same value appears as requestId inside every application/problem+json error body, so an error you log client-side and the corresponding server-side trace share one correlation id.

Quote the X-Request-Id in every support request. It lets the Renewr team find the exact server-side trace of your call in seconds.

You may also send your own X-Request-Id request header: a non-empty inbound value is honored and echoed back instead of a server-generated one, letting you propagate your own correlation ids end to end.

bash
curl https://api.renewr.example/api/v2/external/patents \
  -H "x-api-key: $RENEWR_API_KEY" \
  -H "X-Request-Id: my-batch-2026-07-22-001" \
  -i

Next steps

Renewr External API v2. Access on invitation.