{"openapi":"3.0.0","paths":{"/v1/health":{"get":{"operationId":"HealthController_healthCheck","parameters":[],"responses":{"200":{"description":"API is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"timestamp":{"type":"string","example":"2026-01-26T12:00:00.000Z"}}}}}}},"summary":"Health check endpoint","tags":["Health"]}},"/v1/me":{"get":{"description":"Returns information about the authenticated API key and organization","operationId":"AuthController_getMe","parameters":[],"responses":{"200":{"description":"API key information","content":{"application/json":{"schema":{"type":"object","properties":{"organizationId":{"type":"string","format":"uuid"},"message":{"type":"string","example":"Authenticated successfully"}}}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}}},"security":[{"ApiKey":[]}],"summary":"Get current API key info","tags":["Authentication"]}},"/v1/contacts":{"get":{"description":"Returns a paginated list of contacts scoped to the workspaces accessible by the API key. Use the `workspaceIds` query parameter to narrow results to a subset of those workspaces.","operationId":"ContactController_list","parameters":[{"name":"workspaceIds","required":false,"in":"query","description":"Workspace IDs to narrow down results. Must be a subset of the workspaces accessible by the API key. Omit to return data from every workspace in scope. Accepts either a comma-separated string (`?workspaceIds=uuid1,uuid2`) — the documented format — or repeated array params (`?workspaceIds[]=uuid1&workspaceIds[]=uuid2`).","schema":{"example":"550e8400-e29b-41d4-a716-446655440000,6ba7b810-9dad-11d1-80b4-00c04fd430c8","type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number (1-indexed)","schema":{"minimum":1,"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":10,"example":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search query to filter contacts by name, email, or company","schema":{"maxLength":100,"example":"john","type":"string"}}],"responses":{"200":{"description":"Paginated list of contacts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedPublicContactsDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"One or more requested workspaceIds are outside the API key scope"}},"security":[{"ApiKey":[]}],"summary":"List contacts","tags":["Contacts"]},"post":{"description":"Creates a new contact in your organization","operationId":"ContactController_create","parameters":[{"name":"x-workspace-id","in":"header","description":"Target workspace id (from `GET /v1/workspaces`). Required for multi-workspace API keys to designate which workspace to write to; omit for single-workspace keys, where it is resolved automatically. Must be within the API key scope.","required":false,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCreateContactDto"}}}},"responses":{"201":{"description":"The created contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicContactDto"}}}},"400":{"description":"Invalid input data"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"409":{"description":"CONTACT_ALREADY_EXISTS: a contact with exactly this first name, last name and company already exists in the workspace (case-sensitive; never raised without a company). The error carries its contactId.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"503":{"description":"Database temporarily unavailable, retry after the Retry-After delay"}},"security":[{"ApiKey":[]}],"summary":"Create a contact","tags":["Contacts"]}},"/v1/contacts/{id}":{"get":{"description":"Returns a single contact by ID. Returns 404 if the contact is in a workspace outside the API key scope.","operationId":"ContactController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicContactDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Contact not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Get a contact","tags":["Contacts"]},"patch":{"description":"Updates an existing contact. Only provided fields will be updated. Returns 404 if the contact is in a workspace outside the API key scope.","operationId":"ContactController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicUpdateContactDto"}}}},"responses":{"200":{"description":"The updated contact","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicContactDto"}}}},"400":{"description":"Invalid input data"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Contact not found or outside API key scope"},"503":{"description":"Database temporarily unavailable, retry after the Retry-After delay"}},"security":[{"ApiKey":[]}],"summary":"Update a contact","tags":["Contacts"]},"delete":{"description":"Soft-deletes a contact. The contact can no longer be retrieved after deletion. Returns 404 if the contact is in a workspace outside the API key scope.","operationId":"ContactController_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Contact deleted successfully"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Contact not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Delete a contact","tags":["Contacts"]}},"/v1/calls":{"get":{"description":"Returns a paginated list of calls scoped to the workspaces accessible by the API key. Use the `workspaceIds` query parameter to narrow results to a subset of those workspaces.","operationId":"CallController_list","parameters":[{"name":"page","required":false,"in":"query","description":"Page number (starts at 1)","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":10,"example":10,"type":"number"}},{"name":"sort","required":false,"in":"query","description":"Sort as a JSON string, e.g. `?sort={\"orderBy\":\"createdAt\",\"order\":\"desc\"}` (URL-encoded). Defaults to `createdAt` descending.","schema":{"type":"string"}},{"name":"filters","required":false,"in":"query","description":"Filters as a JSON string. Each field wraps an operator object, e.g. `?filters={\"createdAt\":{\"op\":\"between\",\"from\":\"2026-06-01\",\"to\":\"2026-06-30\"}}` or `{\"createdAt\":{\"op\":\"gt\",\"from\":\"2026-06-25\"}}` (URL-encoded).","schema":{"type":"string"}},{"name":"workspaceIds","required":false,"in":"query","description":"Workspace IDs to narrow down results. Must be a subset of the workspaces accessible by the API key. Omit to return data from every workspace in scope. Accepts either a comma-separated string (`?workspaceIds=uuid1,uuid2`) — the documented format — or repeated array params (`?workspaceIds[]=uuid1&workspaceIds[]=uuid2`).","schema":{"example":"550e8400-e29b-41d4-a716-446655440000,6ba7b810-9dad-11d1-80b4-00c04fd430c8","type":"string"}}],"responses":{"200":{"description":"Paginated list of calls","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedCallDTO"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"One or more requested workspaceIds are outside the API key scope"}},"security":[{"ApiKey":[]}],"summary":"List calls","tags":["Calls"]}},"/v1/calls/{id}":{"get":{"description":"Returns a single call by ID. Returns 404 if the call is in a workspace outside the API key scope.","operationId":"CallController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Call UUID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"The call","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallWithContactDTO"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Call not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Get a call","tags":["Calls"]}},"/v1/calls/{id}/recording":{"get":{"description":"Returns the recording metadata for a call, including `audioUrl`: the absolute URL of `GET /v1/calls/{id}/recording/audio`, which streams the audio with the same API key. Returns 403 `RECORDING_DISABLED` when call recording is disabled for the workspace of the call (behaviour change: this endpoint previously returned the metadata in that case). Returns 404 if the call is in a workspace outside the API key scope.","operationId":"CallController_getRecording","parameters":[{"name":"id","required":true,"in":"path","description":"Call UUID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"The call recording metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCallRecordingDTO"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"`RECORDING_DISABLED`: call recording is disabled for the workspace of this call"},"404":{"description":"Call or recording not found, or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Get call recording","tags":["Calls"]},"delete":{"description":"Permanently deletes the call recording (the audio is also removed from the telephony provider). This CASCADES: the call transcription and its summary, if any, are deleted as well.","operationId":"CallController_deleteRecording","parameters":[{"name":"id","required":true,"in":"path","description":"Call UUID","schema":{"format":"uuid","type":"string"}}],"responses":{"204":{"description":"Recording (and its transcription and summary, if any) deleted"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Call or recording not found, or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Delete a call recording","tags":["Calls"]}},"/v1/calls/{id}/recording/audio":{"get":{"description":"Streams the audio of the call recording, authenticated with the same API key as every other endpoint (no public or pre-signed link). Defaults to mp3 (`audio/mpeg`); `?format=wav` returns `audio/wav` and any other value falls back to mp3. Served inline unless `?download=true`, which sets `Content-Disposition: attachment`. Limited to 10 requests per minute. Returns 403 `RECORDING_DISABLED` when call recording is disabled for the workspace of the call. Returns 404 if the call does not exist, is outside the API key scope, has no recording, or its audio is no longer available.","operationId":"CallController_getRecordingAudio","parameters":[{"name":"id","required":true,"in":"path","description":"Call UUID","schema":{"format":"uuid","type":"string"}},{"name":"download","required":false,"in":"query","description":"Set to `true` to receive the file as an attachment instead of inline.","schema":{"enum":["true","false"],"type":"string"}},{"name":"format","required":false,"in":"query","description":"Audio format (default: mp3). Any other value falls back to mp3.","schema":{"enum":["mp3","wav"],"type":"string"}}],"responses":{"200":{"description":"Audio stream, with `Content-Disposition: inline|attachment; filename=\"recording-<callId>.mp3|wav\"`","content":{"audio/mpeg":{"schema":{"type":"string","format":"binary"}},"audio/wav":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"`RECORDING_DISABLED`: call recording is disabled for the workspace of this call"},"404":{"description":"Call not found, outside API key scope, without recording, or audio no longer available"}},"security":[{"ApiKey":[]}],"summary":"Stream the audio of a call recording","tags":["Calls"]}},"/v1/calls/{id}/transcription":{"get":{"description":"Returns the transcription for a call. Returns 404 if the call is in a workspace outside the API key scope.","operationId":"CallController_getTranscription","parameters":[{"name":"id","required":true,"in":"path","description":"Call UUID","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"description":"The call transcription","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCallTranscriptionDTO"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Call or transcription not found, or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Get call transcription","tags":["Calls"]},"delete":{"description":"Deletes the call transcription, including its summary. The recording (audio) is kept.","operationId":"CallController_deleteTranscription","parameters":[{"name":"id","required":true,"in":"path","description":"Call UUID","schema":{"format":"uuid","type":"string"}}],"responses":{"204":{"description":"Transcription (and its summary) deleted"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Call or transcription not found, or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Delete a call transcription","tags":["Calls"]}},"/v1/calls/{id}/summary":{"delete":{"description":"Deletes only the summary of the call transcription. The transcript and the recording are kept.","operationId":"CallController_deleteSummary","parameters":[{"name":"id","required":true,"in":"path","description":"Call UUID","schema":{"format":"uuid","type":"string"}}],"responses":{"204":{"description":"Summary deleted (transcript and recording kept)"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Call or transcription not found, or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Delete a call summary","tags":["Calls"]}},"/v1/calls/{id}/voicemail-drop/audio":{"get":{"description":"Streams the audio of the voicemail clip dropped on the answering machine for this call. Returns 404 if the call has no dropped clip (none dropped, or the clip was later deleted), if the call does not exist, or if it is in a workspace outside the API key scope.","operationId":"CallController_getVoicemailDropAudio","parameters":[{"name":"id","required":true,"in":"path","description":"Call UUID","schema":{"format":"uuid","type":"string"}},{"name":"format","required":false,"in":"query","description":"Audio format to stream (default: mp3)","schema":{"enum":["mp3","wav"],"type":"string"}}],"responses":{"200":{"description":"Audio stream returned successfully","content":{"audio/mpeg":{"schema":{"type":"string","format":"binary"}},"audio/wav":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Call not found, outside API key scope, or no voicemail drop clip available for it"}},"security":[{"ApiKey":[]}],"summary":"Stream the audio of the dropped voicemail clip for a call","tags":["Calls"]}},"/v1/users":{"get":{"description":"Returns a paginated list of users (organization members) who have access to at least one of the workspaces accessible by the API key. Use the `organizationMembershipId` to create sequences. Use the `workspaceIds` query parameter to narrow results to a subset of those workspaces.","operationId":"UserController_list","parameters":[{"name":"workspaceIds","required":false,"in":"query","description":"Workspace IDs to narrow down results. Must be a subset of the workspaces accessible by the API key. Omit to return data from every workspace in scope. Accepts either a comma-separated string (`?workspaceIds=uuid1,uuid2`) — the documented format — or repeated array params (`?workspaceIds[]=uuid1&workspaceIds[]=uuid2`).","schema":{"example":"550e8400-e29b-41d4-a716-446655440000,6ba7b810-9dad-11d1-80b4-00c04fd430c8","type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number (1-indexed)","schema":{"minimum":1,"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":50,"example":50,"type":"number"}}],"responses":{"200":{"description":"Paginated list of users","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedUsersDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"One or more requested workspaceIds are outside the API key scope"}},"security":[{"ApiKey":[]}],"summary":"List organization users","tags":["Users"]}},"/v1/sequences":{"post":{"description":"Creates a new sequence. Use the /users endpoint to get organizationMembershipIds for assignedToIds and creatorId.","operationId":"SequenceController_create","parameters":[{"name":"x-workspace-id","in":"header","description":"Target workspace id (from `GET /v1/workspaces`). Required for multi-workspace API keys to designate which workspace to write to; omit for single-workspace keys, where it is resolved automatically. Must be within the API key scope.","required":false,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSequenceDto"}}}},"responses":{"201":{"description":"Sequence created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}}},"security":[{"ApiKey":[]}],"summary":"Create a sequence","tags":["Sequences"]},"get":{"description":"Returns a paginated list of sequences scoped to the workspaces accessible by the API key. Use the `workspaceIds` query parameter to narrow results to a subset of those workspaces.","operationId":"SequenceController_list","parameters":[{"name":"workspaceIds","required":false,"in":"query","description":"Workspace IDs to narrow down results. Must be a subset of the workspaces accessible by the API key. Omit to return data from every workspace in scope. Accepts either a comma-separated string (`?workspaceIds=uuid1,uuid2`) — the documented format — or repeated array params (`?workspaceIds[]=uuid1&workspaceIds[]=uuid2`).","schema":{"example":"550e8400-e29b-41d4-a716-446655440000,6ba7b810-9dad-11d1-80b4-00c04fd430c8","type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number (1-indexed)","schema":{"minimum":1,"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":50,"example":50,"type":"number"}}],"responses":{"200":{"description":"Paginated list of sequences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedSequencesDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"One or more requested workspaceIds are outside the API key scope"}},"security":[{"ApiKey":[]}],"summary":"List sequences","tags":["Sequences"]}},"/v1/sequences/{id}":{"get":{"description":"Returns the details of a specific sequence. Returns 404 if the sequence is in a workspace outside the API key scope.","operationId":"SequenceController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Sequence details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SequenceDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Sequence not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Get a sequence by ID","tags":["Sequences"]}},"/v1/sequences/{id}/contacts":{"get":{"description":"Returns a paginated list of contacts in a sequence, enriched with their tags and call history within the sequence. Supports filtering by tag label and contact status. Returns 404 if the parent sequence is in a workspace outside the API key scope.","operationId":"SequenceController_listContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number (1-indexed)","schema":{"minimum":1,"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":50,"example":50,"type":"number"}},{"name":"tag","required":false,"in":"query","description":"Filter contacts by tag label","schema":{"example":"hot-lead","type":"string"}},{"name":"status","required":false,"in":"query","description":"Filter contacts by call status","schema":{"example":"CONNECTED","type":"string","enum":["CONNECTED","RESPONDER","ERROR","CANCELLED","RUNNING","MISSING_NUMBER"]}}],"responses":{"200":{"description":"Paginated list of sequence contacts with tags and calls","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedSequenceContactsDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Sequence not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"List contacts of a sequence","tags":["Sequences"]},"post":{"description":"Adds contacts to an existing sequence. Each item may optionally specify an `assignedToWorkspaceMembershipId` (a workspace membership id obtained via `GET /v1/workspaces/:id/members`). Items without `assignedToWorkspaceMembershipId` are auto-assigned via round-robin among the sequence assignees (least loaded first). Idempotent: duplicates, contacts already in the sequence, and contacts outside the sequence scope are silently ignored. Soft-deleted sequence-contacts are resurrected (their original assignee is preserved; an `assignedToWorkspaceMembershipId` in the body is ignored for resurrected rows). Returns 404 if the sequence is outside the API key scope. On concurrent requests for the same contact, the winner among competing `assignedToWorkspaceMembershipId` values is undefined; verify with GET /v1/sequences/:id/contacts.","operationId":"SequenceController_addContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAssignmentBatchDto"}}}},"responses":{"201":{"description":"Contacts added","content":{"application/json":{"schema":{"example":{"added":3}}}}},"400":{"description":"Validation error, or an explicit `assignedToWorkspaceMembershipId` is not in the sequence assignees / not in the sequence workspace."},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Sequence not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Add contacts to a sequence","tags":["Sequences"]},"delete":{"description":"Removes contacts from an existing sequence (soft-delete). Idempotent: contacts not in the sequence are silently ignored. Returns 404 if the sequence is outside the API key scope.","operationId":"SequenceController_removeContacts","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactsBatchDto"}}}},"responses":{"200":{"description":"Contacts removed","content":{"application/json":{"schema":{"example":{"removed":2}}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Sequence not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Remove contacts from a sequence","tags":["Sequences"]}},"/v1/sequences/{id}/archive":{"post":{"description":"Archives a sequence. An archived sequence no longer appears in GET /v1/sequences, returns 404 on GET /v1/sequences/:id and its contacts endpoints, and can be restored with POST /v1/sequences/:id/unarchive. Its contacts and call history are kept. Returns 404 if the sequence is outside the API key scope.","operationId":"SequenceController_archive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Sequence archived"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Sequence not found or outside API key scope"},"409":{"description":"Sequence is already archived"}},"security":[{"ApiKey":[]}],"summary":"Archive a sequence","tags":["Sequences"]}},"/v1/sequences/{id}/unarchive":{"post":{"description":"Restores an archived sequence, with its contacts and call history. Returns 404 if the sequence is outside the API key scope.","operationId":"SequenceController_unarchive","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Sequence unarchived"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Sequence not found or outside API key scope"},"409":{"description":"Sequence is not archived"}},"security":[{"ApiKey":[]}],"summary":"Unarchive a sequence","tags":["Sequences"]}},"/v1/stats/calls":{"get":{"description":"Returns call count, average duration, and total duration. Can be filtered by sequence, user, date range, and workspace. Pass `workspaceId` to narrow to a single workspace within the API key scope. The legacy `teamId` parameter is still accepted but adds a `Deprecation: true` response header.","operationId":"StatsController_getCallsDuration","parameters":[{"name":"sequenceId","required":false,"in":"query","description":"Filter by sequence ID","schema":{"type":"string"}},{"name":"userMembershipId","required":false,"in":"query","description":"Filter by user membership ID","schema":{"type":"string"}},{"name":"callType","required":false,"in":"query","description":"Filter by call type. \"all\" includes sequence + direct calls.","schema":{"default":"all","type":"string","enum":["all","sequence","direct","inbound","outbound"]}},{"name":"granularity","required":false,"in":"query","description":"Time granularity for grouping results","schema":{"default":"none","type":"string","enum":["hour","day","week","month","none"]}},{"name":"startDate","required":false,"in":"query","description":"Start date (ISO format)","schema":{"type":"string"}},{"name":"endDate","required":false,"in":"query","description":"End date (ISO format)","schema":{"type":"string"}},{"name":"workspaceId","required":false,"in":"query","description":"Filter stats by a single workspace ID (must be within the API key scope). Stats endpoints accept exactly one workspace, unlike list endpoints which support a comma-separated `workspaceIds` filter. Replaces the deprecated `teamId`.","schema":{"type":"string"}},{"name":"teamId","required":false,"in":"query","deprecated":true,"description":"**Deprecated** — use `workspaceId` instead. When set, the response includes a `Deprecation: true` header.","schema":{"type":"string"}}],"responses":{"200":{"description":"Call duration statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDurationStatsResponseDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Requested workspaceId/teamId is outside the API key scope"}},"security":[{"ApiKey":[]}],"summary":"Get call duration statistics","tags":["Statistics"]}},"/v1/stats/status-repartition":{"get":{"description":"Returns the distribution of calls by status, plus count of contacts not yet called. Pass `workspaceId` to narrow to a single workspace within the API key scope. The legacy `teamId` parameter is still accepted but adds a `Deprecation: true` response header.","operationId":"StatsController_getStatusRepartition","parameters":[{"name":"sequenceId","required":false,"in":"query","description":"Filter by sequence ID","schema":{"type":"string"}},{"name":"userMembershipId","required":false,"in":"query","description":"Filter by user membership ID","schema":{"type":"string"}},{"name":"callType","required":false,"in":"query","description":"Filter by call type. \"all\" includes sequence + direct calls.","schema":{"default":"all","type":"string","enum":["all","sequence","direct","inbound","outbound"]}},{"name":"granularity","required":false,"in":"query","description":"Time granularity for grouping results","schema":{"default":"none","type":"string","enum":["hour","day","week","month","none"]}},{"name":"startDate","required":false,"in":"query","description":"Start date (ISO format)","schema":{"type":"string"}},{"name":"endDate","required":false,"in":"query","description":"End date (ISO format)","schema":{"type":"string"}},{"name":"workspaceId","required":false,"in":"query","description":"Filter stats by a single workspace ID (must be within the API key scope). Stats endpoints accept exactly one workspace, unlike list endpoints which support a comma-separated `workspaceIds` filter. Replaces the deprecated `teamId`.","schema":{"type":"string"}},{"name":"teamId","required":false,"in":"query","deprecated":true,"description":"**Deprecated** — use `workspaceId` instead. When set, the response includes a `Deprecation: true` header.","schema":{"type":"string"}}],"responses":{"200":{"description":"Status distribution statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusRepartitionResponseDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Requested workspaceId/teamId is outside the API key scope"}},"security":[{"ApiKey":[]}],"summary":"Get call status distribution","tags":["Statistics"]}},"/v1/stats/tag-repartition":{"get":{"description":"Returns the distribution of contacts by tags applied after calls. Pass `workspaceId` to narrow to a single workspace within the API key scope. The legacy `teamId` parameter is still accepted but adds a `Deprecation: true` response header.","operationId":"StatsController_getTagRepartition","parameters":[{"name":"sequenceId","required":false,"in":"query","description":"Filter by sequence ID","schema":{"type":"string"}},{"name":"userMembershipId","required":false,"in":"query","description":"Filter by user membership ID","schema":{"type":"string"}},{"name":"callType","required":false,"in":"query","description":"Filter by call type. \"all\" includes sequence + direct calls.","schema":{"default":"all","type":"string","enum":["all","sequence","direct","inbound","outbound"]}},{"name":"granularity","required":false,"in":"query","description":"Time granularity for grouping results","schema":{"default":"none","type":"string","enum":["hour","day","week","month","none"]}},{"name":"startDate","required":false,"in":"query","description":"Start date (ISO format)","schema":{"type":"string"}},{"name":"endDate","required":false,"in":"query","description":"End date (ISO format)","schema":{"type":"string"}},{"name":"workspaceId","required":false,"in":"query","description":"Filter stats by a single workspace ID (must be within the API key scope). Stats endpoints accept exactly one workspace, unlike list endpoints which support a comma-separated `workspaceIds` filter. Replaces the deprecated `teamId`.","schema":{"type":"string"}},{"name":"teamId","required":false,"in":"query","deprecated":true,"description":"**Deprecated** — use `workspaceId` instead. When set, the response includes a `Deprecation: true` header.","schema":{"type":"string"}}],"responses":{"200":{"description":"Tag distribution statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagRepartitionResponseDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Requested workspaceId/teamId is outside the API key scope"}},"security":[{"ApiKey":[]}],"summary":"Get tag distribution","tags":["Statistics"]}},"/v1/teams":{"get":{"deprecated":true,"description":"**Deprecated** — Use GET /workspaces instead.","operationId":"TeamController_listTeams","parameters":[],"responses":{"200":{"description":"List of accessible teams","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTeamListResponseDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}}},"security":[{"ApiKey":[]}],"summary":"List teams accessible by this API key","tags":["Teams (deprecated — use /workspaces)"]}},"/v1/teams/stats":{"get":{"deprecated":true,"description":"**Deprecated** — Use GET /workspaces/stats instead.","operationId":"TeamController_getTeamStats","parameters":[{"name":"period","required":true,"in":"query","schema":{"example":"week","type":"string","enum":["day","week","month","custom"]}},{"name":"startDate","required":false,"in":"query","schema":{"example":"2026-01-01","type":"string"}},{"name":"endDate","required":false,"in":"query","schema":{"example":"2026-01-31","type":"string"}},{"name":"teamId","required":false,"in":"query","description":"Filter by team ID (must be within API key scope)","schema":{"type":"string"}}],"responses":{"200":{"description":"Team stats response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTeamStatsResponseDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}}},"security":[{"ApiKey":[]}],"summary":"Get stats aggregated by team","tags":["Teams (deprecated — use /workspaces)"]}},"/v1/workspaces":{"get":{"description":"Returns all workspaces within the scope of the API key.","operationId":"WorkspaceController_listWorkspaces","parameters":[],"responses":{"200":{"description":"List of accessible workspaces","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicWorkspaceListResponseDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}}},"security":[{"ApiKey":[]}],"summary":"List workspaces accessible by this API key","tags":["Workspaces"]}},"/v1/workspaces/stats":{"get":{"description":"Returns call, contact, and sequence stats per workspace. Scope is limited to the API key's accessible workspaces.","operationId":"WorkspaceController_getWorkspaceStats","parameters":[{"name":"period","required":true,"in":"query","schema":{"example":"week","type":"string","enum":["day","week","month","custom"]}},{"name":"startDate","required":false,"in":"query","schema":{"example":"2026-01-01","type":"string"}},{"name":"endDate","required":false,"in":"query","schema":{"example":"2026-01-31","type":"string"}},{"name":"workspaceId","required":false,"in":"query","description":"Filter by workspace ID (must be within API key scope)","schema":{"type":"string"}}],"responses":{"200":{"description":"Workspace stats response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicWorkspaceStatsResponseDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}}},"security":[{"ApiKey":[]}],"summary":"Get stats aggregated by workspace","tags":["Workspaces"]}},"/v1/workspaces/{id}/members":{"get":{"description":"Returns paginated members of a workspace. Each item exposes a workspace membership id (`id` field) usable as `assignedToWorkspaceMembershipId` when adding contacts to a sequence in this workspace. Includes members of every status; filter to ACTIVE if needed. Excludes pending workspace invitations that have no organization membership yet.","operationId":"WorkspaceController_listMembers","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","schema":{"minimum":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"minimum":1,"maximum":100,"example":50,"type":"number"}}],"responses":{"200":{"description":"Paginated workspace members","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedWorkspaceMembersDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Workspace not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"List members of a workspace","tags":["Workspaces"]}},"/v1/tags":{"get":{"description":"Returns a paginated list of tags scoped to the workspaces accessible by the API key. Use the `workspaceIds` query parameter to narrow results to a subset of those workspaces.","operationId":"TagController_list","parameters":[{"name":"workspaceIds","required":false,"in":"query","description":"Workspace IDs to narrow down results. Must be a subset of the workspaces accessible by the API key. Omit to return data from every workspace in scope. Accepts either a comma-separated string (`?workspaceIds=uuid1,uuid2`) — the documented format — or repeated array params (`?workspaceIds[]=uuid1&workspaceIds[]=uuid2`).","schema":{"example":"550e8400-e29b-41d4-a716-446655440000,6ba7b810-9dad-11d1-80b4-00c04fd430c8","type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"default":50,"example":50,"type":"number"}}],"responses":{"200":{"description":"Paginated list of tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedTagsDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"One or more requested workspaceIds are outside the API key scope"}},"security":[{"ApiKey":[]}],"summary":"List tags","tags":["Tags"]},"post":{"description":"Creates a new tag for use in sequences to qualify call results.","operationId":"TagController_create","parameters":[{"name":"x-workspace-id","in":"header","description":"Target workspace id (from `GET /v1/workspaces`). Required for multi-workspace API keys to designate which workspace to write to; omit for single-workspace keys, where it is resolved automatically. Must be within the API key scope.","required":false,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCreateTagDto"}}}},"responses":{"201":{"description":"Tag created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTagDto"}}}},"400":{"description":"Invalid input data"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}}},"security":[{"ApiKey":[]}],"summary":"Create a tag","tags":["Tags"]}},"/v1/tags/{id}":{"get":{"description":"Returns the details of a specific tag. Returns 404 if the tag is in a workspace outside the API key scope.","operationId":"TagController_get","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Tag details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTagDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Tag not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Get a tag by ID","tags":["Tags"]},"patch":{"description":"Updates an existing tag. Only provided fields will be updated. Returns 404 if the tag is in a workspace outside the API key scope.","operationId":"TagController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicUpdateTagDto"}}}},"responses":{"200":{"description":"Tag updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicTagDto"}}}},"400":{"description":"Invalid input data"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Tag not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Update a tag","tags":["Tags"]},"delete":{"description":"Deletes a tag. Cannot delete the last success tag — at least one must remain per workspace. Returns 404 if the tag is in a workspace outside the API key scope.","operationId":"TagController_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Tag deleted successfully"},"400":{"description":"Cannot delete the last success tag"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Tag not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Delete a tag","tags":["Tags"]}},"/v1/custom-fields":{"get":{"description":"Returns a paginated list of custom fields scoped to the workspaces accessible by the API key. Each custom field has a stable `slug` (immutable) and a human-readable `name` (editable). Use the `slug` as the key when setting custom field values on contacts. Use the `workspaceIds` query parameter to narrow results to a subset of those workspaces.","operationId":"CustomFieldController_list","parameters":[{"name":"workspaceIds","required":false,"in":"query","description":"Workspace IDs to narrow down results. Must be a subset of the workspaces accessible by the API key. Omit to return data from every workspace in scope. Accepts either a comma-separated string (`?workspaceIds=uuid1,uuid2`) — the documented format — or repeated array params (`?workspaceIds[]=uuid1&workspaceIds[]=uuid2`).","schema":{"example":"550e8400-e29b-41d4-a716-446655440000,6ba7b810-9dad-11d1-80b4-00c04fd430c8","type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number (1-indexed)","schema":{"minimum":1,"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":10,"example":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search query to filter custom fields by name","schema":{"maxLength":100,"example":"job","type":"string"}}],"responses":{"200":{"description":"Paginated list of custom fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedPublicCustomFieldsDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"One or more requested workspaceIds are outside the API key scope"}},"security":[{"ApiKey":[]}],"summary":"List custom fields","tags":["Custom Fields"]},"post":{"description":"Creates a new custom field in your organization. A stable `slug` is automatically generated from the `name` and returned in the response. The slug is immutable: renaming the custom field later will not change it.","operationId":"CustomFieldController_create","parameters":[{"name":"x-workspace-id","in":"header","description":"Target workspace id (from `GET /v1/workspaces`). Required for multi-workspace API keys to designate which workspace to write to; omit for single-workspace keys, where it is resolved automatically. Must be within the API key scope.","required":false,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCreateCustomFieldDto"}}}},"responses":{"201":{"description":"The created custom field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCustomFieldDto"}}}},"400":{"description":"Invalid input data"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"409":{"description":"A custom field with the same name already exists"}},"security":[{"ApiKey":[]}],"summary":"Create a custom field","tags":["Custom Fields"]}},"/v1/custom-fields/{id}":{"get":{"description":"Returns a single custom field by ID. Returns 404 if the custom field is in a workspace outside the API key scope.","operationId":"CustomFieldController_findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The custom field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCustomFieldDto"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Custom field not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Get a custom field","tags":["Custom Fields"]},"patch":{"description":"Updates an existing custom field name. The `slug` is **not** modified by this operation — it remains stable for integrations. Returns 404 if the custom field is in a workspace outside the API key scope.","operationId":"CustomFieldController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicUpdateCustomFieldDto"}}}},"responses":{"200":{"description":"The updated custom field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicCustomFieldDto"}}}},"400":{"description":"Invalid input data"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Custom field not found or outside API key scope"},"409":{"description":"A custom field with the same name already exists"}},"security":[{"ApiKey":[]}],"summary":"Update a custom field","tags":["Custom Fields"]},"delete":{"description":"Permanently deletes a custom field and all its associated values across contacts. Returns 404 if the custom field is in a workspace outside the API key scope.","operationId":"CustomFieldController_delete","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":"Custom field deleted successfully"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Invalid or revoked API key"},"status":{"type":"number","example":401}}}}}}}},"403":{"description":"Subscription required or plan not eligible","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"PLAN_NOT_ELIGIBLE"},"message":{"type":"string","example":"API access requires INTERMÉDIAIRE or EXPERT plan"},"status":{"type":"number","example":403}}}}}}}},"404":{"description":"Custom field not found or outside API key scope"}},"security":[{"ApiKey":[]}],"summary":"Delete a custom field","tags":["Custom Fields"]}}},"info":{"title":"Skipcall Public API","description":"## Overview\nThe Skipcall Public API allows you to integrate Skipcall with your applications, CRM, or automation tools.\n\n## Plan Requirements\nAPI access is available for **STARTER**, **INTERMÉDIAIRE**, **EXPERT** and **VOIP** plans.\n\n## Authentication\nAll API requests require authentication using an API Key. Include your API key in the `Authorization` header:\n\n```\nAuthorization: Bearer sk_live_your_api_key_here\n```\n\nYou can generate API keys from your Skipcall dashboard under Settings > API Keys.\n\n## Rate Limiting\nRate limits vary by subscription plan:\n\n| Plan | Rate Limit |\n|------|------------|\n| STARTER | 100 requests/minute |\n| INTERMÉDIAIRE | 100 requests/minute |\n| EXPERT | 1000 requests/minute |\n| VOIP | 100 requests/minute |\n\nLimits are counted per organization: every API key of the organization shares the same quota, so creating more keys does not raise it.\n\n### Per-endpoint limits\nSome endpoints have a tighter limit, also counted per organization:\n\n| Endpoint | Rate Limit |\n|----------|------------|\n| `GET /v1/calls` | 30 requests/minute |\n| `GET /v1/calls/{id}/recording/audio` | 10 requests/minute |\n| `GET /v1/calls/{id}/voicemail-drop/audio` | 10 requests/minute |\n\nThe stricter of the plan limit and the endpoint limit applies.\n\nRate limit headers are included in every response:\n- `X-RateLimit-Limit-plan`, `X-RateLimit-Remaining-plan`, `X-RateLimit-Reset-plan`: your plan quota, its remaining requests in the current window, and the seconds until it resets\n- `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`: the same values for the endpoint being called\n\n## Errors\nThe API uses standard HTTP status codes:\n- `200` - Success\n- `400` - Bad Request (invalid parameters)\n- `401` - Unauthorized (invalid or missing API key)\n- `403` - Forbidden (subscription required, plan not eligible, or call recording disabled for the workspace)\n- `404` - Not Found\n- `429` - Too Many Requests (rate limit exceeded)\n- `500` - Internal Server Error\n\n### Subscription Errors\n| Code | Description |\n|------|-------------|\n| `SUBSCRIPTION_REQUIRED` | An active subscription is required to access the API |\n| `PLAN_NOT_ELIGIBLE` | API access requires STARTER, INTERMÉDIAIRE, EXPERT or VOIP plan |\n\n### Recording Errors\n| Code | Description |\n|------|-------------|\n| `RECORDING_DISABLED` | Call recording is disabled for the workspace of the call (`GET /v1/calls/{id}/recording` and `GET /v1/calls/{id}/recording/audio`) |","version":"1.0","contact":{}},"tags":[{"name":"Contacts","description":"Manage your contacts"},{"name":"Calls","description":"Access call history and recordings"}],"servers":[{"url":"https://api-public.skipcall.app","description":"Production"}],"components":{"securitySchemes":{"ApiKey":{"scheme":"bearer","bearerFormat":"API Key","type":"http","description":"Enter your API Key (sk_live_xxx or sk_test_xxx)"}},"schemas":{"PublicContactDto":{"type":"object","properties":{"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"},"email":{"type":"object","example":"john.doe@example.com","nullable":true},"company":{"type":"object","example":"Acme Inc.","nullable":true},"city":{"type":"object","example":"Paris","nullable":true},"country":{"type":"object","example":"France","nullable":true},"url":{"type":"object","example":"https://example.com","nullable":true},"linkedinUrl":{"type":"object","example":"https://linkedin.com/in/johndoe","nullable":true},"linkedinSalesUrl":{"type":"object","example":"https://linkedin.com/sales/people/johndoe","nullable":true},"role":{"type":"object","example":"CTO","nullable":true},"allowPhoneCalls":{"type":"boolean","example":true},"callCount":{"type":"number","example":5},"lastCallAt":{"format":"date-time","type":"string","nullable":true},"teamId":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"phoneNumbers":{"example":["+33612345678"],"type":"array","items":{"type":"string"}},"customFields":{"type":"object","example":{"Industry":"Technology","Size":"50-100"},"additionalProperties":{"type":"string"}},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"lastModificationSource":{"type":"string","enum":["SKIPCALL","API"]}},"required":["id","firstName","lastName","allowPhoneCalls","callCount","teamId","phoneNumbers","customFields","createdAt","updatedAt","lastModificationSource"]},"PaginatedPublicContactsDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicContactDto"}},"total":{"type":"number","example":100},"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"totalPages":{"type":"number","example":10}},"required":["data","total","page","limit","totalPages"]},"PublicCreateContactDto":{"type":"object","properties":{"firstName":{"type":"string","description":"First name of the contact","example":"John","minLength":1,"maxLength":100},"lastName":{"type":"string","description":"Last name of the contact","example":"Doe","minLength":1,"maxLength":100},"email":{"type":"string","description":"Email address of the contact","example":"john.doe@example.com"},"company":{"type":"string","description":"Company name","example":"Acme Inc.","maxLength":200},"city":{"type":"string","description":"City","example":"Paris","maxLength":200},"country":{"type":"string","description":"Country","example":"France","maxLength":200},"url":{"type":"string","description":"Website URL","example":"https://example.com"},"linkedinUrl":{"type":"string","description":"LinkedIn profile URL","example":"https://linkedin.com/in/johndoe"},"linkedinSalesUrl":{"type":"string","description":"LinkedIn Sales Navigator URL","example":"https://linkedin.com/sales/people/johndoe"},"role":{"type":"string","description":"Role / job title","example":"CTO","maxLength":200},"allowPhoneCalls":{"type":"boolean","description":"Whether the contact accepts phone calls. Defaults to true.","example":true},"phoneNumbers":{"description":"Phone numbers in E.164 format (e.g., +33612345678)","example":["+33612345678"],"minItems":1,"maxItems":20,"type":"array","items":{"type":"string"}},"customFields":{"type":"object","description":"Custom field values keyed by the custom field **slug** (the stable, immutable identifier returned by GET /custom-fields). Custom fields must already exist for the team (use the Custom Fields endpoints to create them). For backwards compatibility this endpoint also accepts keys matching the custom field **name**, but this fallback is deprecated and will be removed in a future release — migrate your integrations to use slugs.","example":{"industry":"Technology","team_size":"50-100"},"additionalProperties":{"type":"string"},"maxProperties":100}},"required":["firstName","lastName","phoneNumbers"]},"ApiErrorDetail":{"type":"object","properties":{"code":{"type":"string","description":"Error code identifier","example":"UNAUTHORIZED","enum":["UNAUTHORIZED","FORBIDDEN","API_KEY_SCOPE_FORBIDDEN","SUBSCRIPTION_REQUIRED","PLAN_NOT_ELIGIBLE","RECORDING_DISABLED","VALIDATION_ERROR","NOT_FOUND","BAD_REQUEST","CONFLICT","CONTACT_ALREADY_EXISTS","RATE_LIMIT_EXCEEDED","INTERNAL_ERROR","SERVICE_UNAVAILABLE"]},"message":{"type":"string","description":"Human-readable error message","example":"Invalid or missing API key"},"status":{"type":"number","description":"HTTP status code","example":401},"contactId":{"type":"string","description":"Id of the existing contact. Only present with CONTACT_ALREADY_EXISTS (409 on POST /v1/contacts).","format":"uuid","example":"3f0c9a52-1b8e-4c3d-9a57-6e2f4d1b0c11"}},"required":["code","message","status"]},"ApiErrorResponseDto":{"type":"object","properties":{"error":{"description":"Error details","allOf":[{"$ref":"#/components/schemas/ApiErrorDetail"}]}},"required":["error"]},"PublicUpdateContactDto":{"type":"object","properties":{"firstName":{"type":"string","description":"First name of the contact","example":"John","minLength":1,"maxLength":100},"lastName":{"type":"string","description":"Last name of the contact","example":"Doe","minLength":1,"maxLength":100},"email":{"type":"string","description":"Email address of the contact","example":"john.doe@example.com"},"company":{"type":"string","description":"Company name","example":"Acme Inc.","maxLength":200},"city":{"type":"string","description":"City","example":"Paris","maxLength":200},"country":{"type":"string","description":"Country","example":"France","maxLength":200},"url":{"type":"string","description":"Website URL","example":"https://example.com"},"linkedinUrl":{"type":"string","description":"LinkedIn profile URL","example":"https://linkedin.com/in/johndoe"},"linkedinSalesUrl":{"type":"string","description":"LinkedIn Sales Navigator URL","example":"https://linkedin.com/sales/people/johndoe"},"role":{"type":"string","description":"Role / job title","example":"CTO","maxLength":200},"allowPhoneCalls":{"type":"boolean","description":"Whether the contact accepts phone calls","example":true},"phoneNumbers":{"description":"Phone numbers in E.164 format. If provided, replaces all existing phone numbers.","example":["+33612345678","+33698765432"],"minItems":1,"maxItems":20,"type":"array","items":{"type":"string"}},"customFields":{"type":"object","description":"Custom field values keyed by the custom field **slug** (the stable, immutable identifier returned by GET /custom-fields). Only provided keys are updated; omit to leave existing values untouched. Custom fields must already exist for the team. For backwards compatibility this endpoint also accepts keys matching the custom field **name**, but this fallback is deprecated and will be removed in a future release — migrate your integrations to use slugs.","example":{"industry":"Technology","team_size":"50-100"},"additionalProperties":{"type":"string"},"maxProperties":100}}},"CallContactSummaryDTO":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the contact"},"firstName":{"type":"string","example":"John","description":"First name of the contact"},"lastName":{"type":"string","example":"Doe","description":"Last name of the contact"},"isUnknown":{"type":"boolean","example":false,"description":"Whether this is an unknown contact (not in the system)"}},"required":["id","firstName","lastName","isUnknown"]},"CallPhoneNumberSummaryDTO":{"type":"object","properties":{"value":{"type":"string","example":"+33612345678","description":"The phone number value"}},"required":["value"]},"CallCallerSummaryDTO":{"type":"object","properties":{"firstName":{"type":"string","example":"Alice","description":"First name of the caller"},"lastName":{"type":"string","example":"Martin","description":"Last name of the caller"}},"required":["firstName","lastName"]},"CallWithContactDTO":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the call history entry"},"callType":{"type":"string","example":"CALL_SESSION","description":"Type of the call history entry (e.g., CALL_SESSION, DIRECT_CALL)","enum":["CALL_SESSION","DIRECT_CALL"]},"phoneNumberId":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174002","description":"Unique identifier of the phone number used for the call"},"userProviderSid":{"type":"string","example":"CA123456789","description":"Provider SID for the user side of the call"},"adminProviderSid":{"type":"object","example":"CA987654321","description":"Provider SID for the admin side of the call","nullable":true},"providerConferenceId":{"type":"string","example":"CF123456789","description":"Provider conference ID"},"status":{"type":"string","example":"completed","description":"Status of the call"},"type":{"type":"string","example":"outbound","description":"Type of call (e.g., outbound, inbound)"},"transferred":{"type":"boolean","example":false,"description":"Indicates if the call was transferred"},"startedAt":{"type":"object","example":"2024-03-20T09:00:00.000Z","description":"Start time of the call","nullable":true},"endedAt":{"type":"object","example":"2024-03-20T09:15:00.000Z","description":"End time of the call","nullable":true},"createdAt":{"format":"date-time","type":"string","example":"2024-03-20T08:55:00.000Z","description":"Date and time when the call history entry was created"},"updatedAt":{"format":"date-time","type":"string","example":"2024-03-20T09:16:00.000Z","description":"Date and time when the call history entry was last updated"},"sequenceRunId":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174003","description":"Unique identifier of the related sequence run"},"sequenceId":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174010","description":"Unique identifier of the parent sequence"},"syncedWithCrmDate":{"type":"object","example":"2024-03-20T09:15:00.000Z","description":"Date and time when the call was synced with CRM","nullable":true},"deletedAt":{"format":"date-time","type":"string","example":"2024-03-20T09:15:00.000Z","description":"Date and time when the call history entry was deleted","nullable":true},"organizationId":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174004","description":"Unique identifier of the organization"},"organizationMembershipId":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174005","description":"Unique identifier of the organization membership"},"managedPhoneNumberId":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174006","description":"Unique identifier of the managed phone number"},"notes":{"type":"string","example":"Call notes here","description":"Notes associated with the call"},"voicemailClipDropped":{"type":"boolean","example":true,"description":"Whether a voicemail clip was dropped on the answering machine (responder outcome). Always false for direct calls."},"voicemailSmsSent":{"type":"boolean","example":false,"description":"Whether the responder SMS was sent after reaching an answering machine. Always false for direct calls."},"voicemailSmsStatus":{"type":"string","enum":["PENDING","SENT","DELIVERED","FAILED"],"nullable":true,"description":"Granular responder-SMS lifecycle (PENDING/SENT/DELIVERED/FAILED); null if no responder SMS was queued (always null for direct calls)"},"voicemailClipId":{"type":"string","nullable":true,"description":"ID of the voicemail clip dropped on this call (null if the clip was deleted)."},"voicemailSmsBody":{"type":"string","nullable":true,"description":"Body of the responder SMS sent on this call (null if no SMS was sent)."},"recordingDiscardedAt":{"format":"date-time","type":"string","example":"2024-03-20T09:15:01.000Z","description":"When Skipcall deliberately discarded the call's recording (call too short or voicemail call). Null otherwise, including calls made before this field existed.","nullable":true},"contact":{"description":"Contact information associated with the call","nullable":true,"allOf":[{"$ref":"#/components/schemas/CallContactSummaryDTO"}]},"phoneNumber":{"description":"Phone number information associated with the call","nullable":true,"allOf":[{"$ref":"#/components/schemas/CallPhoneNumberSummaryDTO"}]},"caller":{"description":"Caller information (organization member who made the call)","nullable":true,"allOf":[{"$ref":"#/components/schemas/CallCallerSummaryDTO"}]},"callerPhoneNumber":{"description":"Managed phone number used by the caller","nullable":true,"allOf":[{"$ref":"#/components/schemas/CallPhoneNumberSummaryDTO"}]}},"required":["id","callType","status","type","startedAt","endedAt","createdAt","voicemailClipDropped","voicemailSmsSent","contact","phoneNumber","caller","callerPhoneNumber"]},"PaginatedCallDTO":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CallWithContactDTO"}},"total":{"type":"number","example":100},"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"totalPages":{"type":"number","example":10}},"required":["data","total","page","limit","totalPages"]},"PublicCallRecordingDTO":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the recording"},"duration":{"type":"number","example":245,"description":"Duration of the recording in seconds"},"startTime":{"format":"date-time","type":"string","example":"2024-01-15T10:00:00Z","description":"Start time of the recording"},"hasTranscription":{"type":"boolean","example":true,"description":"Indicates if a transcription exists for this recording"},"transcriptionStatus":{"type":"string","example":"COMPLETED","description":"Status of the transcription if it exists","enum":["PENDING","IN_PROGRESS","FAILED","COMPLETED"],"nullable":true},"audioUrl":{"type":"string","example":"https://api-public.skipcall.app/v1/calls/123e4567-e89b-12d3-a456-426614174000/recording/audio","description":"Absolute URL of the audio stream of this recording (`GET /v1/calls/{id}/recording/audio`). Call it with the same API key (`Authorization: Bearer sk_live_…`): it is not a public or pre-signed link. Supports `?format=wav` and `?download=true`."}},"required":["id","duration","startTime","hasTranscription","transcriptionStatus","audioUrl"]},"TranscriptUtteranceDTO":{"type":"object","properties":{"speaker":{"type":"number","example":0,"description":"Speaker identifier (0 or 1)"},"text":{"type":"string","example":"Hello, this is John from...","description":"Transcribed text for this utterance"},"start":{"type":"number","example":0.5,"description":"Start time in seconds"},"end":{"type":"number","example":3.2,"description":"End time in seconds"},"confidence":{"type":"number","example":0.95,"description":"Confidence score (0-1)"}},"required":["speaker","text","start","end","confidence"]},"PublicCallTranscriptionDTO":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the transcription"},"status":{"type":"string","example":"COMPLETED","description":"Status of the transcription","enum":["PENDING","IN_PROGRESS","FAILED","COMPLETED"]},"transcript":{"description":"Array of transcribed utterances","nullable":true,"type":"array","items":{"$ref":"#/components/schemas/TranscriptUtteranceDTO"}},"summary":{"type":"string","example":"Discussion about product features...","description":"AI-generated summary of the conversation","nullable":true},"startedAt":{"type":"string","format":"date-time","example":"2024-01-15T10:00:00Z","description":"When transcription processing started","nullable":true},"endedAt":{"type":"string","format":"date-time","example":"2024-01-15T10:00:45Z","description":"When transcription processing completed","nullable":true}},"required":["id","status","transcript","summary","startedAt","endedAt"]},"UserDto":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the user"},"organizationMembershipId":{"type":"string","example":"987e6543-e21b-45d3-b678-426614174001","description":"Unique identifier of the organization membership. Use this ID when creating sequences."},"firstName":{"type":"object","example":"John","description":"First name of the user","nullable":true},"lastName":{"type":"object","example":"Doe","description":"Last name of the user","nullable":true},"email":{"type":"string","example":"john.doe@example.com","description":"Email address of the user"},"role":{"type":"string","example":"MEMBER","description":"Role of the user in the organization","enum":["ADMIN","MEMBER"]},"status":{"type":"string","example":"ACTIVE","description":"Status of the user membership in the organization","enum":["ACTIVE","INACTIVE","PENDING"]}},"required":["id","organizationMembershipId","email","role","status"]},"PaginatedUsersDto":{"type":"object","properties":{"data":{"description":"Array of users","type":"array","items":{"$ref":"#/components/schemas/UserDto"}},"total":{"type":"number","example":100},"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"totalPages":{"type":"number","example":10}},"required":["data","total","page","limit","totalPages"]},"CreateSequenceDto":{"type":"object","properties":{"name":{"type":"string","description":"Sequence name","example":"My Sales Sequence"},"assignedToIds":{"description":"OrganizationMembership IDs of users to assign this sequence to","example":["123e4567-e89b-12d3-a456-426614174001","123e4567-e89b-12d3-a456-426614174002"],"type":"array","items":{"type":"string"}},"creatorId":{"type":"string","description":"OrganizationMembership ID of the creator. Use the /users endpoint to get available organizationMembershipIds.","example":"123e4567-e89b-12d3-a456-426614174000"},"contactIds":{"description":"Contact IDs to add to the sequence","example":["123e4567-e89b-12d3-a456-426614174010","123e4567-e89b-12d3-a456-426614174011"],"type":"array","items":{"type":"string"}}},"required":["name","assignedToIds","creatorId"]},"AssignedUserDto":{"type":"object","properties":{"organizationMembershipId":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"OrganizationMembership ID of the assigned user"},"firstName":{"type":"object","example":"John","description":"First name of the assigned user","nullable":true},"lastName":{"type":"object","example":"Doe","description":"Last name of the assigned user","nullable":true},"email":{"type":"string","example":"john.doe@example.com","description":"Email of the assigned user"}},"required":["organizationMembershipId","email"]},"SequenceDto":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the sequence"},"name":{"type":"string","example":"My Sales Sequence","description":"Name of the sequence"},"organizationMembershipId":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174001","description":"OrganizationMembership ID of the creator"},"createdAt":{"format":"date-time","type":"string","example":"2024-01-15T10:30:00.000Z","description":"Date when the sequence was created"},"updatedAt":{"format":"date-time","type":"string","example":"2024-01-15T10:30:00.000Z","description":"Date when the sequence was last updated"},"contactCount":{"type":"number","example":150,"description":"Number of contacts in the sequence"},"assignedTo":{"description":"List of users assigned to this sequence","type":"array","items":{"$ref":"#/components/schemas/AssignedUserDto"}}},"required":["id","name","organizationMembershipId","createdAt","updatedAt"]},"PaginatedSequencesDto":{"type":"object","properties":{"data":{"description":"Array of sequences","type":"array","items":{"$ref":"#/components/schemas/SequenceDto"}},"total":{"type":"number","example":100},"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"totalPages":{"type":"number","example":10}},"required":["data","total","page","limit","totalPages"]},"SequenceContactPhoneNumberDto":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the phone number"},"number":{"type":"string","example":"+33612345678","description":"Phone number in E.164 format"}},"required":["id","number"]},"SequenceContactContactDto":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the contact"},"firstName":{"type":"string","example":"John","description":"First name of the contact"},"lastName":{"type":"string","example":"Doe","description":"Last name of the contact"},"email":{"type":"object","example":"john.doe@example.com","description":"Email address of the contact","nullable":true},"company":{"type":"object","example":"Acme Corp","description":"Company of the contact","nullable":true},"phoneNumbers":{"description":"Phone numbers associated with the contact","type":"array","items":{"$ref":"#/components/schemas/SequenceContactPhoneNumberDto"}}},"required":["id","firstName","lastName"]},"SequenceContactTagDto":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the tag"},"label":{"type":"string","example":"hot-lead","description":"Label of the tag"},"isSuccessTag":{"type":"boolean","example":true,"description":"Whether this tag is a success tag"}},"required":["id","label","isSuccessTag"]},"SequenceContactCallDto":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the call session"},"status":{"type":"string","enum":["NOT_INITIATED","INITIATED","QUEUED","RINGING","IN_PROGRESS","BUSY","NO_ANSWER","MISSED_CALL","VOICEMAIL","CONNECTED","CANCELLED","COMPLETED","ERROR_NUMBER","ERROR_COUNTRY","UNKNOWN_ERROR"],"example":"COMPLETED","description":"Status of the call"},"startedAt":{"type":"object","example":"2024-01-15T10:30:00.000Z","description":"Date and time when the call started","nullable":true},"endedAt":{"type":"object","example":"2024-01-15T10:32:30.000Z","description":"Date and time when the call ended","nullable":true},"durationSeconds":{"type":"object","example":150,"description":"Duration of the call in seconds (endedAt - startedAt)","nullable":true},"createdAt":{"format":"date-time","type":"string","example":"2024-01-15T10:30:00.000Z","description":"Date and time when the call record was created"}},"required":["id","status","createdAt"]},"SequenceContactDto":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the sequence contact record"},"status":{"type":"string","enum":["CONNECTED","RESPONDER","ERROR","CANCELLED","RUNNING","MISSING_NUMBER"],"example":"CONNECTED","description":"Status of the contact in the sequence","nullable":true},"contact":{"description":"Contact information","allOf":[{"$ref":"#/components/schemas/SequenceContactContactDto"}]},"tags":{"description":"Tags associated with this contact in the sequence","type":"array","items":{"$ref":"#/components/schemas/SequenceContactTagDto"}},"calls":{"description":"Calls made to this contact in the sequence","type":"array","items":{"$ref":"#/components/schemas/SequenceContactCallDto"}},"createdAt":{"format":"date-time","type":"string","example":"2024-01-15T10:30:00.000Z","description":"Date when the contact was added to the sequence"}},"required":["id","contact","tags","calls","createdAt"]},"PaginatedSequenceContactsDto":{"type":"object","properties":{"data":{"description":"Array of sequence contacts","type":"array","items":{"$ref":"#/components/schemas/SequenceContactDto"}},"total":{"type":"number","example":100},"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"totalPages":{"type":"number","example":10}},"required":["data","total","page","limit","totalPages"]},"ContactAssignmentDto":{"type":"object","properties":{"contactId":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000","description":"The contact UUID (v4)."},"assignedToWorkspaceMembershipId":{"type":"string","format":"uuid","example":"987e6543-e21b-45d3-b678-426614174001","description":"Optional workspace-membership UUID identifying the assignee (the user within the workspace). Obtain via GET /v1/workspaces/:id/members. If omitted, the contact is auto-assigned via round-robin among the sequence assignees. If provided, must belong to the sequence workspace AND be one of the sequence assignees, otherwise 400."}},"required":["contactId"]},"ContactAssignmentBatchDto":{"type":"object","properties":{"contacts":{"minItems":1,"maxItems":100,"description":"Array of 1–100 contact assignment entries. Per item: `contactId` is required; `assignedToWorkspaceMembershipId` optional. Duplicates, contacts already in the sequence, and out-of-scope contacts are silently ignored.","type":"array","items":{"$ref":"#/components/schemas/ContactAssignmentDto"}}},"required":["contacts"]},"ContactsBatchDto":{"type":"object","properties":{"contactIds":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100,"example":["123e4567-e89b-12d3-a456-426614174000","123e4567-e89b-12d3-a456-426614174001"],"description":"Array of contact UUIDs (1–100). Duplicates and out-of-scope contacts are ignored silently."}},"required":["contactIds"]},"CallDurationStatsDto":{"type":"object","properties":{"callCount":{"type":"number","description":"Number of calls"},"avgDurationInSeconds":{"type":"number","description":"Average call duration in seconds"},"totalDurationInSeconds":{"type":"number","description":"Total call duration in seconds"},"date":{"type":"string","description":"Date bucket (when granularity is not \"none\")","example":"2023-10-01T00:00:00.000Z"}},"required":["callCount","avgDurationInSeconds","totalDurationInSeconds"]},"CallDurationStatsResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CallDurationStatsDto"}}},"required":["data"]},"CallSessionStatuses":{"type":"string","enum":["NOT_INITIATED","INITIATED","QUEUED","RINGING","IN_PROGRESS","BUSY","NO_ANSWER","MISSED_CALL","VOICEMAIL","CONNECTED","CANCELLED","COMPLETED","ERROR_NUMBER","ERROR_COUNTRY","UNKNOWN_ERROR"],"description":"Call session status"},"StatusRepartitionItemDto":{"type":"object","properties":{"status":{"description":"Call session status","allOf":[{"$ref":"#/components/schemas/CallSessionStatuses"}]},"count":{"type":"number","description":"Number of calls with this status"},"date":{"type":"string","description":"Date bucket (when granularity is not \"none\")","example":"2023-10-01T00:00:00.000Z"}},"required":["status","count"]},"StatusRepartitionResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StatusRepartitionItemDto"}},"nonCalledCount":{"type":"number","description":"Number of contacts that have not been called yet"}},"required":["data","nonCalledCount"]},"TagRepartitionItemDto":{"type":"object","properties":{"tagId":{"type":"string","description":"Tag ID"},"label":{"type":"string","description":"Tag label"},"count":{"type":"number","description":"Number of contacts with this tag"},"isSuccess":{"type":"boolean","description":"Whether this tag indicates success"},"date":{"type":"string","description":"Date bucket (when granularity is not \"none\")","example":"2023-10-01T00:00:00.000Z"}},"required":["tagId","label","count","isSuccess"]},"TagRepartitionResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TagRepartitionItemDto"}}},"required":["data"]},"PublicTeamDto":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","example":"Sales"},"isDefault":{"type":"boolean","example":false},"memberCount":{"type":"number","example":5}},"required":["id","name","isDefault","memberCount"]},"PublicTeamListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicTeamDto"}}},"required":["data"]},"PublicAggregateStatsDto":{"type":"object","properties":{"totalCalls":{"type":"number","example":1250},"totalCallDuration":{"type":"number","example":45000},"totalContacts":{"type":"number","example":3400},"activeSequences":{"type":"number","example":12}},"required":["totalCalls","totalCallDuration","totalContacts","activeSequences"]},"PublicTeamStatsItemDto":{"type":"object","properties":{"teamId":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000"},"teamName":{"type":"string","example":"Sales"},"calls":{"type":"number","example":450},"callDuration":{"type":"number","example":15000},"contacts":{"type":"number","example":1200},"activeSequences":{"type":"number","example":4},"members":{"type":"number","example":5}},"required":["teamId","teamName","calls","callDuration","contacts","activeSequences","members"]},"PublicTeamStatsResponseDto":{"type":"object","properties":{"aggregate":{"$ref":"#/components/schemas/PublicAggregateStatsDto"},"teams":{"type":"array","items":{"$ref":"#/components/schemas/PublicTeamStatsItemDto"}}},"required":["aggregate","teams"]},"PublicWorkspaceDto":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","example":"Sales"},"isDefault":{"type":"boolean","example":false},"memberCount":{"type":"number","example":5}},"required":["id","name","isDefault","memberCount"]},"PublicWorkspaceListResponseDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicWorkspaceDto"}}},"required":["data"]},"PublicWorkspaceAggregateStatsDto":{"type":"object","properties":{"totalCalls":{"type":"number","example":1250},"totalCallDuration":{"type":"number","example":45000},"totalContacts":{"type":"number","example":3400},"activeSequences":{"type":"number","example":12}},"required":["totalCalls","totalCallDuration","totalContacts","activeSequences"]},"PublicWorkspaceStatsItemDto":{"type":"object","properties":{"workspaceId":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000"},"workspaceName":{"type":"string","example":"Sales"},"calls":{"type":"number","example":450},"callDuration":{"type":"number","example":15000},"contacts":{"type":"number","example":1200},"activeSequences":{"type":"number","example":4},"members":{"type":"number","example":5}},"required":["workspaceId","workspaceName","calls","callDuration","contacts","activeSequences","members"]},"PublicWorkspaceStatsResponseDto":{"type":"object","properties":{"aggregate":{"$ref":"#/components/schemas/PublicWorkspaceAggregateStatsDto"},"workspaces":{"type":"array","items":{"$ref":"#/components/schemas/PublicWorkspaceStatsItemDto"}}},"required":["aggregate","workspaces"]},"WorkspaceMemberUserDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"firstName":{"type":"object","nullable":true,"example":"Alice"},"lastName":{"type":"object","nullable":true,"example":"Dupont"},"email":{"type":"string","example":"alice@example.com"}},"required":["id","email"]},"WorkspaceMemberDto":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Workspace membership ID (the user within the workspace). Use this as `assignedToWorkspaceMembershipId` when adding contacts to a sequence in this workspace.","example":"987e6543-e21b-45d3-b678-426614174001"},"role":{"type":"string","enum":["ADMIN","MEMBER"],"example":"MEMBER","description":"Organization-level role of the user. Not the workspace-scoped role."},"status":{"type":"string","enum":["ACTIVE","INACTIVE","PENDING"],"example":"ACTIVE","description":"Organization-level membership status. Not the workspace-scoped status."},"user":{"$ref":"#/components/schemas/WorkspaceMemberUserDto"}},"required":["id","role","status","user"]},"PaginatedWorkspaceMembersDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceMemberDto"}},"total":{"type":"number","example":100},"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"totalPages":{"type":"number","example":10}},"required":["data","total","page","limit","totalPages"]},"PublicTagDto":{"type":"object","properties":{"id":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000","description":"Unique identifier of the tag"},"label":{"type":"string","example":"Lead","description":"Label of the tag"},"isSuccessTag":{"type":"boolean","example":true,"description":"Whether the tag represents a successful call outcome"},"createdAt":{"format":"date-time","type":"string","example":"2024-01-15T10:30:00.000Z","description":"Date when the tag was created"},"updatedAt":{"format":"date-time","type":"string","example":"2024-01-15T10:30:00.000Z","description":"Date when the tag was last updated"}},"required":["id","label","isSuccessTag","createdAt","updatedAt"]},"PaginatedTagsDto":{"type":"object","properties":{"data":{"description":"Array of tags","type":"array","items":{"$ref":"#/components/schemas/PublicTagDto"}},"total":{"type":"number","example":100},"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"totalPages":{"type":"number","example":10}},"required":["data","total","page","limit","totalPages"]},"PublicCreateTagDto":{"type":"object","properties":{"label":{"type":"string","example":"Lead","description":"The label of the tag"},"isSuccessTag":{"type":"boolean","example":false,"description":"Whether the tag represents a successful call outcome","default":false}},"required":["label"]},"PublicUpdateTagDto":{"type":"object","properties":{"label":{"type":"string","example":"Lead","description":"The label of the tag"},"isSuccessTag":{"type":"boolean","example":false,"description":"Whether the tag represents a successful call outcome","default":false}}},"PublicCustomFieldDto":{"type":"object","properties":{"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"name":{"type":"string","example":"Job Title","description":"Human-readable label. Can be renamed without breaking integrations."},"slug":{"type":"string","example":"job_title","description":"Stable, immutable identifier derived from the name at creation time. Use this as the key when setting custom field values on a contact via POST/PATCH /contacts."},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","name","slug","createdAt","updatedAt"]},"PaginatedPublicCustomFieldsDto":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PublicCustomFieldDto"}},"total":{"type":"number","example":100},"page":{"type":"number","example":1},"limit":{"type":"number","example":10},"totalPages":{"type":"number","example":10}},"required":["data","total","page","limit","totalPages"]},"PublicCreateCustomFieldDto":{"type":"object","properties":{"name":{"type":"string","description":"Name of the custom field","example":"Job Title","minLength":1,"maxLength":200}},"required":["name"]},"PublicUpdateCustomFieldDto":{"type":"object","properties":{"name":{"type":"string","description":"Name of the custom field","example":"Job Title","minLength":1,"maxLength":200}},"required":["name"]}}}}