Get Deal Detail
curl --request GET \
--url https://api.example.com/deals/{deal_id} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.example.com/deals/{deal_id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.example.com/deals/{deal_id}', 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://api.example.com/deals/{deal_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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://api.example.com/deals/{deal_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/deals/{deal_id}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/deals/{deal_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}Deals
Get a Deal
GET
/
deals
/
{deal_id}
Get Deal Detail
curl --request GET \
--url https://api.example.com/deals/{deal_id} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.example.com/deals/{deal_id}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.example.com/deals/{deal_id}', 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://api.example.com/deals/{deal_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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://api.example.com/deals/{deal_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/deals/{deal_id}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/deals/{deal_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}The richest read in this API — a single RPC (
rpc_get_deal_detail) assembles the deal plus everything the deal-detail page and every AI generator on this router need, in one round trip.
Auth
Requires a CRM read scope and an active organization on the token. Any ofcontacts:read, deals:read, companies:read, or activities:read qualifies, as does any *:manage scope — manage implies read.
The deal object
Most deals endpoints return or embed thisdeals table row shape. Rather than repeat it on every page, here it is once — other pages link back to this section.
| Field | Type | Notes |
|---|---|---|
id | string (uuid) | Primary key. |
org_id | string (uuid) | Owning organization. |
name | string | Deal name. |
account_id | string | null | Linked account (company). |
owner_id | string | null | Logto user id of the deal owner. |
stage_id | string | null | Current pipeline stage. |
value | number | null | Deal value in currency. |
currency | string | ISO 4217 code, default USD. |
close_date | string | null | Rep-entered expected close date (YYYY-MM-DD) — optional, never AI-derived. |
claimed_close_date | string | null | Snapshot of a previously claimed close date (forecast bookkeeping). |
won_at / lost_at | string | null | Timestamps set when the deal closes into a Won/Lost stage. |
lost_reason | string | null | Free-text loss reason. |
health_score | integer | null | Denormalized copy of the latest health snapshot’s score (0–100). |
health_last_computed_at | string | null | Timestamp of the last health computation. |
forecast_confidence | string | null | One of the sales-forecast categories (commit, best_case, upside, pipeline, closed, omitted) — not a high/medium/low scale. |
engagement_velocity | string | null | Free-text/enum velocity signal. |
last_activity_at | string | null | Timestamp of the most recent linked activity. |
tags | string[] | Tag names (see Tags); not foreign keys. |
custom_fields | object | Arbitrary org-defined key/value data. |
created_by / created_at / updated_at | Standard audit columns. | |
parent_deal_id | string | null | Parent deal, for renewal/expansion deals. |
source | string | null | Free-text origin. |
actual_close | string | null | Actual close date. |
close_reason / close_notes | string | null | Recorded when closing. |
champion_id | string | null | Contact id of the internal champion. |
notes | string | null | Free-text notes. |
win_probability | integer | null | 0–100. |
latest_brief | object | null | Cached copy of the most recent AI deal brief — see Generate a Deal Brief. |
archived_at | string | null | Soft-delete timestamp; List Deals always excludes archived rows. |
competitors_detected_at / competitors_detection_source | Set by competitor detection — see Detect Competitors. | |
geo_scope | "local" | "regional" | "international" | null | Deal’s geographic scope. |
Response
All deal object fields, plus:| Field | Type | Description |
|---|---|---|
account | object | null | {id, name, domain, industry, size_range}. |
stage | object | null | {id, name, color, position, pct_width, is_won, is_lost, is_closed, probability, is_hidden} — the current stage. |
stages | array | Every visible stage ordered by position, plus the deal’s current stage even if it happens to be hidden. |
contacts | array | Every linked contact: {contact_id, id, first_name, last_name, name, title, email, role, is_champion, last_touch, last_activity_date}. last_touch/last_activity_date are identical (max activity timestamp for that contact on this deal). |
health | object | null | Latest health snapshot: {score, trend, data_points, snapshot_at, factors: [{factor_name, name, score, max_score, status, evidence}]}, or null if never computed. See Refresh Health Score. |
brief | object | null | The deal’s latest_brief column if set, else the most recent deal_briefs row reshaped to {id, summary_text, summary, risks, opportunities, strategy_text, strategy, model_used, generated_at}. |
tasks | array | Open (incomplete) tasks only: {id, text, due_date, priority, assignee_id, source, is_completed, created_at}, ordered by priority then due date. |
competitors | array | {id, name, competitor_name, threat_level, notes} — from deal_competitors. |
latest_competitive_brief | object | null | {id, payload, generated_at, source} — the newest competitive-intelligence brief, if any. |
activities | array | The 20 most recent activities: {id, type, summary, subject, body, direction, occurred_at, created_at, owner_id, contact_id, contact_name}. |
Errors
| Status | Cause |
|---|---|
404 | No deal with that id in this org. |
⌘I