Base URL
Versioning
Current API version: v1.20.0. The/v1 prefix in the URL path is permanent.
Authentication
All requests require an API key in thex-api-key header. Keys start with the pk_ prefix and are scoped to a single tenant.
Per-user context
Tenant-scoped keys accept an optionalx-rings-user-id header. User-scoped keys are permanently bound to a single user.
Rate limiting
Both per-second and monthly limits apply. All responses includeX-RateLimit-* headers; 429 responses include a Retry-After header.
Pagination
List endpoints takepage and per_page (default 10, max 50) and return an items / page / per_page / total envelope. Values outside the range are capped rather than rejected, so read per_page back from the response.
Results are ordered by the endpoint’s sort_by column and then by a unique
tiebreaker, so paging over an unchanging result set never skips or repeats a
record. Records created or deleted mid-scan can still shift rows between pages —
offset pagination cannot protect against that.
Cursor pagination
GET /v1/persons and GET /v1/companies also accept a cursor, which is
immune to that mid-scan shifting and is the right choice for scanning a large
result set. Every response from these endpoints includes a next_cursor, so
you can start with page and switch to cursors without restarting:
next_cursor until has_more is false (the last page also
returns next_cursor: null).
Rules worth knowing:
- Filters and sort must stay identical for the whole scan. The cursor
encodes them; changing one returns
400rather than silently interleaving two different result sets.per_pagemay change freely between pages. pageandafterare mutually exclusive — sending both is a400.totalisnullon the cursor path. Counting the full filtered set is the slowest part of a list request and a cursor scan doesn’t need it. Usehas_more. Page-numbered requests still returntotalas before.- Cursors are opaque. Don’t parse or construct them; they are only valid for the query that produced them.
Request correlation
Every response includes anX-Request-Id header. Forward your own request ID by setting the same header on the request.
Errors
Every error returns{"error": "message"}, with the HTTP status as the machine-readable signal. Retry 429, 500 and 503; do not retry 400, 401, 403 or 404.
Webhooks
Rings does not currently send outbound webhooks. To track changes, pollGET /v1/persons and GET /v1/companies with modified_since.