Deal Insights (8Ps)
The 8Ps are Cortex's structured deal-insight framework — eight schema-driven records per deal capturing what the sales team has learned across meetings. Names come from a sales methodology; the API treats each as a distinct schemaType on a record.
Each 8P is append-only — new insights accumulate as an ordered array under each field. Nothing is edited or deleted; the record is the history of what the team learned.
The eight types
| Name | Id prefix | What it captures |
|---|---|---|
| Profile | prof_ | Who the buyer is — role, seniority, tenure |
| Problem | prob_ | The problem they're trying to solve |
| Pain | pain_ | The consequences of not solving it |
| Power | powr_ | Decision-makers, budget authority, procurement path |
| Position | posn_ | Where Cirrus fits vs. competing options |
| Phases | phas_ | The buying-process phases they're moving through |
| Process | proc_ | The formal evaluation process (POCs, references, security review) |
| Plan | plan_ | The agreed close plan — dates, owners, deliverables |
Distinct prefix per type — a partner reading an id (prof_..., pain_...) sees the 8P type at a glance.
Scopes
| Operation | Scope required |
|---|---|
Read (GET) | insights:read |
| Append insight items | insights:write |
Writes require Idempotency-Key.
Endpoints on this page
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1alpha1/deals/{dealId}/insights | Fetch all 8Ps for a deal in one call. Details ↓ |
GET | /api/v1alpha1/deals/{dealId}/insights/{schemaType} | Fetch one 8P by type. Details ↓ |
POST | /api/v1alpha1/deals/{dealId}/insights/{schemaType} | Create the 8P record for this deal + type. Idempotent. Details ↓ |
POST | /api/v1alpha1/deals/{dealId}/insights/{schemaType}/fields/{fieldKey} | Append an insight item to a specific field. Details ↓ |
GET | /api/v1alpha1/insights/{insightId} | Fetch one 8P by its own id. Details ↓ |
Get all insights
GET /api/v1alpha1/deals/{dealId}/insights
Fetch all eight 8Ps for a deal in one request. Matches the dashboard's "Discovery" panel.
Response
- Every 8P type is a top-level key.
nullwhen the record hasn't been created yet for that deal. - Field keys match the
Deal.insightSummary.*Idpointers on the deal detail response.
See the Insightmodel for the full shape.
Errors
404 deal-not-found— id unknown or cross-org
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/deals/deal_01H8YKQ2N9RXVT/insights" \
-H "X-Cirrus-Api-Key: $TOKEN"import requests
deal_id = "deal_01H8YKQ2N9RXVT"
response = requests.get(
f"https://altus.cirrusinsight.com/api/v1alpha1/deals/{deal_id}/insights",
headers={"X-Cirrus-Api-Key": token},
)
response.raise_for_status()
insights = response.json()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}/insights");
response.EnsureSuccessStatusCode();
var insights = await response.Content.ReadAsStringAsync();{
"dealId": "deal_...",
"profile": { /* Insight shape */ },
"problem": { /* Insight shape */ },
"pain": null,
"power": { /* Insight shape */ },
"position": null,
"phases": null,
"process": { /* Insight shape */ },
"plan": null
}Get one insight by type
GET /api/v1alpha1/deals/{dealId}/insights/{schemaType}
schemaType is lowercase: profile, problem, pain, power, position, phases, process, plan.
Response
fields— map from schema-defined field key to an ordered array ofInsightItemobjects. Every schema defines which keys exist for its 8P type.fields[key][].itemId(insi_...) — stable id for the individual insight item. Referenced by Q&AlinkedInsightback-pointers.fields[key][].capturedFrom.meetingId + chunkId— jump-to-source pointer. Lets a partner walk from an insight to the exact transcript moment where it was captured.fields[key][].capturedBy.typeenum:user | cortex-agent. Manual-authored vs AI-authored.
Errors
400 invalid-schema-type—schemaTypeisn't one of the eight404 deal-not-found— deal id unknown or cross-org404 insight-record-not-found—(deal, schemaType)pair has no record yet
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/deals/deal_01H8YKQ2N9RXVT/insights/profile" \
-H "X-Cirrus-Api-Key: $TOKEN"import requests
deal_id = "deal_01H8YKQ2N9RXVT"
schema_type = "profile"
response = requests.get(
f"https://altus.cirrusinsight.com/api/v1alpha1/deals/{deal_id}/insights/{schema_type}",
headers={"X-Cirrus-Api-Key": token},
)
response.raise_for_status()
insight = response.json()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 schemaType = "profile";
var response = await client.GetAsync(
$"https://altus.cirrusinsight.com/api/v1alpha1/deals/{dealId}/insights/{schemaType}");
response.EnsureSuccessStatusCode();
var insight = await response.Content.ReadAsStringAsync();{
"id": "prof_...",
"schemaType": "profile",
"dealId": "deal_...",
"orgId": "org_...",
"schemaId": "schm_...",
"schemaVersion": 2,
"fields": {
"role": [
{
"itemId": "insi_...",
"value": "Director of Sales Ops",
"importance": "high",
"rationale": "Confirmed by attendee's LinkedIn and their intro on the discovery call",
"capturedFrom": {
"meetingId": "mtg_...",
"chunkId": "chnk_...",
"capturedAt": "2026-06-16T17:03:22Z"
},
"capturedBy": {
"type": "user",
"userId": "usr_...",
"displayName": "Alex Rivera"
}
}
],
"seniority": [ /* more items */ ],
"tenure": [ /* more items */ ]
},
"createdAt": "2026-06-16T17:03:22Z",
"updatedAt": "2026-07-14T09:30:00Z"
}Get one insight by id
GET /api/v1alpha1/insights/{insightId}
Same response shape as by-type. Use this when you hold a prof_... / prob_... / etc. id directly (e.g., from Deal.insightSummary.*Id or a Q&A cross-reference).
Errors
400 invalid-resource-id— id doesn't decode to one of the 8P prefixes404 insight-record-not-found— id unknown or cross-org
curl -s "https://altus.cirrusinsight.com/api/v1alpha1/insights/prof_01H8YKQ2N9RXVT" \
-H "X-Cirrus-Api-Key: $TOKEN"import requests
insight_id = "prof_01H8YKQ2N9RXVT"
response = requests.get(
f"https://altus.cirrusinsight.com/api/v1alpha1/insights/{insight_id}",
headers={"X-Cirrus-Api-Key": token},
)
response.raise_for_status()
insight = response.json()using System.Net.Http;
using System.Net.Http.Headers;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Cirrus-Api-Key", token);
var insightId = "prof_01H8YKQ2N9RXVT";
var response = await client.GetAsync(
$"https://altus.cirrusinsight.com/api/v1alpha1/insights/{insightId}");
response.EnsureSuccessStatusCode();
var insight = await response.Content.ReadAsStringAsync();Create an insight record
POST /api/v1alpha1/deals/{dealId}/insights/{schemaType}
Create the 8P record for this deal + type. Idempotent — repeated calls when the record already exists return 200 OK with the existing record.
Headers
| Header | Description |
|---|---|
Idempotency-Key | Required. |
Request body
Empty body OK. Optional schemaId field overrides the org default:
Response
201 Created— new record. Response is the record with emptyfields.200 OK— record already existed. Response is the existing record.
Errors
400 idempotency-key-required400 invalid-schema-type404 deal-not-found422 schema-not-found— explicitschemaIddoesn't resolve, or org has no default deal schema
curl -s -X POST "https://altus.cirrusinsight.com/api/v1alpha1/deals/deal_01H8YKQ2N9RXVT/insights/profile" \
-H "X-Cirrus-Api-Key: $TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"schemaId": "schm_01H8YKQ2N9RXVT"}'import requests
import uuid
deal_id = "deal_01H8YKQ2N9RXVT"
schema_type = "profile"
headers = {
"X-Cirrus-Api-Key": token,
"Idempotency-Key": str(uuid.uuid4()),
}
response = requests.post(
f"https://altus.cirrusinsight.com/api/v1alpha1/deals/{deal_id}/insights/{schema_type}",
headers=headers,
json={"schemaId": "schm_01H8YKQ2N9RXVT"},
)
response.raise_for_status()
insight = response.json()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 schemaType = "profile";
var body = new { schemaId = "schm_01H8YKQ2N9RXVT" };
var content = new StringContent(
JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
var request = new HttpRequestMessage(
HttpMethod.Post,
$"https://altus.cirrusinsight.com/api/v1alpha1/deals/{dealId}/insights/{schemaType}")
{
Content = content
};
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var insight = await response.Content.ReadAsStringAsync();{}{ "schemaId": "schm_..." }Append an insight item
POST /api/v1alpha1/deals/{dealId}/insights/{schemaType}/fields/{fieldKey}
The "add insight" action. Appends to the array at fields[fieldKey].
Append-only. No update, no delete. New understanding is captured as a new item; the history is preserved.
Headers
| Header | Description |
|---|---|
Idempotency-Key | Required. |
Request body
| Field | Required | Notes |
|---|---|---|
value | yes | Type per schema (string, number, structured). |
importance | no | low / medium / high. Default medium. |
rationale | no | Free-text. Why this matters. |
capturedFrom.meetingId | no | Required when capturedFrom is present. |
capturedFrom.chunkId | no | Optional. Points at the specific transcript moment. |
Response
200 OK with the updated 8P record — same shape as GET, with the newly-appended item included in fields[fieldKey].
Errors
400 idempotency-key-required404 insight-record-not-found— call the create endpoint first404 meeting-not-found—capturedFrom.meetingIdunknown or cross-org422 insight-field-invalid—fieldKeyisn't in the schema, orvaluedoesn't match the field's type422 idempotency-key-conflict— same key, different body
curl -s -X POST "https://altus.cirrusinsight.com/api/v1alpha1/deals/deal_01H8YKQ2N9RXVT/insights/profile/fields/role" \
-H "X-Cirrus-Api-Key: $TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"value": "Director of Sales Ops",
"importance": "high",
"rationale": "Confirmed by attendee'"'"'s LinkedIn and their intro on the discovery call",
"capturedFrom": {
"meetingId": "mtg_01H8YKQ2N9RXVT",
"chunkId": "chnk_01H8YKQ2N9RXVT"
}
}'import requests
import uuid
deal_id = "deal_01H8YKQ2N9RXVT"
schema_type = "profile"
field_key = "role"
headers = {
"X-Cirrus-Api-Key": token,
"Idempotency-Key": str(uuid.uuid4()),
}
body = {
"value": "Director of Sales Ops",
"importance": "high",
"rationale": "Confirmed by attendee's LinkedIn and their intro on the discovery call",
"capturedFrom": {
"meetingId": "mtg_01H8YKQ2N9RXVT",
"chunkId": "chnk_01H8YKQ2N9RXVT",
},
}
response = requests.post(
f"https://altus.cirrusinsight.com/api/v1alpha1/deals/{deal_id}/insights/{schema_type}/fields/{field_key}",
headers=headers,
json=body,
)
response.raise_for_status()
insight = response.json()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 schemaType = "profile";
var fieldKey = "role";
var body = new
{
value = "Director of Sales Ops",
importance = "high",
rationale = "Confirmed by attendee's LinkedIn and their intro on the discovery call",
capturedFrom = new
{
meetingId = "mtg_01H8YKQ2N9RXVT",
chunkId = "chnk_01H8YKQ2N9RXVT"
}
};
var content = new StringContent(
JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
var request = new HttpRequestMessage(
HttpMethod.Post,
$"https://altus.cirrusinsight.com/api/v1alpha1/deals/{dealId}/insights/{schemaType}/fields/{fieldKey}")
{
Content = content
};
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var insight = await response.Content.ReadAsStringAsync();{
"value": "Director of Sales Ops",
"importance": "high",
"rationale": "Confirmed by attendee's LinkedIn and their intro on the discovery call",
"capturedFrom": {
"meetingId": "mtg_...",
"chunkId": "chnk_..."
}
}