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.

Deals

Read and write deal records — Cirrus Insight's pipeline / opportunity objects. Deals are the parent that 8Ps and Q&As hang off; they carry a schema-driven customFields payload and reference the underlying account.

OperationScope required
Read (GET)deals:read
Create / updatedeals:write

Write endpoints require Idempotency-Key on every call. Same 24-hour replay window as the scheduling endpoints.

Endpoints on this page

MethodEndpointDescription
GET/api/v1alpha1/dealsList deals visible to the org. Filter by account, stage, owner, close date. Details ↓
GET/api/v1alpha1/deals/{dealId}Fetch one deal's full record — including customFields and 8P pointers. Details ↓
GET/api/v1alpha1/deals/by-sourceLook up a deal by CRM source id (Salesforce, etc.). Details ↓
POST/api/v1alpha1/dealsCreate a deal. Idempotency-Key required. Details ↓
PATCH/api/v1alpha1/deals/{dealId}Partial-merge update. Any subset of mutable fields. Details ↓
GET/api/v1alpha1/deals/{dealId}/meetingsList meetings linked to a deal. Details ↓
GET/api/v1alpha1/accounts/{accountId}/dealsList deals on one account. Requires accounts:read too. Details ↓

List deals

GET /api/v1alpha1/deals

Query parameters

ParameterTypeDescription
cursorstringStandard keyset cursor.
limitnumberClamped 1–100, default 25.
sortstringupdatedAt, createdAt, name, closeDate, amount. Default -updatedAt.
searchstring(optional) Case-insensitive substring on deal name.
accountIdstring(optional) Filter to one account.
stagestring(optional, repeatable) Filter to specific pipeline stages. Values are org-configured — discover via the schema attached to the deal.
ownerstring(optional) usr_... id. Filter to deals owned by one user.
closingBeforestring(optional) ISO 8601 date. Deals with closeDate ≤ this.
closingAfterstring(optional) ISO 8601 date. Deals with closeDate ≥ this.

Response

See the Dealmodel for the full field reference.

  • amount is always {value, currency}, not a bare number. Explicit currency prevents ambiguity in multi-currency orgs.
  • stage values are org-configured — the available stages come from the schema attached to the deal.
  • owner is the deal owner (Cirrus user accountable for the deal), not the org owner.

Errors

Standard pagination errors.


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

