curl --request GET \
--url https://production-api.joinrings.com/v1/persons \
--header 'x-api-key: <api-key>'import requests
url = "https://production-api.joinrings.com/v1/persons"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://production-api.joinrings.com/v1/persons', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://production-api.joinrings.com/v1/persons",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://production-api.joinrings.com/v1/persons"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://production-api.joinrings.com/v1/persons")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://production-api.joinrings.com/v1/persons")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"items": [
{
"company_name": "<string>",
"email": "<string>",
"job_title": "<string>",
"last_activity_date": "<string>",
"linkedin_url": "<string>",
"name": "<string>",
"uuid": "<string>",
"city": "<string>",
"company_pathpower": {
"meta": {},
"score": 123,
"strength_label": "<string>"
},
"country": "<string>",
"current_company": {
"company_name": "<string>",
"logo_url": "<string>",
"uuid": "<string>",
"job_type": "<string>",
"source": "<string>"
},
"current_company_domain": "<string>",
"current_company_name": "<string>",
"current_job_title": "<string>",
"description": "<string>",
"email_3": "<string>",
"email_3_last_seen": "<string>",
"email_4": "<string>",
"email_4_last_seen": "<string>",
"email_5": "<string>",
"email_5_last_seen": "<string>",
"email_last_seen": "<string>",
"entity_lists": [
{
"name": "<string>",
"uuid": "<string>"
}
],
"facebook_url": "<string>",
"investor_types": [
"<string>"
],
"is_primary_company_recommended": true,
"job_changed_at": "<string>",
"last_activity": "<string>",
"last_contact_at": "<string>",
"logo_url": "<string>",
"my_next_meeting_at": "<string>",
"my_next_meeting_title": "<string>",
"next_meeting_at": "<string>",
"next_meeting_title": "<string>",
"next_meeting_with_user_uuid": "<string>",
"pathpower": {
"meta": {},
"score": 123,
"strength_label": "<string>"
},
"phone_numbers": [
"<string>"
],
"previous_job_ended_at": "<string>",
"priority_management": {
"rq": 123,
"rq_manual": 123,
"rq_math": 123
},
"secondary_email": "<string>",
"secondary_email_last_seen": "<string>",
"state": "<string>",
"strongest_relationships": [
{
"internal_user_person_uuid": "<string>",
"internal_user_uuid": "<string>",
"last_engaged_at": "<string>",
"name": "<string>",
"path_power_score": 123
}
],
"twitter_url": "<string>"
}
],
"page": 123,
"per_page": 123,
"total": 123,
"has_more": true,
"next_cursor": "<string>"
}List persons
Returns a paginated list of people visible to the tenant. All filter parameters are optional — omitting all of them returns all persons.
Filter parameters:
- name: Case-insensitive substring match on person’s display name
- email: Matches any of the person’s emails (case/whitespace-insensitive)
- linkedin_url: Case-insensitive substring match on LinkedIn profile URL
- company_uuid: Matches persons whose current/primary company is this company UUID
- job_title: Case-insensitive substring match on job title
- city: Case-insensitive substring match on city
- state: State/region name, resolved via pycountry (scoped to
countrywhen provided) - country: Country name or code, resolved via pycountry
- modified_since: ISO 8601 timestamp — return only persons modified at or after this time (e.g. ‘2025-01-01T00:00:00Z’)
Sort parameters:
- sort_by: name | last_activity_date (default: unsorted)
- order: asc | desc (default: asc)
Pagination:
- page: Page number (default: 1)
- per_page: Results per page, max 50 (default: 10)
- after: Opaque cursor from a previous response’s
next_cursor. Resumes immediately after that response’s last record, so concurrent writes can’t shift rows between pages the waypageallows.totalis not computed on this path — usehas_more.
Every response carries next_cursor, including page-numbered ones, so a
caller can start with page and switch to cursors mid-scan.
curl --request GET \
--url https://production-api.joinrings.com/v1/persons \
--header 'x-api-key: <api-key>'import requests
url = "https://production-api.joinrings.com/v1/persons"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://production-api.joinrings.com/v1/persons', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://production-api.joinrings.com/v1/persons",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://production-api.joinrings.com/v1/persons"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://production-api.joinrings.com/v1/persons")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://production-api.joinrings.com/v1/persons")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"items": [
{
"company_name": "<string>",
"email": "<string>",
"job_title": "<string>",
"last_activity_date": "<string>",
"linkedin_url": "<string>",
"name": "<string>",
"uuid": "<string>",
"city": "<string>",
"company_pathpower": {
"meta": {},
"score": 123,
"strength_label": "<string>"
},
"country": "<string>",
"current_company": {
"company_name": "<string>",
"logo_url": "<string>",
"uuid": "<string>",
"job_type": "<string>",
"source": "<string>"
},
"current_company_domain": "<string>",
"current_company_name": "<string>",
"current_job_title": "<string>",
"description": "<string>",
"email_3": "<string>",
"email_3_last_seen": "<string>",
"email_4": "<string>",
"email_4_last_seen": "<string>",
"email_5": "<string>",
"email_5_last_seen": "<string>",
"email_last_seen": "<string>",
"entity_lists": [
{
"name": "<string>",
"uuid": "<string>"
}
],
"facebook_url": "<string>",
"investor_types": [
"<string>"
],
"is_primary_company_recommended": true,
"job_changed_at": "<string>",
"last_activity": "<string>",
"last_contact_at": "<string>",
"logo_url": "<string>",
"my_next_meeting_at": "<string>",
"my_next_meeting_title": "<string>",
"next_meeting_at": "<string>",
"next_meeting_title": "<string>",
"next_meeting_with_user_uuid": "<string>",
"pathpower": {
"meta": {},
"score": 123,
"strength_label": "<string>"
},
"phone_numbers": [
"<string>"
],
"previous_job_ended_at": "<string>",
"priority_management": {
"rq": 123,
"rq_manual": 123,
"rq_math": 123
},
"secondary_email": "<string>",
"secondary_email_last_seen": "<string>",
"state": "<string>",
"strongest_relationships": [
{
"internal_user_person_uuid": "<string>",
"internal_user_uuid": "<string>",
"last_engaged_at": "<string>",
"name": "<string>",
"path_power_score": 123
}
],
"twitter_url": "<string>"
}
],
"page": 123,
"per_page": 123,
"total": 123,
"has_more": true,
"next_cursor": "<string>"
}Authorizations
Query Parameters
Page number, 1-indexed. Clamped to >= 1.
Results per page (default 10). Clamped to the range 1-50 (values outside are silently capped, not rejected).
Opaque cursor from a previous response's next_cursor. When supplied, the page starts immediately after the last record of that response and page is ignored — unlike page, this cannot skip or repeat records when the data changes mid-scan. Filters and sort must stay identical for the whole scan; changing one is a 400. Not supported by every list endpoint — those that support it return next_cursor.
Filter to persons whose primary company affiliation is this company UUID. Matches the response's current_company.uuid.
Filter to persons whose current job title contains this text. Persons without a recorded job title are excluded.
Case-insensitive substring match on city.
State/region name; resolved via pycountry and matched case-insensitively against the stored canonical name (scoped to country when provided).
Country name or code; resolved via pycountry and matched case-insensitively against the stored canonical name.
Return only persons modified at or after this ISO 8601 timestamp (e.g. '2025-01-01T00:00:00Z'). Tracks the last time Rings updated the record, from any source.
Field to sort by. Valid values: 'name', 'last_activity_date'
name, last_activity_date Sort order. Valid values: 'asc' (ascending) or 'desc' (descending)
asc, desc Case-insensitive substring match on the person's current job title (from the is_current=true employment row).
Case-insensitive substring match on the person's current company name.
Exact match on the person's current company domain (e.g. 'acme.com').
ISO 8601 timestamp — filter to persons whose current role started at or after this date (job_changed_at >= value).
ISO 8601 timestamp — filter to persons whose current role started at or before this date (job_changed_at <= value).
ISO 8601 timestamp — filter to persons whose most-recent prior job ended at or after this date.
ISO 8601 timestamp — filter to persons whose most-recent prior job ended at or before this date.
Comma-separated list of person UUIDs to fetch. When set, only these persons are returned (subject to other filters).