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 where relationships drive revenue. It unifies people, companies, communications, relationships, 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. Use it to build custom apps, dashboards, workflows, analytics, and integrations directly on Rings data. For AI agents, the same data is available through the MCP server.

Base URL

Versioning

Current API version: v1.28.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.