response = requests.get(
    "https://altus.cirrusinsight.com/api/v1alpha1/deals",
    headers={"X-Cirrus-Api-Key": token},
    params={"stage": "Proposal", "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["stage"] = "Proposal";
query["limit"] = "25";

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

var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var page = await response.Content.ReadAsStringAsync();
json
{
  "items": [
    {
      "id": "deal_...",
      "orgId": "org_...",
      "name": "Acme Q3 Expansion",
      "stage": "Proposal",
      "amount": {
        "value": 125000,
        "currency": "USD"
      },
      "closeDate": "2026-09-30",
      "account": {
        "id": "acct_...",
        "name": "Acme Corporation"
      },
      "owner": {
        "userId": "usr_...",
        "displayName": "Alex Rivera"
      },
      "sourceRefs": {
        "salesforce": {
          "id": "0061U00000abcXYZ"
        }
      },
      "createdAt": "2026-05-01T12:00:00Z",
      "updatedAt": "2026-07-14T09:30:00Z"
    }
  ],
  "nextCursor": null
}

Get a deal

GET /api/v1alpha1/deals/{dealId}

Full detail — includes the schema-driven customFields payload and pointers to the deal's 8P records.

Response

  • customFields — bag of untyped values per the deal's schema. Value types match the schema (string, number, boolean, array). A partner integrating deeply against a specific schema should fetch the schema definition once and cache the field shapes.
  • insightSummary — pointers to the eight 8P records for this deal. Any pointer is null when the 8P hasn't been created yet.
  • schemaVersion — pinned per deal. Allows partners to branch on shape changes.

Errors

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

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

deal_id = "deal_01H8YKQ2N9RXVT"
response = requests.get(
    f"https://altus.cirrusinsight.com/api/v1alpha1/deals/{deal_id}",
    headers={"X-Cirrus-Api-Key": token},
)
response.raise_for_status()
deal = 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 dealId = "deal_01H8YKQ2N9RXVT";
var response = await client.GetAsync(
    $"https://altus.cirrusinsight.com/api/v1alpha1/deals/{dealId}");
response.EnsureSuccessStatusCode();
var deal = await response.Content.ReadAsStringAsync();
json
{
  "id": "deal_...",
  "orgId": "org_...",
  "name": "Acme Q3 Expansion",
  "stage": "Proposal",
  "amount": { "value": 125000, "currency": "USD" },
  "closeDate": "2026-09-30",
  "account": { "id": "acct_...", "name": "Acme Corporation" },
  "owner": { "userId": "usr_...", "displayName": "Alex Rivera" },
  "primaryContact": { "id": "cont_...", "displayName": "Sample Guest" },
  "schemaId": "schm_...",
  "schemaVersion": 3,
  "customFields": {
    "leadSource": "Inbound - Webinar",
    "productLine": "Enterprise",
    "renewalMonths": 12
  },
  "insightSummary": {
    "profileId": "prof_...",
    "problemId": "prob_...",
    "painId": "pain_...",
    "powerId": "powr_...",
    "positionId": "posn_...",
    "phasesId": "phas_...",
    "processId": "proc_...",
    "planId": "plan_..."
  },
  "sourceRefs": {
    "salesforce": {
      "id": "0061U00000abcXYZ",
      "url": "https://acme.my.salesforce.com/0061U00000abcXYZ"
    }
  },
  "createdAt": "2026-05-01T12:00:00Z",
  "updatedAt": "2026-07-14T09:30:00Z"
}

Look up by source

GET /api/v1alpha1/deals/by-source

CRM-sync integrations wake up with a Salesforce opportunity id and need the corresponding Cirrus deal. This endpoint is the lookup path.

Query parameters

ParameterTypeDescription
sourceTypestringCurrently salesforce in v1alpha1. Room for hubspot, etc.
sourceIdstringThe external system's id (e.g., a Salesforce 0061U00000abcXYZ).

Both parameters required.

Response

Same shape as GET /api/v1alpha1/deals/{dealId}.

Errors

  • 404 deal-not-found — no deal in the calling org references the given (sourceType, sourceId) pair. Same 404 as an unknown Cirrus deal id — never leaks whether the external record exists.

bash
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/deals/by-source?sourceType=salesforce&sourceId=0061U00000abcXYZ" \
  -H "X-Cirrus-Api-Key: $TOKEN"
python
import requests

response = requests.get(
    "https://altus.cirrusinsight.com/api/v1alpha1/deals/by-source",
    headers={"X-Cirrus-Api-Key": token},
    params={"sourceType": "salesforce", "sourceId": "0061U00000abcXYZ"},
)
response.raise_for_status()
deal = 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["sourceType"] = "salesforce";
query["sourceId"] = "0061U00000abcXYZ";

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

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

Create a deal

POST /api/v1alpha1/deals

Headers

HeaderDescription
Idempotency-KeyRequired. Opaque client-generated string up to 255 chars. Same replay semantics as scheduling.

Request body

FieldRequiredNotes
nameyes
accountIdyesMust belong to the calling org.
stageyesMust be a valid stage in the deal's schema.
amount.currencyconditionalRequired when amount.value is set.
closeDatenoISO 8601 date.
ownerIdnoDefaults to the token's owner.
primaryContactIdno
schemaIdnoDefaults to the org's default deal schema.
customFieldsnoMust match the schema.
sourceRefs.salesforce.idnoSets the CRM cross-reference at creation. Prevents Salesforce sync from creating a duplicate later.

Response

201 Created with the newly-created deal in the same shape as GET /api/v1alpha1/deals/{dealId}.

Errors

  • 400 idempotency-key-required — header missing
  • 404 account-not-foundaccountId unknown or cross-org
  • 404 contact-not-foundprimaryContactId unknown or cross-org
  • 422 schema-mismatchcustomFields don't match the schema
  • 422 source-ref-conflict — another deal in your org already references the same (sourceType, sourceId) pair
  • 422 idempotency-key-conflict — same key, different body

bash
curl -s -X POST "https://altus.cirrusinsight.com/api/v1alpha1/deals" \
  -H "X-Cirrus-Api-Key: $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "Acme Q3 Expansion",
    "accountId": "acct_01H8YKQ2N9ACME",
    "stage": "Discovery",
    "amount": { "value": 125000, "currency": "USD" },
    "closeDate": "2026-09-30",
    "ownerId": "usr_01H8YKQ2N9ARIVERA",
    "sourceRefs": {
      "salesforce": { "id": "0061U00000abcXYZ" }
    }
  }'
python
import requests
import uuid

headers = {
    "X-Cirrus-Api-Key": token,
    "Idempotency-Key": str(uuid.uuid4()),
}

response = requests.post(
    "https://altus.cirrusinsight.com/api/v1alpha1/deals",
    headers=headers,
    json={
        "name": "Acme Q3 Expansion",
        "accountId": "acct_01H8YKQ2N9ACME",
        "stage": "Discovery",
        "amount": {"value": 125000, "currency": "USD"},
        "closeDate": "2026-09-30",
        "ownerId": "usr_01H8YKQ2N9ARIVERA",
        "sourceRefs": {
            "salesforce": {"id": "0061U00000abcXYZ"},
        },
    },
)
response.raise_for_status()
deal = response.json()
csharp
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

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

var body = new
{
    name = "Acme Q3 Expansion",
    accountId = "acct_01H8YKQ2N9ACME",
    stage = "Discovery",
    amount = new { value = 125000, currency = "USD" },
    closeDate = "2026-09-30",
    ownerId = "usr_01H8YKQ2N9ARIVERA",
    sourceRefs = new
    {
        salesforce = new { id = "0061U00000abcXYZ" },
    },
};

var request = new HttpRequestMessage(
    HttpMethod.Post,
    "https://altus.cirrusinsight.com/api/v1alpha1/deals")
{
    Content = new StringContent(
        JsonSerializer.Serialize(body),
        Encoding.UTF8,
        "application/json"),
};
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var deal = await response.Content.ReadAsStringAsync();
json
{
  "name": "Acme Q3 Expansion",
  "accountId": "acct_...",
  "stage": "Discovery",
  "amount": { "value": 125000, "currency": "USD" },
  "closeDate": "2026-09-30",
  "ownerId": "usr_...",
  "primaryContactId": "cont_...",
  "schemaId": "schm_...",
  "customFields": {
    "leadSource": "Inbound - Webinar"
  },
  "sourceRefs": {
    "salesforce": { "id": "0061U00000abcXYZ" }
  }
}

Update a deal

PATCH /api/v1alpha1/deals/{dealId}

Partial-merge update. Any subset of mutable fields.

Headers

HeaderDescription
Idempotency-KeyRequired.

Request body

Every field optional. Only present fields are updated.

  • customFields merges, doesn't replace. Top-level keys in the request are set; existing keys not in the request are preserved. To remove a field, pass null.

Response

200 OK with the updated deal.

Errors

Same as POST plus:

  • 404 deal-not-found — id unknown or cross-org
  • 409 deal-closed — deal is in a terminal stage (Won / Lost). Closed deals are immutable via the API in v1alpha1.

Closed-deal immutability. Reopening a Won/Lost deal is a sales-process concern the dashboard handles with confirmation flows. Deferred to a future write-scope expansion.


bash
curl -s -X PATCH "https://altus.cirrusinsight.com/api/v1alpha1/deals/deal_01H8YKQ2N9RXVT" \
  -H "X-Cirrus-Api-Key: $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "stage": "Negotiation",
    "amount": { "value": 145000, "currency": "USD" },
    "customFields": {
      "leadSource": "Inbound - Referral"
    }
  }'
