- Home
- Developers
- Reference
Reference
Every operation of the customer API: method, path, scope, parameters, an example response and the errors it can return.
Every operation below belongs to the customer API under
https://app.sip.coach/api/public/v1 and requires the key scope named in the
Authorization header (except /me). Every response also carries
X-Request-Id and the RateLimit-* headers; every POST
operation accepts Idempotency-Key — details on the
overview page. This page is generated from the same code as
openapi.v1.json and therefore always reflects
the operations that are actually reachable.
Account
/me
no scope
Example response:
{
"kind": "team",
"privacy": {
"member_detail_enabled": true
},
"rate_limit_per_min": 600,
"scopes": [
"users:read",
"trainings:read"
],
"tenant_id": "6a9c3e3e-9b8e-4b7b-9e9d-2b7b1a2c3d4e"
}401 unauthorized403 api_disabled422 validation_error429 rate_limited503 unavailableMembers
/users
scope: users:read
email is present only when the team's member_detail_enabled switch is on.| Parameter | Type |
|---|---|
cursor (Query, optional) | string |
limit (Query, optional) | integer |
Example response:
{
"data": [
{
"email": "anna@example.com",
"id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
"joined_at": "2026-09-01T08:00:00Z",
"role": "member",
"status": "active",
"user_id": "2c0f3c4d-5e6f-7081-92a3-b4c5d6e7f809"
}
]
}401 unauthorized403 insufficient_scope/api_disabled422 validation_error429 rate_limited503 unavailable/users
scope: users:write
seat_limit_reached if no seat is free; 409 conflict if the email already belongs to a member of this team or is the team's owner. A role other than member grants that role's rights and follows the same rules as PATCH /users/{member_id} (403 insufficient_scope otherwise). Rate limited to 60 invitations per hour per team.Request body:
| Field | Type | Required |
|---|---|---|
email | string | yes |
role | string | no |
lang | string | no |
Example request:
{
"email": "jordan@example.com",
"role": "member"
}Example response:
{
"email": "anna@example.com",
"id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
"joined_at": "2026-09-01T08:00:00Z",
"role": "member",
"status": "active",
"user_id": "2c0f3c4d-5e6f-7081-92a3-b4c5d6e7f809"
}401 unauthorized403 insufficient_scope/api_disabled409 conflict/seat_limit_reached422 validation_error/idempotency_mismatch429 rate_limited503 unavailable/users/{member_id}
scope: users:read
| Parameter | Type |
|---|---|
member_id (path, required) | string |
Example response:
{
"email": "anna@example.com",
"id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
"joined_at": "2026-09-01T08:00:00Z",
"role": "member",
"status": "active",
"user_id": "2c0f3c4d-5e6f-7081-92a3-b4c5d6e7f809"
}401 unauthorized403 insufficient_scope/api_disabled404 not_found422 validation_error429 rate_limited503 unavailable/users/{member_id}
scope: users:write
last_admin if this would leave the team without any admin member; 409 owner for the team's owner. Granting or revoking the admin role requires a key created by the team's owner or an active admin, otherwise 403 insufficient_scope. email is present only when the team's member_detail_enabled switch is on.| Parameter | Type |
|---|---|
member_id (path, required) | string |
Request body:
| Field | Type | Required |
|---|---|---|
role | string | yes |
Example request:
{
"role": "admin"
}Example response:
{
"email": "anna@example.com",
"id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
"joined_at": "2026-09-01T08:00:00Z",
"role": "member",
"status": "active",
"user_id": "2c0f3c4d-5e6f-7081-92a3-b4c5d6e7f809"
}401 unauthorized403 insufficient_scope/api_disabled404 not_found409 owner/last_admin422 validation_error429 rate_limited503 unavailable/users/{member_id}
scope: users:write
owner if the member is the team's owner; 409 last_admin if the member is the team's only active admin. Revokes any learning assignments in the same step.| Parameter | Type |
|---|---|
member_id (path, required) | string |
Example response:
{
"ok": true
}401 unauthorized403 insufficient_scope/api_disabled404 not_found409 owner/last_admin422 validation_error429 rate_limited503 unavailableTrainings
/trainings
scope: trainings:read
user_id, status, since and assignment_id. Requires member_detail_enabled on the team; otherwise 403 privacy_restricted.| Parameter | Type |
|---|---|
cursor (Query, optional) | string |
user_id (Query, optional) | string |
status (Query, optional) | string |
since (Query, optional) | date-time |
assignment_id (Query, optional) | string |
limit (Query, optional) | integer |
Example response:
{
"data": [
{
"created_at": "2026-10-14T08:30:00Z",
"duration_s": 900,
"finished_at": "2026-10-14T08:42:10Z",
"id": "7f3cfe1a-1111-4b22-9c33-abcdef012345",
"industry_id": "saas",
"personality_id": "skeptiker",
"role_id": "einkauf",
"situation_id": "kaltakquise",
"source": "app",
"status": "scored",
"user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8"
}
]
}401 unauthorized403 insufficient_scope/api_disabled/privacy_restricted422 validation_error429 rate_limited503 unavailable/trainings/{training_id}
scope: trainings:read
| Parameter | Type |
|---|---|
training_id (path, required) | string |
Example response:
{
"created_at": "2026-10-14T08:30:00Z",
"duration_s": 900,
"finished_at": "2026-10-14T08:42:10Z",
"id": "7f3cfe1a-1111-4b22-9c33-abcdef012345",
"industry_id": "saas",
"personality_id": "skeptiker",
"role_id": "einkauf",
"situation_id": "kaltakquise",
"source": "app",
"status": "scored",
"user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8"
}401 unauthorized403 insufficient_scope/api_disabled/privacy_restricted404 not_found422 validation_error429 rate_limited503 unavailableEvaluations
/evaluations
scope: evaluations:read
?updated_since=; same shape as GET /trainings.| Parameter | Type |
|---|---|
cursor (Query, optional) | string |
updated_since (Query, optional) | date-time |
limit (Query, optional) | integer |
Example response:
{
"data": [
{
"created_at": "2026-10-14T08:30:00Z",
"duration_s": 900,
"finished_at": "2026-10-14T08:42:10Z",
"id": "7f3cfe1a-1111-4b22-9c33-abcdef012345",
"industry_id": "saas",
"personality_id": "skeptiker",
"role_id": "einkauf",
"situation_id": "kaltakquise",
"source": "app",
"status": "scored",
"user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8"
}
]
}401 unauthorized403 insufficient_scope/api_disabled/privacy_restricted422 validation_error429 rate_limited503 unavailable/trainings/{training_id}/evaluation
scope: evaluations:read
| Parameter | Type |
|---|---|
training_id (path, required) | string |
Example response:
{
"biggest_lever": "Close earlier",
"goal": "partial",
"methodology": "needs_qual",
"score": {
"dimensions": {
"closing": 72,
"conversation_control": 78,
"needs_analysis": 71,
"objection_handling": 80,
"value_argument": 69
},
"spread": 3,
"total": 74
},
"strongest": "Good discovery questions",
"tips": [
{
"impact": "sounds more confident",
"issue": "too hesitant",
"moment": "Line 4",
"principle": "State it clearly",
"rewrite": "Let's lock that in."
}
],
"training_id": "7f3cfe1a-1111-4b22-9c33-abcdef012345",
"user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8"
}401 unauthorized403 insufficient_scope/api_disabled/privacy_restricted404 not_found422 validation_error429 rate_limited503 unavailableAssignments
/assignments
scope: assignments:read
member_detail_enabled on the team; otherwise 403 privacy_restricted.| Parameter | Type |
|---|---|
cursor (Query, optional) | string |
limit (Query, optional) | integer |
Example response:
{
"data": [
{
"created_at": "2026-10-01T09:00:00Z",
"due_date": "2026-10-20",
"id": "9a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
"industry_id": "saas",
"member_email": "anna@example.com",
"member_user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
"personality_id": "skeptiker",
"situation_id": "kaltakquise",
"status": "open",
"title": "Practise cold calling"
}
]
}401 unauthorized403 insufficient_scope/api_disabled/privacy_restricted422 validation_error429 rate_limited503 unavailable/assignments
scope: assignments:write
vorgabe_gesperrt if blocked.Request body:
| Field | Type | Required |
|---|---|---|
member_id | string | yes |
title | string | yes |
situation_id | string | yes |
personality_id | string | yes |
industry_id | string | yes |
note | string | no |
due_date | date | no |
Example request:
{
"member_id": "b3b2b1a0-1234-4a3b-8c9d-0e1f2a3b4c5d",
"title": "Objection handling drill",
"situation_id": "kaltakquise",
"personality_id": "skeptiker",
"industry_id": "saas",
"due_date": "2026-10-15"
}Example response:
{
"created_at": "2026-10-01T09:00:00Z",
"due_date": "2026-10-20",
"id": "9a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
"industry_id": "saas",
"member_email": "anna@example.com",
"member_user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
"personality_id": "skeptiker",
"situation_id": "kaltakquise",
"status": "open",
"title": "Practise cold calling"
}401 unauthorized403 insufficient_scope/api_disabled/vorgabe_gesperrt422 validation_error/idempotency_mismatch/kombination_ungueltig429 rate_limited503 unavailable/assignments/{assignment_id}
scope: assignments:read
member_detail_enabled on the team; otherwise 403 privacy_restricted.| Parameter | Type |
|---|---|
assignment_id (path, required) | string |
Example response:
{
"created_at": "2026-10-01T09:00:00Z",
"due_date": "2026-10-20",
"id": "9a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
"industry_id": "saas",
"member_email": "anna@example.com",
"member_user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
"personality_id": "skeptiker",
"situation_id": "kaltakquise",
"status": "open",
"title": "Practise cold calling"
}401 unauthorized403 insufficient_scope/api_disabled/privacy_restricted404 not_found422 validation_error429 rate_limited503 unavailable/assignments/{assignment_id}
scope: assignments:write
status, note and/or due_date. 404 for a foreign or unknown id.| Parameter | Type |
|---|---|
assignment_id (path, required) | string |
Request body:
| Field | Type | Required |
|---|---|---|
status | string | no |
note | string | no |
due_date | date | no |
Example request:
{
"status": "done"
}Example response:
{
"created_at": "2026-10-01T09:00:00Z",
"due_date": "2026-10-20",
"id": "9a1b2c3d-4e5f-6071-8293-a4b5c6d7e8f9",
"industry_id": "saas",
"member_email": "anna@example.com",
"member_user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
"personality_id": "skeptiker",
"situation_id": "kaltakquise",
"status": "open",
"title": "Practise cold calling"
}401 unauthorized403 insufficient_scope/api_disabled404 not_found422 validation_error429 rate_limited503 unavailable/assignments/{assignment_id}
scope: assignments:write
| Parameter | Type |
|---|---|
assignment_id (path, required) | string |
Example response:
{
"ok": true
}401 unauthorized403 insufficient_scope/api_disabled404 not_found422 validation_error429 rate_limited503 unavailableCases
/cases
scope: cases:read
member_detail_enabled on the team; otherwise 403 privacy_restricted.| Parameter | Type |
|---|---|
cursor (Query, optional) | string |
user_id (Query, optional) | string |
limit (Query, optional) | integer |
Example response:
{
"data": [
{
"created_at": "2026-09-20T07:00:00Z",
"external_ref": {
"id": "123",
"object": "deal",
"system": "hubspot"
},
"fields": {},
"id": "5c6d7e8f-9011-4213-8495-c6d7e8f90123",
"persona_id": "kaltakquise:skeptiker:saas",
"title": "Deal Acme Corp",
"user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8"
}
]
}401 unauthorized403 insufficient_scope/api_disabled/privacy_restricted422 validation_error429 rate_limited503 unavailable/cases
scope: cases:write
user_id must be an active member of the calling team; a foreign or unknown id returns 404.Request body:
| Field | Type | Required |
|---|---|---|
user_id | string | yes |
title | string | no |
fields | object | no |
persona_id | string | no |
external_ref | object | no |
Example request:
{
"user_id": "b3b2b1a0-1234-4a3b-8c9d-0e1f2a3b4c5d",
"title": "Acme Corp — renewal",
"fields": {
"amount": 12000,
"stage": "negotiation"
}
}Example response:
{
"created_at": "2026-09-20T07:00:00Z",
"external_ref": {
"id": "123",
"object": "deal",
"system": "hubspot"
},
"fields": {},
"id": "5c6d7e8f-9011-4213-8495-c6d7e8f90123",
"persona_id": "kaltakquise:skeptiker:saas",
"title": "Deal Acme Corp",
"user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8"
}401 unauthorized403 insufficient_scope/api_disabled422 validation_error/idempotency_mismatch429 rate_limited503 unavailable/cases/{case_id}
scope: cases:read
member_detail_enabled on the team; otherwise 403 privacy_restricted.| Parameter | Type |
|---|---|
case_id (path, required) | string |
Example response:
{
"created_at": "2026-09-20T07:00:00Z",
"external_ref": {
"id": "123",
"object": "deal",
"system": "hubspot"
},
"fields": {},
"id": "5c6d7e8f-9011-4213-8495-c6d7e8f90123",
"persona_id": "kaltakquise:skeptiker:saas",
"title": "Deal Acme Corp",
"user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8"
}401 unauthorized403 insufficient_scope/api_disabled/privacy_restricted404 not_found422 validation_error429 rate_limited503 unavailable/cases/{case_id}
scope: cases:write
title, fields, persona_id and/or external_ref. 404 for a foreign or unknown id.| Parameter | Type |
|---|---|
case_id (path, required) | string |
Request body:
| Field | Type | Required |
|---|---|---|
title | string | no |
fields | object | no |
persona_id | string | no |
external_ref | object | no |
Example request:
{
"fields": {
"stage": "won"
}
}Example response:
{
"created_at": "2026-09-20T07:00:00Z",
"external_ref": {
"id": "123",
"object": "deal",
"system": "hubspot"
},
"fields": {},
"id": "5c6d7e8f-9011-4213-8495-c6d7e8f90123",
"persona_id": "kaltakquise:skeptiker:saas",
"title": "Deal Acme Corp",
"user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8"
}401 unauthorized403 insufficient_scope/api_disabled404 not_found422 validation_error429 rate_limited503 unavailable/cases/{case_id}
scope: cases:write
| Parameter | Type |
|---|---|
case_id (path, required) | string |
Example response:
{
"ok": true
}401 unauthorized403 insufficient_scope/api_disabled404 not_found422 validation_error429 rate_limited503 unavailableCatalog
/catalog
scope: catalog:read
Accept-Language.Example response:
{
"industry": [
{
"icon": "cloud",
"id": "saas",
"name": "SaaS"
}
],
"methodology": [
{
"icon": "list",
"id": "needs_qual",
"name": "Needs qualification"
}
],
"personality": [
{
"icon": "shield",
"id": "skeptiker",
"name": "Skeptic"
}
],
"role": [
{
"icon": "briefcase",
"id": "einkauf",
"name": "Procurement"
}
],
"situation": [
{
"icon": "phone",
"id": "kaltakquise",
"name": "Cold calling"
}
]
}401 unauthorized403 insufficient_scope/api_disabled422 validation_error429 rate_limited503 unavailableAnalytics
/analytics/team
scope: analytics:read
members is empty unless the team has member_detail_enabled and leaderboard_enabled on and at least 5 active members.Example response:
{
"dimensions": [
{
"dimension": "needs_analysis",
"value": 71
}
],
"members": [],
"skill_gaps": [
"closing"
],
"totals": {
"active_members": 9,
"avg_score": 71.5,
"scored": 38,
"sessions": 42
},
"trend": [
{
"score": 68
},
{
"score": 72
}
]
}401 unauthorized403 insufficient_scope/api_disabled422 validation_error429 rate_limited503 unavailableCRM
/crm/deals
scope: cases:read
owner_user_id is present only when member_detail_enabled is on for the team; otherwise the field is left out (other fields are unaffected).| Parameter | Type |
|---|---|
cursor (Query, optional) | string |
limit (Query, optional) | integer |
Example response:
{
"data": [
{
"amount": "1000.00",
"close_date": "2026-11-01",
"currency": "EUR",
"external_id": "123",
"id": "1a2b3c4d-5e6f-7081-92a3-b4c5d6e7f809",
"industry_id": "saas",
"last_activity_at": "2026-10-10T09:00:00Z",
"outcome": "open",
"owner_user_id": "1b9e2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
"pipeline_id": "default",
"probability": 60,
"stage_id": "contractsent",
"synced_at": "2026-10-14T06:00:00Z",
"title": "Acme Corp"
}
]
}401 unauthorized403 insufficient_scope/api_disabled422 validation_error429 rate_limited503 unavailable/crm/objections
scope: cases:read
| Parameter | Type |
|---|---|
cursor (Query, optional) | string |
limit (Query, optional) | integer |
Example response:
{
"data": [
{
"category": "price",
"created_at": "2026-10-09T11:00:00Z",
"deal_id": "1a2b3c4d-5e6f-7081-92a3-b4c5d6e7f809",
"id": "42",
"lang": "en",
"text": "Too expensive compared to the incumbent."
}
]
}401 unauthorized403 insufficient_scope/api_disabled422 validation_error429 rate_limited503 unavailableWebhooks
/webhook-endpoints
scope: webhooks:manage
secret is never included (only the response to POST carries it, once).Example response:
{
"data": [
{
"api_version": "2026-10",
"created_at": "2026-10-01T09:00:00Z",
"description": "CRM sync",
"events": [
"training.completed",
"evaluation.completed"
],
"id": "7c3b2a1d-0000-4000-8000-0123456789ab",
"last_success_at": "2026-10-14T08:00:00Z",
"status": "active",
"url": "https://hooks.example.com/sip"
}
]
}401 unauthorized403 insufficient_scope/api_disabled422 validation_error429 rate_limited503 unavailable/webhook-endpoints
scope: webhooks:manage
secret is returned only in this response — it is never shown again.Request body:
| Field | Type | Required |
|---|---|---|
url | string | yes |
description | string | no |
events | array | yes |
Example request:
{
"url": "https://example.com/webhooks/sip-coach",
"description": "Production",
"events": [
"training.completed",
"evaluation.completed"
]
}Example response:
{
"api_version": "2026-10",
"created_at": "2026-10-01T09:00:00Z",
"description": "CRM sync",
"events": [
"training.completed",
"evaluation.completed"
],
"id": "7c3b2a1d-0000-4000-8000-0123456789ab",
"last_success_at": "2026-10-14T08:00:00Z",
"secret": "whsec_7f3c1a2b3c4d5e6f70819293a4b5c6d7",
"status": "active",
"url": "https://hooks.example.com/sip"
}401 unauthorized403 insufficient_scope/api_disabled422 validation_error/idempotency_mismatch429 rate_limited503 unavailable/webhook-endpoints/{endpoint_id}
scope: webhooks:manage
url, description, events and/or status. 404 for a foreign or unknown id.| Parameter | Type |
|---|---|
endpoint_id (path, required) | string |
Request body:
| Field | Type | Required |
|---|---|---|
url | string | no |
description | string | no |
events | array | no |
status | string | no |
Example request:
{
"status": "active"
}Example response:
{
"api_version": "2026-10",
"created_at": "2026-10-01T09:00:00Z",
"description": "CRM sync",
"events": [
"training.completed",
"evaluation.completed"
],
"id": "7c3b2a1d-0000-4000-8000-0123456789ab",
"last_success_at": "2026-10-14T08:00:00Z",
"status": "active",
"url": "https://hooks.example.com/sip"
}401 unauthorized403 insufficient_scope/api_disabled404 not_found422 validation_error429 rate_limited503 unavailable/webhook-endpoints/{endpoint_id}
scope: webhooks:manage
| Parameter | Type |
|---|---|
endpoint_id (path, required) | string |
Example response:
{
"ok": true
}401 unauthorized403 insufficient_scope/api_disabled404 not_found422 validation_error429 rate_limited503 unavailable/webhook-endpoints/{endpoint_id}/test
scope: webhooks:manage
ping event for delivery by the background delivery loop (picked up within seconds); the outcome appears in GET .../deliveries under the returned delivery_id.| Parameter | Type |
|---|---|
endpoint_id (path, required) | string |
Example response:
{
"delivery_id": "42",
"status": "pending"
}401 unauthorized403 insufficient_scope/api_disabled404 not_found422 validation_error/idempotency_mismatch429 rate_limited503 unavailable/webhook-deliveries/{delivery_id}/retry
scope: webhooks:manage
| Parameter | Type |
|---|---|
delivery_id (path, required) | string |
Example response:
{
"attempt": 1,
"created_at": "2026-10-14T07:59:00Z",
"event_type": "training.completed",
"id": "42",
"next_try_at": "2026-10-14T08:00:00Z",
"response_code": 200,
"response_excerpt": "ok",
"response_ms": 120,
"status": "ok"
}401 unauthorized403 insufficient_scope/api_disabled404 not_found422 validation_error/idempotency_mismatch429 rate_limited503 unavailable/webhook-endpoints/{endpoint_id}/deliveries
scope: webhooks:manage
| Parameter | Type |
|---|---|
endpoint_id (path, required) | string |
limit (Query, optional) | integer |
Example response:
{
"data": [
{
"attempt": 1,
"created_at": "2026-10-14T07:59:00Z",
"event_type": "training.completed",
"id": "42",
"next_try_at": "2026-10-14T08:00:00Z",
"response_code": 200,
"response_excerpt": "ok",
"response_ms": 120,
"status": "ok"
}
]
}401 unauthorized403 insufficient_scope/api_disabled404 not_found422 validation_error429 rate_limited503 unavailable