Skip to main content
Rings is a relationship intelligence platform for businesses that win on their networks — investment firms, banks, recruiters, and BD and partnerships teams anywhere relationships drive revenue. It unifies people, companies, communications, and deal activity into a live relationship graph. The REST API gives you programmatic read and write access to that graph — contacts, companies, opportunities, notes, tasks, meetings, and relationship data — scoped by your workspace permissions. For AI agents, the same data is available through the MCP server.

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 the x-api-key header. Keys start with the pk_ prefix and are scoped to a single tenant.
See the Quickstart for a walkthrough.

Per-user context

Tenant-scoped keys accept an optional x-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 include X-RateLimit-* headers; 429 responses include a Retry-After header.

Pagination

List endpoints take page 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:
Keep following 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 400 rather than silently interleaving two different result sets. per_page may change freely between pages.
  • page and after are mutually exclusive — sending both is a 400.
  • total is null on the cursor path. Counting the full filtered set is the slowest part of a list request and a cursor scan doesn’t need it. Use has_more. Page-numbered requests still return total as 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 an X-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, poll GET /v1/persons and GET /v1/companies with modified_since.