Skip to content
Preview. The endpoints on this page are illustrative and are likely to change as they move toward general availability. Documentation is published in advance so you can start shaping your integration; treat request and response details as subject to revision.

Contacts

Read enriched contact records from Cirrus Insight's Cortex data model — the "people" objects on accounts.

contacts:read covers all endpoints on this page. The account-scoped listing endpoint additionally requires accounts:read — reading contacts on a specific account implies visibility of the account.

Endpoints on this page

MethodEndpointDescription
GET/api/v1alpha1/contactsList contacts visible to the org. Filter by search, email, account, or others. Details ↓
GET/api/v1alpha1/contacts/{contactId}Fetch one contact's full record — includes enrichment (title, LinkedIn URL, summary). Details ↓
GET/api/v1alpha1/contacts/{contactId}/activityPaginated activity timeline for one contact. Details ↓
GET/api/v1alpha1/accounts/{accountId}/contactsList contacts on one account. Requires accounts:read too. Details ↓

List contacts

GET /api/v1alpha1/contacts

Query parameters

ParameterTypeDescription
cursorstringStandard keyset cursor.
limitnumberClamped 1–100, default 25.
sortstringupdatedAt, createdAt, lastName, firstName. Prefix - for descending. Default -updatedAt.
searchstring(optional) Substring match on first name, last name, or email. Case-insensitive.
emailstring(optional) Exact match on primary email. Useful for lookup-by-email flows.
accountIdstring(optional) Filter to one account. Equivalent to /accounts/{id}/contacts.

Response

See the Contactmodel for the full field reference.

  • email filter is deliberately narrow — exact-match only. No wildcard, no regex. Prevents mass-scraping. Substring searches go through search.
  • account — lightweight {id, name} reference. null when the contact isn't linked to an account (rare; most contacts are enriched with an account guess by domain).

Errors

Standard pagination errors.


bash
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/contacts?search=guest&limit=25" \
  -H "X-Cirrus-Api-Key: $TOKEN"
python
import requests

response = requests.get(
    "https://altus.cirrusinsight.com/api/v1alpha1/contacts",
    headers={"X-Cirrus-Api-Key": token},
    params={"search": "guest", "limit": 25},
)
response.raise_for_status()
page = response.json()
csharp
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);

var query = HttpUtility.ParseQueryString(string.Empty);
query["search"] = "guest";
query["limit"] = "25";

var uri = new UriBuilder("https://altus.cirrusinsight.com/api/v1alpha1/contacts")
{
    Query = query.ToString()
}.Uri;

var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var page = await response.Content.ReadAsStringAsync();
json
{
  "items": [
    {
      "id": "cont_...",
      "orgId": "org_...",
      "firstName": "Sample",
      "lastName": "Guest",
      "displayName": "Sample Guest",
      "email": "guest@example.com",
      "phone": "+14155551234",
      "title": "Director of Sales Ops",
      "account": {
        "id": "acct_...",
        "name": "Acme Corporation"
      },
      "profileIconUri": null,
      "createdAt": "2026-05-01T12:00:00Z",
      "updatedAt": "2026-07-14T09:30:00Z"
    }
  ],
  "nextCursor": null
}

Get a contact

GET /api/v1alpha1/contacts/{contactId}

Response

  • summary — LLM-generated. May be stale.
  • sourceRefs.salesforce — Salesforce contact id + URL, when synced.

Only the primary email is exposed on the record. To look up a person by an alternate email address, query each candidate separately.

Errors

  • 404 contact-not-found — id unknown or cross-org

bash
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/contacts/cont_..." \
  -H "X-Cirrus-Api-Key: $TOKEN"
python
import requests

response = requests.get(
    f"https://altus.cirrusinsight.com/api/v1alpha1/contacts/{contact_id}",
    headers={"X-Cirrus-Api-Key": token},
)
response.raise_for_status()
contact = response.json()
csharp
using System.Net.Http;
using System.Net.Http.Headers;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);

var response = await client.GetAsync(
    $"https://altus.cirrusinsight.com/api/v1alpha1/contacts/{contactId}");
response.EnsureSuccessStatusCode();
var contact = await response.Content.ReadAsStringAsync();
json
{
  "id": "cont_...",
  "orgId": "org_...",
  "firstName": "Sample",
  "lastName": "Guest",
  "displayName": "Sample Guest",
  "email": "guest@example.com",
  "phone": "+14155551234",
  "title": "Director of Sales Ops",
  "account": {
    "id": "acct_...",
    "name": "Acme Corporation"
  },
  "profileIconUri": null,
  "linkedInUrl": "https://linkedin.com/in/sample-guest",
  "summary": "Sample Guest is a Director of Sales Ops at Acme Corporation ...",
  "sourceRefs": {
    "salesforce": {
      "id": "0031U00000abcXYZ",
      "url": "https://acme.my.salesforce.com/0031U00000abcXYZ"
    }
  },
  "createdAt": "2026-05-01T12:00:00Z",
  "updatedAt": "2026-07-14T09:30:00Z"
}

List activity

GET /api/v1alpha1/contacts/{contactId}/activity

Paginated activity timeline for one contact. Same shape as GET /api/v1alpha1/accounts/{id}/activity — meeting + email items filterable by type and since.

Query params: cursor, limit, sort (-occurredAt default), type (repeatable), since.

Errors

  • 404 contact-not-found — id unknown or cross-org

bash
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/contacts/cont_.../activity?type=meeting&limit=25" \
  -H "X-Cirrus-Api-Key: $TOKEN"
python
import requests

response = requests.get(
    f"https://altus.cirrusinsight.com/api/v1alpha1/contacts/{contact_id}/activity",
    headers={"X-Cirrus-Api-Key": token},
    params={"type": "meeting", "limit": 25},
)
response.raise_for_status()
page = response.json()
csharp
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);

var query = HttpUtility.ParseQueryString(string.Empty);
query["type"] = "meeting";
query["limit"] = "25";

var uri = new UriBuilder(
    $"https://altus.cirrusinsight.com/api/v1alpha1/contacts/{contactId}/activity")
{
    Query = query.ToString()
}.Uri;

var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var page = await response.Content.ReadAsStringAsync();

List contacts on an account

GET /api/v1alpha1/accounts/{accountId}/contacts

Convenience wrapper equivalent to GET /api/v1alpha1/contacts?accountId={id}.

Requires both contacts:read and accounts:read. Reading contacts by account implies visibility of the account. A partner with only contacts:read who calls this endpoint gets 403 insufficient-scope with requiredScope: "accounts:read".

Query params identical to GET /api/v1alpha1/contacts except accountId and email filters (nonsensical here). The search filter still applies.

Response

Same shape as GET /api/v1alpha1/contacts.

Errors

  • 404 account-not-found — id unknown or cross-org
bash
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/accounts/acct_.../contacts?limit=25" \
  -H "X-Cirrus-Api-Key: $TOKEN"
python
import requests

response = requests.get(
    f"https://altus.cirrusinsight.com/api/v1alpha1/accounts/{account_id}/contacts",
    headers={"X-Cirrus-Api-Key": token},
    params={"limit": 25},
)
response.raise_for_status()
page = response.json()
csharp
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);

var query = HttpUtility.ParseQueryString(string.Empty);
query["limit"] = "25";

var uri = new UriBuilder(
    $"https://altus.cirrusinsight.com/api/v1alpha1/accounts/{accountId}/contacts")
{
    Query = query.ToString()
}.Uri;

var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var page = await response.Content.ReadAsStringAsync();

Raleigh, NC — a Cirruspath, Inc. company