Close AI
Build Close AI desktop integrations with session analysis, prompt presets, coaching dashboards, scripts, and analytics settings through the Talkturo API.
{
"sessions": [
{
"id": "sess_7f2c91a4",
"user_id": "usr_a1b2c3d4",
"account_id": "acct_4e5f6a7b",
"title": "Discovery call with Northstar",
"session_type": "sales_call",
"started_at": "2025-02-12T14:00:00.000Z",
"ended_at": "2025-02-12T14:32:18.000Z",
"status": "completed",
"duration_seconds": 1938,
"updated_at": "2025-02-12T14:35:02.000Z"
}
],
"count": 1
}
{
"session": {
"id": "sess_7f2c91a4",
"user_id": "usr_a1b2c3d4",
"title": "Discovery call with Northstar",
"session_type": "sales_call",
"started_at": "2025-02-12T14:00:00.000Z",
"ended_at": "2025-02-12T14:32:18.000Z",
"status": "completed",
"duration_seconds": 1938,
"updated_at": "2025-02-12T14:35:02.000Z",
"created_at": "2025-02-12T14:00:00.000Z",
"parent_session_id": null
},
"transcripts": [
{
"id": "tr_91a2b3c4",
"session_id": "sess_7f2c91a4",
"start_at": "2025-02-12T14:00:04.000Z",
"end_at": "2025-02-12T14:00:18.000Z",
"speaker": "rep",
"text": "Thanks for taking the time to meet today.",
"lang": "en",
"created_at": "2025-02-12T14:00:19.000Z"
}
],
"messages": [],
"summary": null,
"analysis": null
}
{
"ok": true,
"title": "Northstar discovery call"
}
{
"ok": true,
"deleted": true
}
{
"analysis": {
"session_id": "sess_7f2c91a4",
"close_score": 82,
"score_breakdown": {
"discovery": 88,
"objection_handling": 76,
"next_steps": 82
},
"strengths": ["Clear discovery questions"],
"weaknesses": ["Limited objection follow-up"],
"risks": ["No confirmed procurement timeline"],
"objections": [],
"questions": {
"open": 8,
"closed": 3,
"deep": 4,
"missed": []
},
"personality": {
"type": "analytical"
},
"talk_metrics": {
"rep_talk_share_pct": 46,
"words_per_minute": 132
},
"script_coverage": {
"coverage_pct": 84
},
"language": "en",
"model": "close-ai",
"generated_at": "2025-02-12T14:40:00.000Z"
}
}
{
"presets": [
{
"id": "preset_8a2b3c4d",
"user_id": "usr_a1b2c3d4",
"title": "Discovery call review",
"prompt": "Evaluate discovery depth, qualification, and next steps.",
"is_default": true,
"is_template": true,
"created_at": "2025-02-10T09:00:00.000Z",
"updated_at": "2025-02-12T10:15:00.000Z"
}
]
}
{
"preset": {
"id": "preset_8a2b3c4d",
"user_id": "usr_a1b2c3d4",
"title": "Discovery call review",
"prompt": "Evaluate discovery depth, qualification, and next steps.",
"is_default": true,
"is_template": false,
"created_at": "2025-02-12T10:15:00.000Z",
"updated_at": "2025-02-12T10:15:00.000Z"
}
}
{
"analytics_system_prompt": "Focus on discovery quality and measurable next steps.",
"updated_at": "2025-02-12T10:15:00.000Z"
}
{
"analytics_system_prompt": "Focus on discovery quality and measurable next steps.",
"updated_at": "2025-02-12T10:20:00.000Z"
}
{
"kpis": {
"calls": 48,
"callsDeltaPct": 12.5,
"avgCloseScore": 76,
"avgDurationSeconds": 1840,
"activeMembers": 6,
"analyzedCount": 41
},
"coaching": {
"evaluations": 41,
"strengths": [
{ "label": "Discovery", "count": 22 }
],
"weaknesses": [
{ "label": "Objection handling", "count": 15 }
],
"risks": [
{ "label": "Unclear next steps", "count": 9 }
]
},
"objections": {
"total": 18,
"byCategory": [
{ "key": "budget", "count": 8, "avgCloseScore": 71 }
],
"byType": [
{ "key": "timing", "count": 5, "avgCloseScore": 74 }
],
"byIntensity": [
{ "key": "high", "count": 3, "avgCloseScore": 62 }
]
},
"questions": {
"open": 120,
"closed": 64,
"deep": 38,
"missed": [
{ "label": "Decision process", "count": 7 }
]
},
"personality": [
{ "type": "analytical", "count": 16 }
],
"language": {
"avgTalkSharePct": 48,
"avgWpm": 132,
"avgPatiencePct": 72,
"avgLongestMonologueSeconds": 46
},
"script": {
"calls": 39,
"avgCoveragePct": 81,
"avgOrderDeviationPct": 14,
"blocks": [
{ "name": "Discovery", "avgPct": 91 }
]
},
"scores": {
"distribution": [
{ "bucket": "0-39", "count": 2 },
{ "bucket": "40-59", "count": 7 },
{ "bucket": "60-79", "count": 20 },
{ "bucket": "80-100", "count": 12 }
],
"avg": 76
},
"durationDistribution": [
{ "bucket": "0-5m", "count": 3 },
{ "bucket": "5-10m", "count": 8 },
{ "bucket": "10-15m", "count": 14 },
{ "bucket": "15-30m", "count": 17 },
{ "bucket": "30m+", "count": 6 }
],
"trends": [
{
"date": "2025-02-12",
"calls": 4,
"avgCloseScore": 78
}
],
"members": [
{
"userId": "usr_a1b2c3d4",
"name": "Jordan Lee",
"calls": 12,
"evaluations": 10,
"avgCloseScore": 79,
"avgDurationSeconds": 1760,
"strengths": 8,
"weaknesses": 3,
"risks": 2,
"avgCoveragePct": 85,
"personality": "analytical"
}
]
}
{
"scripts": [
{
"id": "script_3c4d5e6f",
"name": "Enterprise discovery",
"content": {
"sections": [],
"prompts": []
},
"is_active": true,
"updated_at": "2025-02-12T11:00:00.000Z"
}
]
}
{
"script": {
"id": "script_3c4d5e6f",
"name": "Enterprise discovery",
"content": {
"sections": [],
"prompts": []
},
"is_active": false,
"updated_at": "2025-02-12T11:00:00.000Z"
}
}
{
"script": {
"id": "script_3c4d5e6f",
"name": "Enterprise discovery",
"content": {
"sections": [
{
"id": "section_discovery",
"name": "Discovery",
"type": "script",
"content": "What is driving this initiative?",
"next": [],
"position": {
"x": 120,
"y": 80
}
}
],
"prompts": [
{
"id": "prompt_budget",
"trigger": "budget",
"text": "Ask how the buying team evaluates investment.",
"enabled": true
}
]
},
"is_active": true,
"updated_at": "2025-02-12T11:05:00.000Z"
}
}
{
"ok": true
}
Close AI API
Use the Close AI API to manage desktop coaching sessions, generate session analysis, configure prompt presets and analytics settings, manage sales scripts, and retrieve workspace dashboards.
All Close AI endpoints use the authenticated browser Supabase session cookie. They do not use desktop JWT authentication. Send requests to https://app.talkturo.com with the session cookie included.
Endpoint summary
| Method | Path | Purpose |
|---|---|---|
GET | /api/close-ai/sessions | List Close AI sessions |
GET | /api/close-ai/sessions/{sessionId} | Get a session and its related data |
PATCH | /api/close-ai/sessions/{sessionId} | Rename or clear a session title |
DELETE | /api/close-ai/sessions/{sessionId} | Delete a session and related data |
POST | /api/close-ai/sessions/{sessionId}/analyze | Analyze a session transcript |
GET | /api/close-ai/prompts | List prompt presets |
POST | /api/close-ai/prompts | Create a prompt preset |
GET | /api/close-ai/settings | Get analytics settings |
PUT | /api/close-ai/settings | Update analytics settings |
GET | /api/close-ai/dashboard | Get workspace dashboard metrics |
GET | /api/close-ai/scripts | List workspace scripts |
POST | /api/close-ai/scripts | Create a workspace script |
PUT | /api/close-ai/scripts | Update a workspace script |
DELETE | /api/close-ai/scripts | Delete a workspace script |
Sessions
The sessions endpoints let you find recorded Close AI sessions, retrieve transcripts and analysis, rename sessions, delete sessions, and trigger analysis.
List sessions
GET /api/close-ai/sessions
Use query parameters to paginate results, search session titles, or limit results to a workspace.
Query parameters
Maximum number of sessions to return. Values are clamped to the range 1 through 100. Defaults to 50.
1100Number of sessions to skip before returning results. Defaults to 0.
Case-insensitive substring search against the session title.
Workspace slug. When provided, the response includes sessions for that workspace and legacy sessions without an account assignment.
Request
curl "https://app.talkturo.com/api/close-ai/sessions?limit=25&offset=0&q=discovery&account=acme-sales" \
-b "sb-session=authenticated-browser-session"
const response = await fetch(
"https://app.talkturo.com/api/close-ai/sessions?limit=25&offset=0&q=discovery&account=acme-sales",
{
credentials: "include",
}
);
const data = await response.json();
console.log(data.sessions);
Response
Sessions matching the supplied pagination, search, and workspace filters.
Unique session identifier.
Identifier of the user who owns the session.
Workspace identifier. Legacy sessions may have no workspace assignment.
Session title.
Type assigned to the session.
Session start timestamp.
Session end timestamp.
Current session status.
Session duration in seconds.
Timestamp of the most recent session update.
Number of sessions returned for the query.
Get a session
GET /api/close-ai/sessions/{sessionId}
Session identifier.
Request
curl "https://app.talkturo.com/api/close-ai/sessions/sess_7f2c91a4" \
-b "sb-session=authenticated-browser-session"
const response = await fetch(
"https://app.talkturo.com/api/close-ai/sessions/sess_7f2c91a4",
{
credentials: "include",
}
);
const data = await response.json();
console.log(data.session, data.transcripts, data.analysis);
Response
Session metadata.
Unique session identifier.
Identifier of the session owner.
Session title.
Type assigned to the session.
Session start timestamp.
Session end timestamp.
Current session status.
Session duration in seconds.
Timestamp of the most recent update.
Session creation timestamp.
Identifier of the parent session when this session was created from another session.
Transcript segments for the session. Returns an empty array when no transcript exists.
Transcript segment identifier.
Session identifier associated with the transcript segment.
Segment start timestamp.
Segment end timestamp.
Speaker label.
Transcript text.
Transcript language.
Transcript creation timestamp.
AI messages associated with the session. Returns an empty array when no messages exist.
Message identifier.
Session identifier associated with the message.
Message timestamp.
Message role.
Message content.
Token count for the message.
Model used to generate the message.
Message creation timestamp.
Generated session summary. Returns null when no summary exists.
Session identifier associated with the summary.
Summary generation timestamp.
Model used to generate the summary.
Full summary text.
Short summary.
Structured summary bullets.
Structured follow-up actions.
Tokens used to generate the summary.
Timestamp of the most recent summary update.
Generated coaching analysis. Returns null when no analysis exists.
Session identifier associated with the analysis.
Overall Close AI score.
Score breakdown by evaluation category.
Detected strengths.
Detected weaknesses.
Detected risks.
Detected objections.
Question analysis.
Detected personality information.
Conversation and speaking metrics.
Script coverage metrics.
Analysis language.
Model used to generate the analysis.
Analysis generation timestamp.
Rename a session
PATCH /api/close-ai/sessions/{sessionId}
An empty title clears the existing title.
Session identifier.
New session title. Pass an empty string to clear the title.
Request
curl -X PATCH "https://app.talkturo.com/api/close-ai/sessions/sess_7f2c91a4" \
-H "Content-Type: application/json" \
-b "sb-session=authenticated-browser-session" \
-d '{"title":"Northstar discovery call"}'
const response = await fetch(
"https://app.talkturo.com/api/close-ai/sessions/sess_7f2c91a4",
{
method: "PATCH",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
title: "Northstar discovery call"
})
}
);
const data = await response.json();
console.log(data.title);
Response
Whether the update succeeded.
The updated session title.
Delete a session
DELETE /api/close-ai/sessions/{sessionId}
Deleting a session also removes its transcripts, AI messages, summary, and analysis through the database cascade.
Session identifier.
Request
curl -X DELETE "https://app.talkturo.com/api/close-ai/sessions/sess_7f2c91a4" \
-b "sb-session=authenticated-browser-session"
const response = await fetch(
"https://app.talkturo.com/api/close-ai/sessions/sess_7f2c91a4",
{
method: "DELETE",
credentials: "include"
}
);
const data = await response.json();
console.log(data.deleted);
Response
Whether the delete request completed without a database error.
Indicates that the delete operation completed.
Analyze a session
POST /api/close-ai/sessions/{sessionId}/analyze
The session must contain a transcript. The optional workspace slug attributes analysis for legacy sessions.
Session identifier.
Workspace slug used for workspace attribution of legacy sessions.
Request
curl -X POST "https://app.talkturo.com/api/close-ai/sessions/sess_7f2c91a4/analyze" \
-H "Content-Type: application/json" \
-b "sb-session=authenticated-browser-session" \
-d '{"accountSlug":"acme-sales"}'
const response = await fetch(
"https://app.talkturo.com/api/close-ai/sessions/sess_7f2c91a4/analyze",
{
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
accountSlug: "acme-sales"
})
}
);
const data = await response.json();
console.log(data.analysis.close_score);
Response
Generated analysis for the session.
Session identifier.
Overall Close AI score.
Score by evaluation category.
Detected strengths.
Detected weaknesses.
Detected risks.
Detected objections.
Question analysis.
Detected personality information.
Conversation metrics.
Script coverage metrics.
Language used for the analysis.
Model used to generate the analysis.
Analysis generation timestamp.
Analysis requests can return 401 for an unauthenticated session, 404 when the session does not exist, 422 when the session has no transcript, 502 when analysis generation fails, or 500 when the generated analysis cannot be saved.
Prompts
Prompt presets provide reusable prompts for Close AI analysis.
List prompt presets
GET /api/close-ai/prompts
Request
curl "https://app.talkturo.com/api/close-ai/prompts?templates=true" \
-b "sb-session=authenticated-browser-session"
const response = await fetch(
"https://app.talkturo.com/api/close-ai/prompts?templates=true",
{
credentials: "include"
}
);
const data = await response.json();
console.log(data.presets);
Response
Prompt presets ordered by default status and update time.
Preset identifier.
Identifier of the preset owner.
Preset title.
Prompt text.
Whether the preset is the user's default.
Whether the preset is a template.
Preset creation timestamp.
Timestamp of the most recent preset update.
Create a prompt preset
POST /api/close-ai/prompts
Preset title. Must contain between 1 and 200 characters.
Prompt text. Must contain between 1 and 20,000 characters.
Whether to make this the user's default preset. Defaults to false. Creating a new default clears the user's existing default.
Whether to mark the preset as a template. Defaults to false.
Request
curl -X POST "https://app.talkturo.com/api/close-ai/prompts" \
-H "Content-Type: application/json" \
-b "sb-session=authenticated-browser-session" \
-d '{
"title": "Discovery call review",
"prompt": "Evaluate discovery depth, qualification, and next steps.",
"is_default": true,
"is_template": false
}'
const response = await fetch(
"https://app.talkturo.com/api/close-ai/prompts",
{
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
title: "Discovery call review",
prompt: "Evaluate discovery depth, qualification, and next steps.",
is_default: true,
is_template: false
})
}
);
const data = await response.json();
console.log(data.preset);
Response
The newly created prompt preset.
Preset identifier.
Identifier of the preset owner.
Preset title.
Prompt text.
Whether the preset is the user's default.
Whether the preset is a template.
Preset creation timestamp.
Timestamp of the most recent update.
Settings
Settings endpoints store the analytics system prompt used by Close AI.
Get analytics settings
GET /api/close-ai/settings
Request
curl "https://app.talkturo.com/api/close-ai/settings" \
-b "sb-session=authenticated-browser-session"
const response = await fetch(
"https://app.talkturo.com/api/close-ai/settings",
{
credentials: "include"
}
);
const data = await response.json();
console.log(data.analytics_system_prompt);
Response
Custom analytics system prompt. Returns null when no custom prompt is configured.
Timestamp of the most recent settings update.
Update analytics settings
PUT /api/close-ai/settings
Analytics system prompt. Pass null to clear the custom prompt. A string cannot exceed 20,000 characters.
Request
curl -X PUT "https://app.talkturo.com/api/close-ai/settings" \
-H "Content-Type: application/json" \
-b "sb-session=authenticated-browser-session" \
-d '{
"analytics_system_prompt": "Focus on discovery quality and measurable next steps."
}'
const response = await fetch(
"https://app.talkturo.com/api/close-ai/settings",
{
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
analytics_system_prompt:
"Focus on discovery quality and measurable next steps."
})
}
);
const data = await response.json();
console.log(data.updated_at);
Response
Saved analytics system prompt.
Timestamp of the settings update.
Malformed JSON returns invalid_json. Schema validation returns invalid_body, and database upsert failures return save_failed.
Dashboard
The dashboard endpoint returns aggregated workspace metrics for a selected time range.
Get dashboard data
GET /api/close-ai/dashboard
Workspace slug.
Number of days to include. Values are clamped to the range 1 through 365. Defaults to 30.
1365Request
curl "https://app.talkturo.com/api/close-ai/dashboard?account=acme-sales&days=30" \
-b "sb-session=authenticated-browser-session"
const response = await fetch(
"https://app.talkturo.com/api/close-ai/dashboard?account=acme-sales&days=30",
{
credentials: "include"
}
);
const data = await response.json();
console.log(data.kpis, data.trends);
Response
Workspace-level call, scoring, duration, and membership KPIs.
Aggregated strengths, weaknesses, risks, and evaluation counts.
Objection totals grouped by category, type, and intensity.
Open, closed, deep, and missed-question metrics.
Counts grouped by detected personality type.
Aggregated talk-share, speaking-rate, patience, and monologue metrics.
Script coverage and ordering metrics.
Close score distribution and average score.
Call counts grouped by duration bucket.
Daily call counts and average Close AI scores.
Per-member call, evaluation, score, coaching, script, and personality metrics.
The caller must belong to the requested workspace. Requests can return 401 for an unauthenticated session, 400 for a missing account, 404 for an unknown workspace, or 403 when workspace access is denied.
Scripts
Scripts are workspace-level Close AI playbooks. Setting a script as active deactivates the other scripts in the same workspace.
List scripts
GET /api/close-ai/scripts
Workspace slug.
Request
curl "https://app.talkturo.com/api/close-ai/scripts?account=acme-sales" \
-b "sb-session=authenticated-browser-session"
const response = await fetch(
"https://app.talkturo.com/api/close-ai/scripts?account=acme-sales",
{
credentials: "include"
}
);
const data = await response.json();
console.log(data.scripts);
Response
Scripts available in the workspace.
Script identifier.
Script name.
Script sections and prompts.
Whether the script is active.
Timestamp of the most recent update.
Create a script
POST /api/close-ai/scripts
Workspace slug.
Script name. If omitted, empty, or not a string, the route uses Untitled script.
Request
curl -X POST "https://app.talkturo.com/api/close-ai/scripts?account=acme-sales" \
-H "Content-Type: application/json" \
-b "sb-session=authenticated-browser-session" \
-d '{"name":"Enterprise discovery"}'
const response = await fetch(
"https://app.talkturo.com/api/close-ai/scripts?account=acme-sales",
{
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "Enterprise discovery"
})
}
);
const data = await response.json();
console.log(data.script);
Response
The newly created script.
Script identifier.
Script name.
Script sections and prompts.
Whether the script is active.
Timestamp of the most recent update.
Update a script
PUT /api/close-ai/scripts
The id field is required. Sections can use the type script or info. When is_active is true, all other scripts in the workspace are deactivated first.
Script identifier.
Updated script name.
Script content containing sections and prompts. Both arrays default to empty arrays.
Script sections. Each section includes an identifier, name, type, content, optional next steps, and optional position.
Conditional transitions to other sections. Each transition includes an identifier, condition, and nullable target identifier.
Prompt definitions. Each prompt includes an identifier, trigger, text, and enabled state.
Whether to activate the script. Activating it deactivates other scripts in the workspace.
Request
curl -X PUT "https://app.talkturo.com/api/close-ai/scripts" \
-H "Content-Type: application/json" \
-b "sb-session=authenticated-browser-session" \
-d '{
"id": "script_3c4d5e6f",
"name": "Enterprise discovery",
"content": {
"sections": [
{
"id": "section_discovery",
"name": "Discovery",
"type": "script",
"content": "What is driving this initiative?",
"next": [],
"position": {
"x": 120,
"y": 80
}
}
],
"prompts": [
{
"id": "prompt_budget",
"trigger": "budget",
"text": "Ask how the buying team evaluates investment.",
"enabled": true
}
]
},
"is_active": true
}'
const response = await fetch(
"https://app.talkturo.com/api/close-ai/scripts",
{
method: "PUT",
credentials: "include",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
id: "script_3c4d5e6f",
name: "Enterprise discovery",
content: {
sections: [
{
id: "section_discovery",
name: "Discovery",
type: "script",
content: "What is driving this initiative?",
next: [],
position: {
x: 120,
y: 80
}
}
],
prompts: [
{
id: "prompt_budget",
trigger: "budget",
text: "Ask how the buying team evaluates investment.",
enabled: true
}
]
},
is_active: true
})
}
);
const data = await response.json();
console.log(data.script);
Response
The updated script.
Script identifier.
Script name.
Updated sections and prompts.
Whether the script is active.
Timestamp of the most recent update.
Delete a script
DELETE /api/close-ai/scripts
Script identifier.
Request
curl -X DELETE "https://app.talkturo.com/api/close-ai/scripts?id=script_3c4d5e6f" \
-b "sb-session=authenticated-browser-session"
const response = await fetch(
"https://app.talkturo.com/api/close-ai/scripts?id=script_3c4d5e6f",
{
method: "DELETE",
credentials: "include"
}
);
const data = await response.json();
console.log(data.ok);
Response
Whether the delete operation completed successfully.
Script requests require an authenticated browser session. Listing and creating scripts also require the account workspace query parameter. Deleting a script requires the id query parameter.