python
import requests
import uuid

deal_id = "deal_01H8YKQ2N9RXVT"
headers = {
    "X-Cirrus-Api-Key": token,
    "Idempotency-Key": str(uuid.uuid4()),
}

response = requests.patch(
    f"https://altus.cirrusinsight.com/api/v1alpha1/deals/{deal_id}",
    headers=headers,
    json={
        "stage": "Negotiation",
        "amount": {"value": 145000, "currency": "USD"},
        "customFields": {
            "leadSource": "Inbound - Referral",
        },
    },
)
response.raise_for_status()
deal = response.json()
csharp
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;

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

var dealId = "deal_01H8YKQ2N9RXVT";
var body = new
{
    stage = "Negotiation",
    amount = new { value = 145000, currency = "USD" },
    customFields = new
    {
        leadSource = "Inbound - Referral",
    },
};

var request = new HttpRequestMessage(
    HttpMethod.Patch,
    $"https://altus.cirrusinsight.com/api/v1alpha1/deals/{dealId}")
{
    Content = new StringContent(
        JsonSerializer.Serialize(body),
        Encoding.UTF8,
        "application/json"),
};
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var deal = await response.Content.ReadAsStringAsync();
json
{
  "stage": "Negotiation",
  "amount": { "value": 145000, "currency": "USD" },
  "customFields": {
    "leadSource": "Inbound - Referral"
  }
}

List linked meetings

GET /api/v1alpha1/deals/{dealId}/meetings

List of meetings that produced 8P insights, Q&As, or other context for this deal.

Query parameters

ParameterTypeDescription
cursorstringStandard keyset cursor.
limitnumberClamped 1–100, default 25.
sortstringstartTime only. Default -startTime.
sincestring(optional) Cap the lookback.

Response

Lightweight meeting references (not full Meeting objects):

hasTranscript: true signals that a GET /api/v1alpha1/scheduled-meetings/{id}/transcript call will succeed. Pre-filtering here saves partners from having to try each meeting.

For the full Meeting object, click through to GET /api/v1alpha1/scheduled-meetings/{id}.

Errors

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

bash
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/deals/deal_01H8YKQ2N9RXVT/meetings?limit=25&since=2026-01-01" \
  -H "X-Cirrus-Api-Key: $TOKEN"
python
import requests

deal_id = "deal_01H8YKQ2N9RXVT"
response = requests.get(
    f"https://altus.cirrusinsight.com/api/v1alpha1/deals/{deal_id}/meetings",
    headers={"X-Cirrus-Api-Key": token},
    params={"limit": 25, "since": "2026-01-01"},
)
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 dealId = "deal_01H8YKQ2N9RXVT";
var query = HttpUtility.ParseQueryString(string.Empty);
query["limit"] = "25";
query["since"] = "2026-01-01";

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

var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
var page = await response.Content.ReadAsStringAsync();
json
{
  "items": [
    {
      "id": "mtg_...",
      "title": "Acme Discovery Call",
      "startTime": "2026-06-16T17:00:00Z",
      "endTime": "2026-06-16T17:30:00Z",
      "host": { "userId": "usr_...", "displayName": "Alex Rivera" },
      "hasTranscript": true
    }
  ],
  "nextCursor": null
}

List deals on an account

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

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

Requires both deals:read and accounts:read.

Query params identical to GET /api/v1alpha1/deals except accountId (nonsensical here).

Errors

  • 404 account-not-found
bash
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/accounts/acct_01H8YKQ2N9ACME/deals?stage=Proposal&limit=25" \
  -H "X-Cirrus-Api-Key: $TOKEN"
python
import requests

account_id = "acct_01H8YKQ2N9ACME"
response = requests.get(
    f"https://altus.cirrusinsight.com/api/v1alpha1/accounts/{account_id}/deals",
    headers={"X-Cirrus-Api-Key": token},
    params={"stage": "Proposal", "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 accountId = "acct_01H8YKQ2N9ACME";
var query = HttpUtility.ParseQueryString(string.Empty);
query["stage"] = "Proposal";
query["limit"] = "25";

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

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

Raleigh, NC — a Cirruspath, Inc. company