{"openapi":"3.0.0","paths":{"/users/me":{"get":{"operationId":"getProfile","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetUserProfileResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Get current user profile","tags":["users"]}},"/users/me/contacts/sync":{"post":{"description":"Bulk upsert of contacts from the device address book, keyed on `userId + phoneNumber`. Existing contacts are updated with the most recent values, new ones are created. Rows missing `phoneNumber` or missing BOTH `firstName` AND `companyName` are silently skipped and counted. Phone numbers are normalized (strips `()`, `-`, spaces) so formatting variations don't create duplicates. Does NOT emit timeline activity — this is a silent sync.","operationId":"syncContacts","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncContactsDto"}}}},"responses":{"200":{"description":"Contacts synced successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasicResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Sync contacts from mobile device","tags":["users"]}},"/users/me/contacts":{"delete":{"description":"When `id` query param is provided, deletes only that contact. When omitted, deletes ALL of the user's contacts and requires request body `{\"confirmation\":\"delete all\"}`. The cleanup runs in one transaction: contact-only rows are removed, and calls/SMS/tasks/follow-ups/appointments are retained with `contactId` cleared.","operationId":"deleteAllContacts","parameters":[{"name":"id","required":false,"in":"query","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteContactsDto"}}}},"responses":{"200":{"description":"All contacts deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasicResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Delete all contacts","tags":["users"]},"get":{"description":"Paginated list of non-deleted contacts with per-contact stats (call counts, last interaction date) and aggregations (unique company count + list). `sort` accepts `lastInteraction`, `created`, or `name` — invalid values silently fall back to `created`. Sorting by `lastInteraction` is indexed but can get slow above ~10k contacts; prefer `created` for the default list view.","operationId":"getContacts","parameters":[{"name":"limit","required":false,"in":"query","schema":{"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"type":"number"}},{"name":"sort","required":false,"in":"query","description":"Sort contacts by: lastInteraction, created, or name","schema":{"enum":["lastInteraction","created","name"],"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactSearchResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Get all contacts","tags":["users"]}},"/users/me/contacts/{id}":{"patch":{"description":"Partial update of a single contact's fields: name, email, company, avatar, tags, `isFavorite`, `lifecycleStage`, `doNotCall`, `doNotSms`. Changing `phoneNumber` resets the contact's identity key — avoid unless intentional. `doNotCall` and `doNotSms` act as outbound suppression flags; enforcement happens at send time, not in this endpoint.","operationId":"updateContact","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactItemResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Update contact","tags":["users"]},"get":{"description":"Returns contact details enriched with totalIncomingCalls, totalOutboundCalls, totalSmsMessages, lastCallDate, upcomingAppointments","operationId":"getContact","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactItemResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Get a single contact with stats","tags":["users"]}},"/users/me/contacts/duplicates":{"get":{"description":"Returns candidate duplicate pairs grouped by either phone (last 10 digits of the normalized number match) or name (fuzzy similarity > 0.8, Levenshtein-like). Each group carries a `matchType` and a `confidence` hint. Run this after large imports before calling `/merge` — phone matches are high-confidence, name matches produce false positives for common names and should always be reviewed by a human.","operationId":"getDuplicateContacts","parameters":[],"responses":{"200":{"description":"List of potential duplicate contact pairs"}},"security":[{"bearer":[]}],"summary":"Find duplicate contacts","tags":["users"]}},"/users/me/contacts/merge":{"post":{"description":"Keeps the primary contact and reassigns all linked records (calls, SMS, notes, tasks, appointments) from secondary to primary, then soft-deletes the secondary. Field conflicts are resolved by `mergedData` — whatever you pass wins, so the client must decide ahead of time which values to keep. Irreversible: the secondary's `deletedAt` is set, history is preserved under the primary.","operationId":"mergeContacts","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MergeContactsDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BasicResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Merge two duplicate contacts","tags":["users"]}},"/users/me/contacts/search":{"post":{"description":"Full-text, typo-tolerant search across name, phone, company, and tags. Results are ranked by similarity then recency. If the query contains digits, also matches against the normalized (digits-only, last 10) phone so `555-123` and `(555) 123` find the same contact. With `injectCalls=true`, recent matching calls are returned as synthetic contacts (source `WEB`, max 5) — useful for surfacing numbers that aren't saved yet.","operationId":"searchContacts","parameters":[{"name":"query","required":true,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"number"}},{"name":"offset","required":false,"in":"query","schema":{"type":"number"}},{"name":"injectCalls","required":false,"in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactSearchResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Search contacts","tags":["users"]}},"/users/me/contacts/import":{"post":{"description":"Bulk import from arbitrary CSV or JSON. An AI pass reads the first 10 lines / 500 chars and auto-maps unknown column names to canonical contact fields (`firstName`, `lastName`, `phoneNumber`, `email`, `address`, `companyName`, `notes`, `tags`). If mapping fails, sensible defaults are used. Rows missing a valid phone, or missing BOTH `firstName` and `companyName`, are rejected with per-row errors; valid rows merge by phone rather than creating duplicates. Comma-separated tag strings are split into arrays.","operationId":"importContacts","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportContactsDto"}}}},"responses":{"200":{"description":"Contacts imported successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportContactsResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Import contacts from CSV or JSON file","tags":["users"]}},"/users/me/contacts/tags":{"get":{"description":"Returns all tags used across the user's contacts with occurrence counts, sorted by count DESC. Feeds frontend tag autocomplete and tag-cloud widgets. Only contacts with non-empty `tags` arrays contribute — newly-invented tags that aren't yet assigned to any contact won't appear. Tag matching is case-sensitive, so \"VIP\" and \"vip\" count as separate tags.","operationId":"getTagStats","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagStatsResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Get tag statistics for autocomplete","tags":["users"]}},"/users/me/contacts/advanced-search":{"post":{"description":"Multi-criteria filter with AND between groups and OR within a group: `name` is split on spaces and matched against `firstName`/`lastName`/`companyName` (and `phoneNumber` if it contains digits, with phone normalization), `companies` matches any in the array, `tags` matches any in the array. Supports custom `sortBy` and `sortOrder`. Tag filtering is case-sensitive — keep tag naming consistent across the app. Combining many filters narrows results aggressively.","operationId":"advancedSearch","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdvancedSearchDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactSearchResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Advanced search in contacts by name, company, and tags","tags":["users"]}},"/users/me/contacts/{id}/notes":{"get":{"description":"Returns all notes attached to the contact, ordered by `createdAt DESC`. Notes are user-scoped by default: team members only see their own notes unless `isPublic: true` was set when the note was created (team accounts feature). Use this for a dedicated notes tab; the same notes also appear in the contact timeline.","operationId":"getCustomerNotes","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"List notes for a customer (newest first)","tags":["users"]},"post":{"description":"Attaches a free-text note to the contact and records the activity in its timeline. `isPublic` controls team visibility — defaults to private (visible only to the author). Notes are a human-authored layer separate from AI-generated summaries: keep them for context that the agent can't infer from transcripts (deal notes, manual follow-ups, offline context).","operationId":"addCustomerNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCustomerNoteDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Add a note to a customer","tags":["users"]}},"/users/me/contacts/{id}/timeline":{"get":{"description":"Paginated, unified activity feed — inbound/outbound calls, SMS, notes, tasks, appointments, file uploads, custom field changes — sorted newest-first. This endpoint is read-only; to create activity, hit the specific endpoints (`/notes`, `/schedule-call`, `/send-sms`, etc.) and the timeline entry is written automatically. Aggregation is capped at ~1000 activities per contact; use `limit`/`offset` pagination for very active contacts to avoid slow loads.","operationId":"getCustomerTimeline","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":true,"in":"query","schema":{"type":"string"}},{"name":"offset","required":true,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get unified timeline for a customer","tags":["users"]}},"/users/me/contacts/{id}/notes/{noteId}":{"patch":{"description":"Updates note content and/or toggles the `isPublic` flag. The note ID is scoped to the caller's user ID and the current contact, so you can't edit someone else's note or a note from another customer.","operationId":"updateCustomerNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"noteId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomerNoteDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Update a customer note","tags":["users"]},"delete":{"description":"Removes a note from the contact. The timeline entry for the note remains unless separately removed.","operationId":"deleteCustomerNote","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"noteId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Delete a customer note","tags":["users"]}},"/users/me/contacts/{id}/custom-fields":{"patch":{"description":"Sets values for one or more user-defined custom fields on a contact. Each key must match an existing custom field definition — unknown keys are silently ignored. Values are validated against the field's type and (for `SELECT`/`MULTI_SELECT`) its options. Passing `null` clears the field; clearing a field marked `isRequired` returns a validation error. The change is recorded on the contact timeline.","operationId":"updateCustomerFields","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Update custom fields on a customer","tags":["users"]}},"/calendars/appointments":{"get":{"description":"Returns appointments booked via calls or imported from connected calendars (Google, Outlook, Calendly, Square, Cal.com, GHL). Supports pagination (1-indexed `page`, max 100 per page — different from the 0-indexed offset used by `/calls`), plus filters by `period` ('upcoming' | 'past' | 'all'), `agentId`, `calendarId`, and free-text `search` across phone/email/title. Appointments only appear if at least one calendar is connected and enabled.","operationId":"listAppointments","parameters":[{"name":"page","required":false,"in":"query","schema":{"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","schema":{"default":20,"type":"number"}},{"name":"period","required":false,"in":"query","schema":{"default":"all","type":"string","enum":["upcoming","past","all"]}},{"name":"agentId","required":false,"in":"query","schema":{"type":"string"}},{"name":"calendarId","required":false,"in":"query","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Search by phone, email, or title","schema":{"type":"string"}},{"name":"from","required":false,"in":"query","description":"Filter from date (ISO string)","schema":{"type":"string"}},{"name":"to","required":false,"in":"query","description":"Filter to date (ISO string)","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentsListResponseDto"}}}}},"summary":"List booked appointments","tags":["Calendars"]}},"/calendars/appointments/upcoming":{"get":{"description":"Lightweight endpoint for dashboard/widget UIs — returns the next N confirmed appointments sorted by `startTime` ascending (nearest first), default limit 5. Tentative appointments are excluded. Use `/calendars/appointments` with `period='upcoming'` when you need full pagination, filtering, or the unabridged appointment payload.","operationId":"getUpcomingAppointments","parameters":[{"name":"limit","required":false,"in":"query","schema":{"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AppointmentResponseDto"}}}}}},"summary":"Get upcoming appointments for widget","tags":["Calendars"]}},"/calendars/appointments/stats":{"get":{"description":"Returns count buckets for dashboard summary cards: total `upcoming`, `thisWeek`, `thisMonth`, and all-time `total`. \"This week\" and \"this month\" are relative to today in the user's timezone. Aggregates across every connected calendar provider (Google, Outlook, Calendly, Square, Cal.com, GHL) — no way to scope to a single calendar from this endpoint.","operationId":"getAppointmentStats","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentStatsDto"}}}}},"summary":"Get appointment statistics","tags":["Calendars"]}},"/calendars/appointments/{id}":{"get":{"description":"Returns the full appointment record including the external calendar event URL (`externalEventUrl` — deep link to Google Calendar, Calendly, etc.), the creating call reference (`callId` + `callDetailsUrl`), and whether it came from an inbound or outbound call (`isIncoming`). Useful for building detail views after `/calendars/appointments` or `/calendars/appointments/upcoming`.","operationId":"getAppointment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentResponseDto"}}}}},"summary":"Get a single appointment","tags":["Calendars"]},"delete":{"description":"Soft-deletes the appointment from SkipCalls only. The event REMAINS in the external calendar provider (Google, Outlook, Calendly, Square, Cal.com, GHL) — this endpoint does NOT cancel the booking with the customer. To fully cancel, also delete the event from the provider UI or via the `cancel_event` LLM tool during a call. There is no restore endpoint.","operationId":"deleteAppointment","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Hide/delete an appointment from the list","tags":["Calendars"]}},"/calls/transcribe":{"post":{"description":"Converts base64-encoded audio into text. Used for voice input in the chat UI so users can speak instead of typing. Accepts common formats (webm, mp3, wav, m4a, ogg). Audio must be a base64 data URL. Not intended for call transcription — call transcripts are generated automatically during the call lifecycle.","operationId":"transcribe","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranscribeDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TranscribeResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Transcribe audio (for chat)","tags":["calls"]}},"/calls/schedule":{"post":{"description":"Queues an outbound call. Creates the record in QUEUED status (or NOT_STARTED if scheduled for a future time). Runs validation: phone format and country checks (rejects VOIP/premium/shared-cost numbers for US/CA), destination-country restriction (your phone numbers must match the destination country), rate limits, balance check against `maxDurationMinutes`, and a content safety review. If the goal is ambiguous, the response may be `NEEDS_CLARIFICATION` with a follow-up question instead of a scheduled call — set `force: true` to skip clarification.","operationId":"scheduleCall","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleCallDto"}}}},"responses":{"201":{"description":"Call scheduled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseCallResponseDto"}}}},"400":{"description":"Invalid input data, needs clarification, insufficient credits, or call request denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseUnsuccessfulCallResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Schedule a new call","tags":["calls"]}},"/calls/{id}":{"delete":{"description":"Transitions a call from NOT_STARTED or QUEUED to CANCELLED. The record is retained for history and analytics. Only not-yet-started calls can be cancelled here — for IN_PROGRESS calls use `POST /calls/:id/drop`, and for finished calls use `DELETE /calls/:id/full`. Reserved minutes are released back to the user's balance.","operationId":"cancelScheduledCall","parameters":[{"name":"id","required":true,"in":"path","description":"Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Cancel a scheduled call by ID","tags":["calls"]},"get":{"description":"Returns the full call record with all relations loaded: transactions (billing), agent, voicemails, dataCollections, evaluations, tasks, analysis, followUps, plus computed fields `isFavorite`, `shareHash`, and a plain-text `transcription` rendered from `roleplayTranscript`. For in-progress calls some fields (finalSummary, minutesUsed) may be partial.","operationId":"getCallDetails","parameters":[{"name":"id","required":true,"in":"path","description":"Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDto"}}}},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Get call details","tags":["calls"]}},"/calls/copy/{id}":{"post":{"description":"Duplicates an existing call for a retry with optional overrides (new `scheduledAt`, different `phoneNumber`, revised goal/context). The new call's `copyOfCallId` points to the source, forming a retry chain. `cronSchedule` is intentionally NOT copied to prevent runaway recurring retries. Runs the same validation as `/schedule`, so a copy can still be denied. Primarily used when a call failed or the customer was unavailable.","operationId":"copyCall","parameters":[{"name":"id","required":true,"in":"path","description":"Call ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopyCallDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseCallResponseDto"}}}},"400":{"description":"Invalid input data, needs clarification, insufficient credits, or call request denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BaseUnsuccessfulCallResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Copy a call","tags":["calls"]}},"/calls":{"get":{"description":"Lists outbound calls for the current user with status/date/phone filters, pagination, and aggregated stats (totals by status, minutes used). When `raw=true` the response is a plain array without stats. `transcription` is rendered on-the-fly from `roleplayTranscript` and may be empty for in-progress calls. Use `favorites=true` to filter to pinned calls only.","operationId":"getCallHistory","parameters":[{"name":"status","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["QUEUED","IN_PROGRESS","AWAITING_CONNECTION","SUCCESS","FAILED","NOT_STARTED","CANCELLED","CALL_TRANSFERRED"]}}},{"name":"startDate","required":false,"in":"query","description":"Start date for filtering calls (ISO 8601)","schema":{"type":"string"}},{"name":"endDate","required":false,"in":"query","description":"End date for filtering calls (ISO 8601)","schema":{"type":"string"}},{"name":"phoneNumber","required":false,"in":"query","description":"Filter by phone number","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of records to return","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Number of records to skip","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"raw","required":false,"in":"query","description":"In Raw mode","schema":{"default":"false","type":"string"}},{"name":"favorites","required":false,"in":"query","description":"Filter only favorite calls","schema":{"default":false,"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallHistoryResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Get call history","tags":["calls"]}},"/calls/search":{"get":{"description":"Full-text search across BOTH outbound and incoming calls in one query. Matches against transcripts, finalSummary, title, phoneNumber/phoneNumberFrom, goal, and callerName (case-insensitive). Results carry a `callType: 'outgoing' | 'incoming'` discriminator plus `matchedFields` showing which columns hit. For outbound-only results use `/calls/search/outgoing`; for incoming-only use `/incoming-calls/search`. Soft-deleted calls are excluded.","operationId":"searchCalls","parameters":[{"name":"query","required":true,"in":"query","description":"Search query string","schema":{"minLength":1,"example":"appointment","type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of records to return","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Number of records to skip","schema":{"minimum":0,"default":0,"type":"number"}}],"responses":{"200":{"description":"Search results including both outgoing and incoming calls","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchCallsResponseDto"}}}},"400":{"description":"Invalid search query"}},"security":[{"bearer":[]}],"summary":"Search calls","tags":["calls"]}},"/calls/search/outgoing":{"get":{"description":"Same search semantics as `/calls/search` but scoped to outbound calls — faster because it skips the incoming-calls merge step. Matches transcripts, summaries, titles, goals, and phone numbers case-insensitively, returning `matchedFields` for each result. Use this when you know you only care about outbound history (e.g., a campaign follow-up list).","operationId":"searchOutgoingCalls","parameters":[{"name":"query","required":true,"in":"query","description":"Search query string","schema":{"minLength":1,"example":"appointment","type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of records to return","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Number of records to skip","schema":{"minimum":0,"default":0,"type":"number"}}],"responses":{"200":{"description":"Search results for outgoing calls only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallHistoryResponseDto"}}}},"400":{"description":"Invalid search query"}},"security":[{"bearer":[]}],"summary":"Search outgoing calls only","tags":["calls"]}},"/calls/{id}/rate":{"post":{"description":"Records a thumbs-up/thumbs-down rating plus optional comment on a completed call. Set `isIncomingCall=true` to rate an inbound call instead of outbound. A call can only be rated once — a second call returns 400. Ratings are generally only meaningful for SUCCESS/FAILED calls; rating an in-progress call is allowed but discouraged.","operationId":"rateCall","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateCallDto"}}}},"responses":{"200":{"description":"Call rated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}},"400":{"description":"Call already rated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Rate a call","tags":["calls"]}},"/calls/{id}/drop":{"post":{"description":"Best-effort termination of an IN_PROGRESS or AWAITING_CONNECTION call. The endpoint returns success even if the call is already ending. Minutes consumed up to the drop are billed, and the call is finalized with status FAILED and reason DROPPED_BY_USER. No-op if the call is already finished.","operationId":"dropCall","parameters":[{"name":"id","required":true,"in":"path","description":"Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Drop a call immediately by ID","tags":["calls"]}},"/calls/{id}/favorite":{"post":{"description":"Pins an outbound call for quick access via the `favorites=true` filter on history/search. A second call returns 400 — check `isFavorite` first or catch the error. Favoriting does not affect call behavior, retention, or billing; it is purely a UI concern.","operationId":"addToFavorites","parameters":[{"name":"id","required":true,"in":"path","description":"Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}},"400":{"description":"Call already in favorites"},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Add call to favorites","tags":["calls"]},"delete":{"description":"Unpins an outbound call. Returns 400 if the call was not previously favorited — check `isFavorite` first if you want idempotent behavior. Does not modify the call record itself.","operationId":"removeFromFavorites","parameters":[{"name":"id","required":true,"in":"path","description":"Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}},"400":{"description":"Call not in favorites"}},"security":[{"bearer":[]}],"summary":"Remove call from favorites","tags":["calls"]}},"/calls/{id}/notes":{"patch":{"description":"Attaches or replaces free-form plain-text notes on a call — pass `isIncomingCall=true` to target an inbound call instead. Typically used to record follow-up actions, context the agent missed, or personal observations after reviewing the transcript. Can be called on both in-progress and completed calls; there is no formatting support (plain text only).","operationId":"updateCallNotes","parameters":[{"name":"id","required":true,"in":"path","description":"Call ID (outbound or inbound)","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCallNotesDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Update call notes","tags":["calls"]}},"/incoming-calls":{"get":{"description":"Lists inbound calls received on the user's agent numbers with status/date/phone filters and pagination. Unlike outbound calls, inbound calls only appear here once their status is FINISHED or PROCESSED (they go IN_PROGRESS → FINISHED → PROCESSED). Soft-deleted/hidden calls are excluded. Use `hideTrashCalls=true` to exclude spam and calls that ended immediately after the greeting before pagination and totals are calculated. Use `favorites=true` for pinned calls only, `raw=true` to skip the stats block. Each call still consumes minutes from the user's subscription balance.","operationId":"getCallHistory","parameters":[{"name":"status","required":false,"in":"query","schema":{"type":"array","items":{"type":"string","enum":["FINISHED","PROCESSED","FAILED","IN_PROGRESS"]}}},{"name":"startDate","required":false,"in":"query","description":"Start date for filtering calls (ISO 8601)","schema":{"type":"string"}},{"name":"endDate","required":false,"in":"query","description":"End date for filtering calls (ISO 8601)","schema":{"type":"string"}},{"name":"phoneNumber","required":false,"in":"query","description":"Filter by phone number","schema":{"type":"string"}},{"name":"agentId","required":false,"in":"query","description":"Filter by receptionist ID","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of records to return","schema":{"minimum":1,"default":10,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Number of records to skip","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"raw","required":false,"in":"query","description":"In Raw mode","schema":{"default":"false","type":"string"}},{"name":"favorites","required":false,"in":"query","description":"Filter only favorite calls","schema":{"default":false,"type":"boolean"}},{"name":"hideTrashCalls","required":false,"in":"query","description":"Hide spam and calls that ended immediately after the greeting","schema":{"default":false,"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncomingCallHistoryResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Get incoming call history","tags":["incoming-calls"]}},"/incoming-calls/search":{"get":{"description":"Full-text search scoped to inbound calls — matches caller name, phone number, transcript, summary, and title case-insensitively. Faster than `/calls/search` which also scans outbound calls. Returns `matchedFields` per result showing which columns hit the query. Soft-deleted calls are excluded.","operationId":"searchIncomingCalls","parameters":[{"name":"query","required":true,"in":"query","description":"Search query string","schema":{"minLength":1,"example":"appointment","type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of records to return","schema":{"minimum":1,"maximum":100,"default":20,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Number of records to skip","schema":{"minimum":0,"default":0,"type":"number"}},{"name":"agentId","required":false,"in":"query","description":"Filter by receptionist ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Search results for incoming calls only","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncomingCallHistoryResponseDto"}}}},"400":{"description":"Invalid search query"}},"security":[{"bearer":[]}],"summary":"Search incoming calls only","tags":["incoming-calls"]}},"/incoming-calls/{id}":{"get":{"description":"Returns the full inbound call record with all relations: transcript, finalSummary, agent config used, `dataCollections` (structured data extracted by the AI), `followUps` and `tasks` created during the call (both filtered to non-deleted and sorted newest first). If the call is still IN_PROGRESS some fields may be partial.","operationId":"getCallDetails","parameters":[{"name":"id","required":true,"in":"path","description":"Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncomingCallDto"}}}},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Get incoming call details","tags":["incoming-calls"]},"delete":{"description":"Soft-deletes an inbound call by setting `deletedAt`, hiding it from history and search. The record stays in the DB for analytics and audit; there is no restore endpoint. Does not affect transactions/billing or delete any booked appointments created during the call.","operationId":"deleteCall","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Delete an incoming call","tags":["incoming-calls"]}},"/incoming-calls/{id}/block":{"post":{"description":"Adds the call's `phoneNumberFrom` to the user's blocklist so future calls from that number are rejected by ALL the user's agents globally. Typical use: spam, harassment, or competitors. Blocks the exact number only (not the caller name/account). Use `POST /incoming-calls/:id/unblock` with the same call ID to reverse.","operationId":"blockCaller","parameters":[{"name":"id","required":true,"in":"path","description":"Incoming Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Phone number blocked successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlockCallerResponseDto"}}}},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Block the caller phone number from this incoming call","tags":["incoming-calls"]}},"/incoming-calls/{id}/unblock":{"post":{"description":"Removes `phoneNumberFrom` of the referenced call from the user's blocklist — effective immediately, the next call from that number will ring through to the agent again. Pass the incoming call ID that was originally used to block, not the phone number directly.","operationId":"unblockCaller","parameters":[{"name":"id","required":true,"in":"path","description":"Incoming Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Phone number unblocked successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlockCallerResponseDto"}}}},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Unblock the caller phone number from this incoming call","tags":["incoming-calls"]}},"/incoming-calls/{id}/drop":{"post":{"description":"Terminates an IN_PROGRESS inbound call. Best-effort: returns success even if termination fails (the call may already be ending). Minutes consumed up to the drop are billed.","operationId":"dropIncomingCall","parameters":[{"name":"id","required":true,"in":"path","description":"Incoming Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}},"404":{"description":"Incoming call not found"}},"security":[{"bearer":[]}],"summary":"Drop an incoming call immediately by ID","tags":["incoming-calls"]}},"/incoming-calls/{id}/favorite":{"post":{"description":"Pins an inbound call for quick access via the `favorites=true` filter on history/search. A second call returns 400 — check `isFavorite` first or catch the error. Purely a UI concern — does not change call behavior or retention.","operationId":"addToFavorites","parameters":[{"name":"id","required":true,"in":"path","description":"Incoming Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}},"400":{"description":"Call already in favorites"},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Add incoming call to favorites","tags":["incoming-calls"]},"delete":{"description":"Unpins an inbound call. Returns 400 if the call was not previously favorited — check `isFavorite` first if you want idempotent behavior. Does not modify the call record itself.","operationId":"removeFromFavorites","parameters":[{"name":"id","required":true,"in":"path","description":"Incoming Call ID","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallSimpleResponseDto"}}}},"400":{"description":"Call not in favorites"},"404":{"description":"Call not found"}},"security":[{"bearer":[]}],"summary":"Remove incoming call from favorites","tags":["incoming-calls"]}},"/agents":{"post":{"description":"Creates a voice AI agent with the provided configuration. The agent won't receive calls until a phone number is assigned, but it can be tested immediately. Instructions are validated by an LLM and rejected if vague or off-topic. Subscription agent-count limits are enforced. Mobile users auto-get isVoiceMailAgent=true; avatar is auto-generated from name.","operationId":"create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentDto"}}}},"responses":{"201":{"description":"The agent has been successfully created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentDto"}}}},"400":{"description":"Invalid agent instructions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentValidationDto"}}}}},"security":[{"bearer":[]}],"summary":"Create a new agent","tags":["agents"]},"get":{"description":"Returns all non-deleted agents you own, ordered by newest first, with nested phone numbers (test numbers excluded), tools, evaluations, and data collections plus their results. Use for the dashboard agent list, external sync, or audits. Soft-deleted agents are filtered out.","operationId":"findAll","parameters":[],"responses":{"200":{"description":"Returns an array of agents.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgentDto"}}}}}},"security":[{"bearer":[]}],"summary":"Get all not deleted agents for the current user","tags":["agents"]}},"/agents/public":{"get":{"description":"Returns curated public template agents visible to all users — useful as starting points, examples, or for a template gallery. Response excludes userId and sensitive config fields. No authentication data is required beyond standard JWT.","operationId":"findPublic","parameters":[],"responses":{"200":{"description":"Returns an array of public agents.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgentDto"}}}}}},"security":[{"bearer":[]}],"summary":"Get all public agents","tags":["agents"]}},"/agents/{id}":{"get":{"description":"Retrieves the full agent configuration including instructions, voice, evaluations, data collections, linked calendars, transfer numbers, and tasks. Use for edit form pre-population, detail views, or config audits. Returns 404 if the agent doesn't belong to the authenticated user or was soft-deleted.","operationId":"findOne","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Returns the agent if found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentDto"}}}},"404":{"description":"Agent not found."}},"security":[{"bearer":[]}],"summary":"Get a specific agent by ID","tags":["agents"]},"patch":{"description":"Partial update — only fields sent in the body are changed. If instructions change they're re-validated and rejected if invalid. If toolIds is sent, ALL existing tool links are replaced. SMS-capable setting changes reconcile Messaging Service registration for assigned US Twilio numbers.","operationId":"update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAgentDto"}}}},"responses":{"200":{"description":"The agent has been successfully updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentDto"}}}},"400":{"description":"Invalid agent instructions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentValidationDto"}}}},"404":{"description":"Agent not found."}},"security":[{"bearer":[]}],"summary":"Update an agent","tags":["agents"]},"delete":{"description":"Deletes the agent and its evaluations, data collections, and transfer numbers. Phone numbers become unassigned and can be reused.","operationId":"remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The agent has been successfully deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentDto"}}}},"404":{"description":"Agent not found."}},"security":[{"bearer":[]}],"summary":"Delete an agent","tags":["agents"]}},"/agents/{id}/toggle":{"patch":{"description":"Flips the agent's isActive flag to quickly pause or resume it without losing configuration. Inactive agents don't receive calls. Use for off-hours pause, maintenance windows, or a single-click enable/disable control in the UI.","operationId":"toggle","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The agent has been successfully toggled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentDto"}}}}},"security":[{"bearer":[]}],"summary":"Toggle an agent active status","tags":["agents"]}},"/agents/{id}/reset-to-defaults":{"post":{"description":"Resets the agent's editable dashboard configuration to the default new-receptionist settings while preserving the agent record and linked resources. The reset is recorded in agent audit history.","operationId":"resetToDefaults","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"The agent has been reset to defaults.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentDto"}}}},"404":{"description":"Agent not found."}},"security":[{"bearer":[]}],"summary":"Reset an agent to dashboard defaults","tags":["agents"]}},"/agents/{id}/audit-history":{"get":{"description":"Returns paginated audit log of every config change on this agent (instructions, voice, settings, etc.) with old/new values and source attribution. Use for compliance reports, debugging unexpected changes, or rollback planning. Defaults: limit=50, offset=0.","operationId":"getAuditHistory","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Max entries to return","schema":{"default":50,"type":"number"}},{"name":"offset","required":false,"in":"query","description":"Offset for pagination","schema":{"default":0,"type":"number"}}],"responses":{"200":{"description":"Returns paginated audit log entries for the agent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentAuditHistoryResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Get agent change history","tags":["agents"]}},"/agents/{id}/evaluations":{"post":{"description":"Defines a new call-quality criterion (yes/no question like \"Did the agent mention pricing?\"). After every call, the LLM evaluates the transcript and returns SUCCESS/FAILURE/UNKNOWN with a rationale. Use to track agent performance metrics and build quality dashboards.","operationId":"createEvaluation","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentEvaluationDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Create agent evaluation","tags":["agents"]},"get":{"description":"Returns all evaluation criteria defined for this agent with their execution results (SUCCESS/FAILURE/UNKNOWN + rationale per call). Use for quality dashboards, trend analysis, or listing tracked metrics. Soft-deleted evaluations are filtered out.","operationId":"getEvaluations","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get agent evaluations","tags":["agents"]}},"/agents/evaluations/{id}":{"patch":{"description":"Modifies the name or prompt of an evaluation criterion. Past results are preserved — only future evaluations use the new prompt. Use to refine criteria or clarify what you're measuring. Ownership verified via the nested agent.userId.","operationId":"updateEvaluation","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAgentEvaluationDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Update agent evaluation","tags":["agents"]},"delete":{"description":"Soft-deletes the evaluation (sets deletedAt). Past results stay archived and queryable; no new evaluations run on future calls. Use when retiring outdated metrics or simplifying dashboards.","operationId":"deleteEvaluation","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Delete agent evaluation","tags":["agents"]}},"/agents/{id}/data-collections":{"post":{"description":"Defines a structured field (customer_name, budget, appointment_time, etc.) auto-extracted from every call transcript. Specify dataType (STRING/NUMBER/INTEGER/BOOLEAN/DATE) to enforce the expected type on the extracted value. Use for CRM sync, analytics, or integrations.","operationId":"createDataCollection","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentDataCollectionDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Create agent data collection","tags":["agents"]},"get":{"description":"Returns all extraction fields configured for this agent plus the values extracted from recent calls. Use for CRM sync settings, reviewing captured data, or auditing extraction setup. Soft-deleted fields are filtered out.","operationId":"getDataCollections","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get agent data collections","tags":["agents"]}},"/agents/data-collections/{id}":{"patch":{"description":"Modifies the description or dataType of an extraction field. Past results remain untouched; future calls use the new config. Use to clarify extraction instructions or change the expected data type.","operationId":"updateDataCollection","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAgentDataCollectionDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Update agent data collection","tags":["agents"]},"delete":{"description":"Soft-deletes the extraction field. Past extracted values are preserved and queryable; no new extractions run on future calls. Use to remove unused fields or consolidate data capture.","operationId":"deleteDataCollection","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Delete agent data collection","tags":["agents"]}},"/agents/{id}/calendars":{"post":{"description":"Links a calendar (Google/Outlook/Apple) to the agent so it can check availability and auto-book appointments during calls. Specify work hours per day (HHMM format), timezone, default duration, buffer minutes. The calendar must already belong to the user.","operationId":"connectCalendar","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentCalendarDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Connect calendar to agent","tags":["agents"]},"get":{"description":"Returns all calendars linked to this agent with their booking config (work hours, timezone, duration, buffer, active flag). Use to view integrations, verify booking setup, or audit access.","operationId":"getConnectedCalendars","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get agent connected calendars","tags":["agents"]}},"/agents/{id}/calendars/{agentCalendarId}/duplicate":{"post":{"description":"Creates a second AgentCalendar row pointing at the same underlying calendar but with independent duration/description. Use this to expose multiple \"virtual\" variants of one Google/Outlook/Apple calendar to the AI — e.g., \"New patient — 40 min\" and \"Follow-up — 10 min\" on the same physical calendar. The AI sees them as distinct options and picks one per appointment type. Only allowed for self-managed providers (GOOGLE, OUTLOOK, APPLE); external booking engines (Calendly, Cal.com, Square, GHL) dictate duration from their own system, so cloning is rejected. :agentCalendarId is the AgentCalendar primary key (not the underlying calendar's ID).","operationId":"duplicateCalendar","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"agentCalendarId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateAgentCalendarDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Duplicate an agent-calendar link (virtual calendar)","tags":["agents"]}},"/agents/{id}/calendars/{calendarId}":{"patch":{"description":"Partial update of a calendar link — work hours, timezone, default duration, buffer minutes, active flag, double-booking permission. Use for seasonal schedule changes, timezone updates after relocation, or enabling/disabling booking temporarily.","operationId":"updateCalendarSettings","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"calendarId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAgentCalendarDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Update calendar settings","tags":["agents"]},"delete":{"description":"Removes the link between the agent and the calendar. Agent stops checking availability or booking events on this calendar. The underlying calendar itself is preserved. Use when replacing calendars or removing booking capability.","operationId":"disconnectCalendar","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"calendarId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Disconnect calendar from agent","tags":["agents"]}},"/agents/{id}/embed":{"post":{"description":"Creates or updates the widget config for embedding this agent on a website as a voice button. Requires at least one allowed domain (exact \"example.com\" or wildcard \"*.example.com\"). Embed key is generated on first create and preserved on updates. Customize position, autoConnect, primaryColor, callButtonText.","operationId":"createOrUpdateEmbed","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWidgetConfigDto"}}}},"responses":{"200":{"description":"Widget configuration created/updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WidgetConfigResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Create or update widget embed configuration","tags":["agents"]},"get":{"description":"Returns the widget's embedKey (pk_embed_*), isEnabled flag, allowed domains, styling options, and usage stats (totalConnections, lastUsedAt). Use to display the embed code snippet in settings or verify current config.","operationId":"getEmbed","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Returns widget configuration"}},"security":[{"bearer":[]}],"summary":"Get widget embed configuration","tags":["agents"]},"delete":{"description":"Sets isEnabled=false on the widget config — the embed stops working on all websites immediately, but config (domains, styling, embed key) is preserved for quick re-enable. Use for maintenance, temporarily pausing, or removing from production.","operationId":"disableEmbed","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Disable widget embed","tags":["agents"]}},"/agents/{id}/embed/regenerate-key":{"post":{"description":"Invalidates the current embed key and generates a new pk_embed_* value. The old key stops working immediately — any deployed <script> tags need to be updated. Use after a suspected key leak or as part of scheduled security rotation.","operationId":"regenerateEmbedKey","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Regenerate embed key","tags":["agents"]}},"/agents/{id}/transfer-numbers":{"get":{"description":"Returns all configured transfer numbers (active + inactive) ordered by sortOrder. Max 20 per agent is a hard limit. Each entry includes label, description, phone, work hours, active flag, sort order. Use to render the routing list, validate setup, or audit rules.","operationId":"getTransferNumbers","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Returns array of transfer numbers (max 20)"}},"security":[{"bearer":[]}],"summary":"Get all transfer numbers for an agent","tags":["agents"]},"post":{"description":"Creates a routing option the agent can forward calls to. Label must be lowercase letters only and unique per agent. Phone in E.164 format, restricted to supported countries. Work hours use HHMM format per weekday; omit for 24/7. Hard limit of 20 transfer numbers per agent.","operationId":"createTransferNumber","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTransferNumberDto"}}}},"responses":{"201":{"description":"Transfer number created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferNumberResponseDto"}}}},"400":{"description":"Maximum 20 transfer numbers allowed or invalid data"},"409":{"description":"Label already exists for this agent"}},"security":[{"bearer":[]}],"summary":"Add a new transfer number to an agent","tags":["agents"]}},"/agents/{id}/transfer-numbers/{transferId}":{"patch":{"description":"Partial update — label, description, phone, work hours, or active flag. Label uniqueness is re-checked if changed. Phone is re-validated (E.164 + supported countries). Use when restructuring teams, updating numbers, or adjusting seasonal hours.","operationId":"updateTransferNumber","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"transferId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTransferNumberDto"}}}},"responses":{"200":{"description":"Transfer number updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferNumberResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Update a transfer number","tags":["agents"]},"delete":{"description":"Hard-deletes the transfer number (no soft deletion for this table). The agent immediately stops offering this routing path. Use to remove defunct departments or consolidate routing rules.","operationId":"deleteTransferNumber","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"transferId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Transfer number deleted successfully"}},"security":[{"bearer":[]}],"summary":"Delete a transfer number","tags":["agents"]}},"/agents/tasks/available":{"get":{"description":"Returns built-in global tasks (userId=null) plus any custom tasks you've created. Tasks are structured objectives agents can execute on calls (schedule callback, collect email, etc.) and may have prerequisites like calendar_connected that gate visibility.","operationId":"getAvailableTasks","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TaskDefinitionDto"}}}}}},"security":[{"bearer":[]}],"summary":"List all tasks available to user (global + custom)","tags":["agents"]}},"/agents/tasks/custom":{"post":{"description":"Defines a user-scoped task (only visible to you) with title, description, and completion criteria. Custom tasks can then be enabled on any of your agents. Use when the global task library doesn't cover a niche objective specific to your business.","operationId":"createCustomTask","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomTaskDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskDefinitionDto"}}}}},"security":[{"bearer":[]}],"summary":"Create a custom task definition","tags":["agents"]}},"/agents/tasks/custom/{taskId}":{"delete":{"description":"Deletes a custom task you own. Global tasks (userId=null) cannot be deleted via this endpoint. Agents with this task enabled will no longer offer it on new calls. Use to clean up outdated or unused custom tasks.","operationId":"deleteCustomTask","parameters":[{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskDefinitionDto"}}}}},"security":[{"bearer":[]}],"summary":"Delete a custom task definition","tags":["agents"]}},"/agents/{id}/scenarios":{"get":{"description":"Returns non-deleted call scenarios for this agent, ordered by priority ASC. Full scenario Markdown is included for editing.","operationId":"listScenarios","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgentScenarioResponseDto"}}}}}},"security":[{"bearer":[]}],"summary":"List call scenarios for an agent","tags":["agents"]},"post":{"description":"Creates a scenario-specific Markdown guide. The lookup key is generated server-side from the title and is not user-editable.","operationId":"createScenario","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgentScenarioDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentScenarioResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Create a call scenario for an agent","tags":["agents"]}},"/agents/{id}/scenarios/reorder":{"patch":{"description":"Updates priority on all non-deleted scenarios to match the provided scenarioIds array. Must include every non-deleted scenario ID.","operationId":"reorderScenarios","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderAgentScenariosDto"}}}},"responses":{"200":{"description":"Scenarios reordered successfully"}},"security":[{"bearer":[]}],"summary":"Reorder call scenarios for an agent","tags":["agents"]}},"/agents/{id}/scenarios/{scenarioId}":{"patch":{"description":"Updates title, use-when selector, Markdown guide, or enabled state. The generated key is stable and is not regenerated.","operationId":"updateScenario","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"scenarioId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAgentScenarioDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentScenarioResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Update a call scenario","tags":["agents"]},"delete":{"description":"Soft-deletes a scenario so it is no longer listed or available in future calls.","operationId":"deleteScenario","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"scenarioId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Scenario deleted successfully"}},"security":[{"bearer":[]}],"summary":"Delete a call scenario","tags":["agents"]}},"/agents/{id}/tasks":{"get":{"description":"Returns all task links currently enabled on the agent, ordered by priority ASC (lower number = higher priority). Each result contains the priority and the nested task definition. Use for agent capability dashboards or task-management UIs.","operationId":"getAgentTasks","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgentTaskLinkDto"}}}}}},"security":[{"bearer":[]}],"summary":"List enabled tasks for an agent","tags":["agents"]}},"/agents/{id}/tasks/{taskId}/enable":{"post":{"description":"Enables a task for the agent — creates the link if absent, updates priority if already enabled. The agent will offer this task during calls provided its prerequisites are met (e.g., `calendar_connected` requires a linked calendar). Priority defaults to 0.","operationId":"enableTask","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableTaskDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentTaskLinkDto"}}}}},"security":[{"bearer":[]}],"summary":"Enable a task on an agent","tags":["agents"]}},"/agents/{id}/tasks/{taskId}":{"delete":{"description":"Disables the task on this agent. Agent stops offering this capability on new calls. Returns 404 if the task wasn't enabled on this agent. Use to restrict capabilities or retire outdated tasks per agent.","operationId":"disableTask","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}},{"name":"taskId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Task disabled successfully"}},"security":[{"bearer":[]}],"summary":"Disable a task on an agent","tags":["agents"]}},"/agents/{id}/stt-keyterms/suggest":{"post":{"description":"Returns a simple list of new recognition words found in up to 30 recent meaningful inbound and outbound calls, the Business Profile, and agent instructions. This endpoint does not update the agent.","operationId":"suggest","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"New recognition words","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"},"example":["Acme Dental","Invisalign","Sausalito"]}}}}},"security":[{"bearer":[]}],"summary":"Suggest speech recognition words from recent agent context","tags":["agents"]}},"/agents/{agentId}/email-receptionist":{"get":{"operationId":"getSettings","parameters":[{"name":"agentId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Email receptionist settings for the agent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailReceptionistSettingsResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Get email receptionist settings for an agent","tags":["email-receptionist"]},"put":{"operationId":"updateSettings","parameters":[{"name":"agentId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailReceptionistSettingsDto"}}}},"responses":{"200":{"description":"Updated email receptionist settings for the agent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailReceptionistSettingsResponseDto"}}}}},"security":[{"bearer":[]}],"summary":"Create or update email receptionist settings for an agent","tags":["email-receptionist"]}},"/users/me/contacts/{id}/schedule-call":{"post":{"description":"Queues an outbound call targeted at this contact. Wraps `POST /calls/schedule` and auto-fills `phoneNumber` from the contact record, plus injects contact context (name, tags, last interaction) so the agent knows who it's calling. The resulting Call is linked to the contact — shows up in their timeline, counts toward lifecycle stats. Agent must be `isActive` and owned by the caller; contact must have a valid E.164 phone.","operationId":"scheduleCallFromContact","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleCallFromContactDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Schedule an outbound call to a contact","tags":["contact-actions"]}},"/users/me/contacts/{id}/send-sms":{"post":{"description":"Sends an SMS from the user's SkipCalls-owned phone number to this contact. Body can be a literal `text` or an AI-drafted message (`mode: 'ai'` with a prompt). The outbound SMS is persisted and added to the contact's timeline automatically. Requires the user to own at least one active SMS-capable phone number; contact must have a valid phone.","operationId":"sendSmsToContact","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendSmsFromContactDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Send an SMS to a contact","tags":["contact-actions"]}}},"info":{"title":"SkipCalls Public API","description":"Core endpoints for dashboards and integrations. Agents, calls, contacts, meetings, basic profile. All endpoints authenticated via Bearer JWT unless noted.","version":"1.0","contact":{}},"tags":[{"name":"agents","description":"Agent configuration — create, update, transfer numbers, calendars, evaluations, data collection"},{"name":"calls","description":"Outbound calls — schedule, list, inspect, cancel"},{"name":"incoming-calls","description":"Inbound calls — list and inspect"},{"name":"users","description":"Basic profile — /users/me + contacts"},{"name":"calendars","description":"Booked appointments"}],"servers":[],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"UserProfileSubscriptionDto":{"type":"object","properties":{"status":{"type":"string","enum":["ACTIVE","INACTIVE","TRIALING","CANCELED","PAST_DUE","UNPAID"],"description":"Status of the subscription"},"paymentProvider":{"type":"string","enum":["STRIPE","REVENUECAT","MANUAL"],"description":"Payment provider"},"createdAt":{"format":"date-time","type":"string","description":"Subscription creation date"},"expiresAt":{"format":"date-time","type":"string","description":"Expiration date of the subscription"},"currentPeriodStart":{"format":"date-time","type":"string","description":"Start date of the current period"},"currentPeriodEnd":{"format":"date-time","type":"string","description":"End date of the current period"},"planName":{"type":"string","description":"Name of the plan"},"planId":{"type":"string","description":"ID of the plan"},"planType":{"type":"string","enum":["ENTERPRISE","B2C"]},"planPrice":{"type":"number","description":"Price of the plan"},"planMinutes":{"type":"number","description":"Total minutes for the current period"},"planPeriod":{"type":"string","description":"Period of subscriotion","enum":["WEEKLY","MONTHLY","YEARLY"]},"planFeatures":{"description":"Presentation metadata from the subscription plan; runtime authorization uses PlanAccessService","example":["priority_support"],"type":"array","items":{"type":"string"}},"remainingMinutes":{"type":"number","description":"Remaining minutes for the current period"},"cancelAtPeriodEnd":{"type":"boolean","description":"Cancel at period end"}},"required":["status","expiresAt","currentPeriodStart","currentPeriodEnd","planName","planId","planType","planPrice","planMinutes","planPeriod","planFeatures","remainingMinutes","cancelAtPeriodEnd"]},"UserProfileResponseDto":{"type":"object","properties":{"createdAt":{"format":"date-time","type":"string","description":"Date and time the user was created","example":"2021-01-01T00:00:00.000Z"},"referralCode":{"type":"string","description":"Referral code of the user","example":"1234567890"},"firstName":{"type":"string","description":"First name of the user","example":"John"},"lastName":{"type":"string","description":"Last name of the user","example":"Doe"},"phoneNumber":{"type":"string","description":"Phone number of the user","example":"+1234567890"},"phoneCarrier":{"type":"string","description":"Phone carrier name","example":"Verizon"},"isBlocked":{"type":"boolean","description":"Whether the user is blocked","example":false},"kycRequired":{"type":"boolean","description":"Whether KYC verification is required for this user","example":false},"balanceMinutes":{"type":"number","description":"Balance minutes of the user","example":100},"cityName":{"type":"string","description":"City name of the user","example":"New York"},"countryName":{"type":"string","description":"Country name of the user","example":"United States"},"zipCode":{"type":"string","description":"Zip code of the user","example":"10001"},"address":{"type":"string","description":"Address of the user","example":"123 Main St"},"stateName":{"type":"string","description":"State name of the user","example":"New York"},"timezone":{"type":"string","description":"Timezone of the user","example":"America/New_York"},"companyName":{"type":"string","description":"Company name of the user","example":"Acme Inc"},"companyWebsite":{"type":"string","description":"Company website of the user","example":"https://www.acmeinc.com"},"companyDescription":{"type":"string","description":"Company description of the user","example":"We are a company that makes widgets"},"companyIndustry":{"type":"string","description":"Company industry of the user","example":"Technology"},"companySize":{"type":"string","description":"Company size of the user","example":"100"},"dob":{"type":"string","description":"Date of birth of the user","example":"1990-01-01"},"disableEmails":{"type":"boolean","description":"Whether the user has disabled emails","example":false,"default":false},"sendEmailSummary":{"type":"boolean","default":false},"notifyCallActivity":{"type":"boolean","default":true,"description":"Whether to notify about routine call activity"},"notifyNewMessages":{"type":"boolean","default":true,"description":"Whether to notify about new messages"},"sendWeeklySummary":{"type":"boolean","default":false},"sendSmsNotifications":{"type":"boolean","default":true,"description":"Whether to receive email notifications for SMS events"},"enableSmartRetry":{"type":"boolean","default":false,"description":"Whether to enable smart retry for failed calls"},"autoCreateContacts":{"type":"boolean","default":true,"description":"Auto-create contacts from incoming calls and SMS"},"isVoicemailTested":{"type":"boolean","default":false,"description":"Whether the user has tested voicemail"},"sendDailyRecap":{"type":"boolean","default":false,"description":"Whether to send daily recap push notifications"},"notifySpamCalls":{"type":"boolean","default":false,"description":"Whether to notify when spam calls are detected or blocked"},"notifyAbandonedCalls":{"type":"boolean","default":false,"description":"Whether to notify when callers abandon a call"},"sendSmsOnImportantCalls":{"type":"boolean","default":false,"description":"Whether high-confidence important incoming calls are texted to the confirmed account owner"},"dailyRecapTime":{"type":"string","default":"18:00","description":"Time for daily recap (HH:mm format)"},"dailyRecapDelivery":{"type":"string","enum":["PUSH","EMAIL","BOTH"],"default":"PUSH","description":"Daily recap delivery method"},"overrideEmail":{"type":"string","description":"Override email address list for notifications. Comma or semicolon separated; uses auth email if not set.","example":"notifications@example.com,ops@example.com"},"preferredName":{"type":"string","description":"Preferred name for AI agent (e.g., \"Dr. Smith\"). Overrides firstName.","example":"Dr. Smith"}},"required":["createdAt","referralCode","firstName","lastName","phoneNumber","isBlocked","kycRequired","balanceMinutes","cityName","countryName","zipCode","address","stateName","timezone","companyName","companyWebsite","companyDescription","companyIndustry","companySize","dob","disableEmails"]},"UserTrialResponseDto":{"type":"object","properties":{"minutesRemaining":{"type":"number"},"totalMinutes":{"type":"number"},"hasReceived":{"type":"boolean"},"minutesUsed":{"type":"number"}},"required":["minutesRemaining","totalMinutes","hasReceived","minutesUsed"]},"UserStatsResponseDto":{"type":"object","properties":{"totalCalls":{"type":"number","description":"Total number of calls made by the user","example":25},"successfulCalls":{"type":"number","description":"Number of successful calls","example":20},"totalMinutesUsed":{"type":"number","description":"Total minutes deducted from balance for calls","example":120},"totalMinutesSpent":{"type":"number","description":"Total minutes spent on all calls (incoming + outgoing)","example":150},"successRate":{"type":"number","description":"Success rate of calls as a percentage","example":80},"contactsCount":{"type":"number","description":"Number of contacts synced","example":150}},"required":["totalCalls","successfulCalls","totalMinutesUsed","totalMinutesSpent","successRate","contactsCount"]},"UserPhoneResponseDto":{"type":"object","properties":{"phone":{"type":"string"},"phoneChange":{"type":"string"},"changeToken":{"type":"string"},"confirmedAt":{"format":"date-time","type":"string"}}},"GetUserProfileResponseDto":{"type":"object","properties":{"id":{"type":"string","description":"ID of the user"},"email":{"type":"string","description":"Email of the user"},"hasPassword":{"type":"boolean","description":"Whether the user has an email/password sign-in password set","example":true},"totalMinutes":{"type":"number","description":"Total combined minutes aka balance for the user"},"subscription":{"$ref":"#/components/schemas/UserProfileSubscriptionDto"},"profile":{"description":"Profile of the user","allOf":[{"$ref":"#/components/schemas/UserProfileResponseDto"}]},"isSubscribeExpiredOrCancelled":{"type":"boolean","description":"Whether the user is subscribed","example":false},"trial":{"description":"Trial of the user","allOf":[{"$ref":"#/components/schemas/UserTrialResponseDto"}]},"stats":{"description":"Stats of the user","allOf":[{"$ref":"#/components/schemas/UserStatsResponseDto"}]},"phone":{"description":"Phone of the user","allOf":[{"$ref":"#/components/schemas/UserPhoneResponseDto"}]},"intercomHashIos":{"type":"string","description":"Hash for Intercom iOS identity verification"},"intercomHashWeb":{"type":"string","description":"Hash for Intercom Web identity verification"},"intercomHashAndroid":{"type":"string","description":"Hash for Intercom Android identity verification"},"featureAccess":{"type":"object","description":"Feature access statuses map (featureType -> status)","example":{"CAMPAIGNS":"APPROVED"}}},"required":["id","email","hasPassword","totalMinutes","profile","isSubscribeExpiredOrCancelled","trial","stats"]},"ContactDto":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"phoneNumber":{"type":"string"},"email":{"type":"string"},"address":{"type":"string","nullable":true},"notes":{"type":"string"},"companyName":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"avatar":{"type":"string"},"isFavorite":{"type":"boolean"},"source":{"type":"string","enum":["MOBILE","WEB","IMPORT","AGENT"],"description":"Source of the contact"},"lifecycleStage":{"type":"string","description":"Lifecycle stage of the contact","enum":["lead","prospect","customer","churned"]},"doNotCall":{"type":"boolean","description":"Do not call this contact"},"doNotSms":{"type":"boolean","description":"Do not SMS this contact"}},"required":["phoneNumber"]},"SyncContactsDto":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactDto"}}},"required":["contacts"]},"BasicResponseDto":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"}},"required":["success"]},"DeleteContactsDto":{"type":"object","properties":{"confirmation":{"type":"string","description":"Required when deleting all contacts. Must be exactly \"delete all\". Not required when deleting one contact by id.","example":"delete all"}}},"UpdateContactDto":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"phoneNumber":{"type":"string"},"email":{"type":"string"},"address":{"type":"string","nullable":true},"notes":{"type":"string"},"companyName":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"avatar":{"type":"string"},"isFavorite":{"type":"boolean"},"source":{"type":"string","enum":["MOBILE","WEB","IMPORT","AGENT"],"description":"Source of the contact"},"lifecycleStage":{"type":"string","description":"Lifecycle stage of the contact","enum":["lead","prospect","customer","churned"]},"doNotCall":{"type":"boolean","description":"Do not call this contact"},"doNotSms":{"type":"boolean","description":"Do not SMS this contact"}}},"ContactStatsDto":{"type":"object","properties":{"totalIncomingCalls":{"type":"number"},"totalOutboundCalls":{"type":"number"},"totalSmsMessages":{"type":"number"},"lastCallDate":{"type":"string","nullable":true},"upcomingAppointments":{"type":"number"}},"required":["totalIncomingCalls","totalOutboundCalls","totalSmsMessages","upcomingAppointments"]},"ContactLatestNoteDto":{"type":"object","properties":{"content":{"type":"string"},"createdAt":{"type":"string"}},"required":["content","createdAt"]},"ContactItemResponseDto":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"phoneNumber":{"type":"string"},"email":{"type":"string"},"address":{"type":"string","nullable":true},"notes":{"type":"string"},"companyName":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"avatar":{"type":"string"},"isFavorite":{"type":"boolean"},"source":{"type":"string","enum":["MOBILE","WEB","IMPORT","AGENT"],"description":"Source of the contact"},"lifecycleStage":{"type":"string","description":"Lifecycle stage of the contact","enum":["lead","prospect","customer","churned"]},"doNotCall":{"type":"boolean","description":"Do not call this contact"},"doNotSms":{"type":"boolean","description":"Do not SMS this contact"},"id":{"type":"string"},"stats":{"$ref":"#/components/schemas/ContactStatsDto"},"latestNote":{"nullable":true,"allOf":[{"$ref":"#/components/schemas/ContactLatestNoteDto"}]},"suggestedLifecycleStage":{"type":"string","nullable":true}},"required":["phoneNumber","id"]},"MergeContactDataDto":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"phoneNumber":{"type":"string"},"email":{"type":"string"},"address":{"type":"string","nullable":true},"notes":{"type":"string"},"companyName":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"avatar":{"type":"string"},"isFavorite":{"type":"boolean"},"source":{"type":"string","enum":["MOBILE","WEB","IMPORT","AGENT"],"description":"Source of the contact"},"lifecycleStage":{"type":"string","description":"Lifecycle stage of the contact","enum":["lead","prospect","customer","churned"]},"doNotCall":{"type":"boolean","description":"Do not call this contact"},"doNotSms":{"type":"boolean","description":"Do not SMS this contact"},"id":{"type":"string","description":"Ignored — primaryId is used instead"}},"required":["phoneNumber"]},"MergeContactsDto":{"type":"object","properties":{"primaryId":{"type":"string","description":"ID of the contact to keep"},"secondaryId":{"type":"string","description":"ID of the duplicate contact to merge and delete"},"mergedData":{"description":"Merged field values to apply to the primary contact","allOf":[{"$ref":"#/components/schemas/MergeContactDataDto"}]}},"required":["primaryId","secondaryId","mergedData"]},"PaginationDto":{"type":"object","properties":{"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["total","limit","offset"]},"ContactAggregationsDto":{"type":"object","properties":{"uniqueCompanies":{"type":"number","description":"Number of unique companies across all contacts"},"companies":{"description":"List of unique company names","type":"array","items":{"type":"string"}}},"required":["uniqueCompanies","companies"]},"ContactSearchResponseDto":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactItemResponseDto"}},"pagination":{"$ref":"#/components/schemas/PaginationDto"},"aggregations":{"$ref":"#/components/schemas/ContactAggregationsDto"}},"required":["contacts"]},"ImportContactsDto":{"type":"object","properties":{"format":{"type":"string","enum":["csv","json"]},"content":{"type":"string","description":"Raw content of file in CSV or JSON format"}},"required":["format","content"]},"ImportContactsResponseDto":{"type":"object","properties":{"success":{"type":"boolean"},"imported":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}},"contacts":{"type":"array","items":{"$ref":"#/components/schemas/ContactDto"}}},"required":["success","imported","errors","contacts"]},"TagStatDto":{"type":"object","properties":{"tag":{"type":"string"},"count":{"type":"number"}},"required":["tag","count"]},"TagStatsResponseDto":{"type":"object","properties":{"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagStatDto"}}},"required":["tags"]},"AdvancedSearchDto":{"type":"object","properties":{"name":{"type":"string","description":"Search in firstName and lastName. Can include multiple words (e.g. \"John Doe\")"},"companies":{"description":"Array of company names to search","type":"array","items":{"type":"string"}},"tags":{"description":"Array of tags to search","type":"array","items":{"type":"string"}},"limit":{"type":"number","default":20},"offset":{"type":"number","default":0},"sortBy":{"type":"string","enum":["firstName","lastName","companyName","phoneNumber","createdAt","updatedAt"],"default":"createdAt"},"sortOrder":{"type":"string","enum":["asc","desc"],"default":"desc"}}},"AddCustomerNoteDto":{"type":"object","properties":{"content":{"type":"string","description":"Free-text note content","maxLength":4000},"isPublic":{"type":"boolean","default":true,"description":"Whether team members can see the note"}},"required":["content"]},"UpdateCustomerNoteDto":{"type":"object","properties":{"content":{"type":"string","description":"Updated free-text note content","maxLength":4000},"isPublic":{"type":"boolean","description":"Whether team members can see the note"}}},"AppointmentAgentDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"avatar":{"type":"string","description":"Agent avatar URL"}},"required":["id","name"]},"AppointmentCalendarDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"provider":{"type":"string","enum":["GOOGLE","CALENDLY","CALCOM","SQUARE","OUTLOOK","GHL","APPLE"]}},"required":["id","name","provider"]},"AppointmentResponseDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"startTime":{"format":"date-time","type":"string"},"endTime":{"format":"date-time","type":"string"},"durationMinutes":{"type":"number"},"guestPhone":{"type":"string"},"guestEmail":{"type":"string"},"guestName":{"type":"string"},"sourceType":{"type":"string","enum":["INBOUND_CALL","OUTBOUND_CALL","SMS","MANUAL"]},"callId":{"type":"string","description":"ID of the call that created this appointment"},"isIncoming":{"type":"boolean","description":"True if created from incoming call"},"calendarProvider":{"type":"string","enum":["GOOGLE","CALENDLY","CALCOM","SQUARE","OUTLOOK","GHL","APPLE"]},"externalEventId":{"type":"string","description":"External event ID in the calendar provider"},"externalEventUrl":{"type":"string","description":"Direct link to the event in external calendar (Google Calendar, Calendly, etc.)"},"callDetailsUrl":{"type":"string","description":"Link to the call details page in SkipCalls"},"agent":{"$ref":"#/components/schemas/AppointmentAgentDto"},"calendar":{"$ref":"#/components/schemas/AppointmentCalendarDto"},"timezone":{"type":"string"},"createdAt":{"format":"date-time","type":"string"}},"required":["id","title","startTime","endTime","durationMinutes","sourceType","isIncoming","calendarProvider","createdAt"]},"AppointmentsListResponseDto":{"type":"object","properties":{"appointments":{"type":"array","items":{"$ref":"#/components/schemas/AppointmentResponseDto"}},"total":{"type":"number"},"page":{"type":"number"},"limit":{"type":"number"},"totalPages":{"type":"number"}},"required":["appointments","total","page","limit","totalPages"]},"AppointmentStatsDto":{"type":"object","properties":{"upcoming":{"type":"number","description":"Number of upcoming appointments"},"thisWeek":{"type":"number","description":"Number of appointments this week"},"thisMonth":{"type":"number","description":"Number of appointments this month"},"total":{"type":"number","description":"Total appointments all time"}},"required":["upcoming","thisWeek","thisMonth","total"]},"NumberAgentDto":{"type":"object","properties":{"id":{"type":"string","description":"Agent ID"},"name":{"type":"string","description":"Agent name"}},"required":["id","name"]},"NumberItemDto":{"type":"object","properties":{"id":{"type":"string","description":"Phone number ID"},"createdAt":{"format":"date-time","type":"string","description":"Created at","example":"2021-01-01T00:00:00Z"},"updatedAt":{"format":"date-time","type":"string","description":"Updated at","example":"2021-01-01T00:00:00Z"},"phoneNumber":{"type":"string","description":"Phone number","example":"+1234567890"},"country":{"type":"string","description":"Two letter country code for supported countries","example":"US"},"isActive":{"type":"boolean","description":"Active status"},"agent":{"description":"Associated agent details","allOf":[{"$ref":"#/components/schemas/NumberAgentDto"}]},"agentId":{"type":"string","description":"Agent ID","example":"123"},"direction":{"type":"string","description":"Direction of the phone number","enum":["INCOMING","OUTGOING","BIDIRECTIONAL"],"example":"INCOMING"},"isSharedOutbound":{"type":"boolean","description":"Whether the number is shared for outbound calls","example":false},"provider":{"type":"string","description":"Provider that owns the phone number","enum":["TWILIO","SIGNALWIRE","VONAGE"]},"source":{"type":"string","description":"Whether this number was rented by SkipCalls or ported in","enum":["RENTED","PORTED"]},"readyToRelease":{"type":"boolean","description":"Whether the number is available for reuse/release","example":false},"markedReadyToReleaseAt":{"format":"date-time","type":"string","description":"Timestamp when the number entered the release pool","nullable":true},"markToDeleteAt":{"format":"date-time","type":"string","description":"Timestamp when provider deletion is scheduled","nullable":true},"lastBilledAt":{"format":"date-time","type":"string","description":"Last billing timestamp for this number","nullable":true},"monthlyCost":{"type":"string","description":"Monthly provider cost in USD","example":"1.15","nullable":true},"isTestNumber":{"type":"boolean","description":"Whether this is a temporary test number","example":false}},"required":["id","createdAt","updatedAt","phoneNumber","country","isActive","agentId"]},"TranscribeDto":{"type":"object","properties":{"audio":{"type":"string","description":"Audio file in base64"},"format":{"type":"string","description":"Audio format","default":"wav"}},"required":["audio","format"]},"TranscribeResponseDto":{"type":"object","properties":{"transcription":{"type":"string","description":"Transcription"}},"required":["transcription"]},"ScheduleCallDto":{"type":"object","properties":{"phoneNumber":{"type":"string","description":"Phone number to call"},"goal":{"type":"string","description":"Goal of the call"},"scheduledAt":{"type":"string","description":"ISO 8601 date-time for scheduling the call"},"timezone":{"type":"string","description":"Timezone for scheduling the call (e.g. America/Los_Angeles)","default":"America/Los_Angeles"},"additionalContext":{"type":"string","description":"Additional context for the call"},"maxDurationMinutes":{"type":"number","description":"Maximum duration of the call in minutes","minimum":1,"default":15},"doWeNeedToRetry":{"type":"boolean","description":"Do we need to retry the call","default":false},"voice":{"type":"string","description":"Voice to use for the call"},"retryAfterMinutes":{"type":"number","description":"Number of minutes to wait before retrying if call fails","minimum":1,"maximum":30,"default":5},"force":{"type":"boolean","description":"Force call creation without clarification","default":false},"askForClarification":{"type":"boolean","description":"Allow to ask for clarification (if user is online)","default":false},"includePrivateData":{"type":"boolean","description":"Include private data in the call prompt","default":false},"agentId":{"type":"string","description":"Agent ID to use for the call"},"title":{"type":"string","description":"Title of the call (for campaign)"},"firstMessage":{"type":"string","description":"First message to use for the call (for campaign)"},"cronSchedule":{"type":"string","description":"Cron expression for recurring calls (e.g., \"0 9 * * MON\" for every Monday at 9 AM)"}},"required":["phoneNumber","goal"]},"TransactionDto":{"type":"object","properties":{"minutes":{"type":"number","description":"Minutes used"},"type":{"type":"string","description":"Transaction type"},"createdAt":{"format":"date-time","type":"string","description":"Transaction created at"},"description":{"type":"string","description":"Transaction description"}},"required":["minutes","type","createdAt"]},"RoleplayTranscriptMetadataDto":{"type":"object","properties":{"tone":{"type":"string","description":"Tone"},"emotion":{"type":"string","description":"Emotion"},"language":{"type":"string","description":"Language"},"sentiment":{"type":"string","description":"Sentiment"}},"required":["tone","emotion","language","sentiment"]},"RoleplayTranscriptDto":{"type":"object","properties":{"from":{"type":"string","enum":["ai","user"]},"text":{"type":"string"},"metadata":{"$ref":"#/components/schemas/RoleplayTranscriptMetadataDto"},"timestamp":{"type":"number"}},"required":["from","text","timestamp"]},"SchemaFieldValidationsDto":{"type":"object","properties":{"required":{"type":"boolean"},"min":{"type":"number"},"max":{"type":"number"},"regex":{"type":"string"},"custom":{"type":"string"},"default":{"type":"string"}}},"CalculatedFieldDto":{"type":"object","properties":{"dependencies":{"type":"array","items":{"type":"string"}},"formula":{"type":"string"}},"required":["dependencies","formula"]},"SchemaFieldDto":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["string","number","boolean","array","object","enum","union","date","file","calculated"]},"description":{"type":"string"},"children":{"type":"array","items":{"$ref":"#/components/schemas/SchemaFieldDto"}},"enumValues":{"type":"array","items":{"type":"string"}},"validations":{"$ref":"#/components/schemas/SchemaFieldValidationsDto"},"label":{"type":"string"},"calculatedField":{"$ref":"#/components/schemas/CalculatedFieldDto"}},"required":["name","type"]},"ToolDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier of the tool"},"name":{"type":"string","description":"Name of the tool/function"},"description":{"type":"string","description":"Description of what the tool does"},"instruction":{"type":"string","description":"Instructions for GPT on how to use this tool"},"toolType":{"type":"string","description":"Type of the tool","enum":["HTTP","MCP","CODE"],"example":"HTTP"},"url":{"type":"string","description":"Webhook URL to call (HTTP tools only)"},"method":{"type":"string","description":"HTTP method to use (HTTP tools only)","enum":["GET","POST","PUT","PATCH","DELETE"]},"headers":{"type":"object","description":"HTTP headers to include in the request (HTTP tools only)","example":{"Authorization":"Bearer token123","Content-Type":"application/json"}},"mcpServerUrl":{"type":"string","description":"MCP server URL (MCP tools only)"},"mcpServerHeaders":{"type":"object","description":"MCP server headers for authentication (MCP tools only)"},"mcpServerName":{"type":"string","description":"Human-readable name for the MCP server (MCP tools only)"},"mcpToolName":{"type":"string","description":"Name of the specific tool/function on the MCP server (MCP tools only)"},"codeLanguage":{"type":"string","description":"Code language (CODE tools only)","enum":["PYTHON","JAVASCRIPT","TYPESCRIPT"]},"codeSource":{"type":"string","description":"Customer code source (CODE tools only)"},"codeTestCases":{"type":"object","description":"Saved code test vectors (CODE tools only)","nullable":true},"inputSchema":{"description":"Input schema for validation - root schema object","example":{"name":"function_params","type":"object","description":"Function input parameters","children":[{"name":"query","type":"string","description":"Search query","validations":{"required":true,"min":1,"max":100},"label":"Search Query"},{"name":"category","type":"enum","description":"Category filter","enumValues":["news","weather","sports"],"validations":{"required":false}}]},"allOf":[{"$ref":"#/components/schemas/SchemaFieldDto"}]},"isActive":{"type":"boolean","description":"Whether the tool is active"},"createdAt":{"format":"date-time","type":"string","description":"When the tool was created"},"updatedAt":{"format":"date-time","type":"string","description":"When the tool was last updated"}},"required":["id","name","description","instruction","toolType","inputSchema","isActive","createdAt","updatedAt"]},"AgentToolDto":{"type":"object","properties":{"agentId":{"type":"string","description":"Agent id"},"toolId":{"type":"string","description":"Tool id"},"createdAt":{"format":"date-time","type":"string","description":"Tool name"},"tool":{"description":"Tool","allOf":[{"$ref":"#/components/schemas/ToolDto"}]}},"required":["agentId","toolId","createdAt","tool"]},"DataCollectionResultDto":{"type":"object","properties":{"id":{"type":"string"},"dataCollectionId":{"type":"string"},"callId":{"type":"string"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"dataValue":{"type":"object","additionalProperties":true}},"required":["id","dataCollectionId","callId","createdAt","updatedAt","dataValue"]},"DataCollectionResponseDto":{"type":"object","properties":{"dataIdentifier":{"type":"string"},"description":{"type":"string"},"dataType":{"type":"string","enum":["STRING","NUMBER","BOOLEAN","INTEGER","DATE"]},"id":{"type":"string"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"agentId":{"type":"string"},"results":{"type":"array","items":{"$ref":"#/components/schemas/DataCollectionResultDto"}}},"required":["dataIdentifier","description","dataType","id","createdAt","updatedAt","agentId"]},"EvaluationResultDto":{"type":"object","properties":{"id":{"type":"string"},"callId":{"type":"string"},"evaluationId":{"type":"string"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"type":{"type":"string","enum":["SUCCESS","FAILURE","UNKNOWN"]},"rationale":{"type":"string"}},"required":["id","callId","evaluationId","createdAt","updatedAt","type","rationale"]},"EvaluationResponseDto":{"type":"object","properties":{"name":{"type":"string"},"prompt":{"type":"string"},"id":{"type":"string"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"},"agentId":{"type":"string"},"results":{"type":"array","items":{"$ref":"#/components/schemas/EvaluationResultDto"}}},"required":["name","prompt","id","createdAt","updatedAt","agentId"]},"AgentEmailAddressDto":{"type":"object","properties":{"address":{"type":"string","description":"Full agent email address (slug@domain)"},"status":{"type":"string","enum":["ACTIVE","DISABLED"],"description":"Routing status for the email address"}},"required":["address","status"]},"AgentDto":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","description":"Agent name"},"description":{"type":"string","description":"Agent description"},"avatar":{"type":"string","description":"Agent avatar"},"isPublic":{"type":"boolean","description":"Is agent public"},"isActive":{"type":"boolean","description":"Is agent active"},"instructions":{"type":"string","description":"Agent instructions"},"incomingCallInstructions":{"type":"string","description":"Agent instructions for incoming calls"},"maxIncomingCallDurationMinutes":{"type":"number","description":"Max duration of incoming call in minutes"},"maxOutgoingCallDurationMinutes":{"type":"number","description":"Max duration of outgoing call in minutes"},"gatheringInformationOnIncomingCall":{"type":"boolean","description":"Whether the agent allows gathering information on incoming call"},"createdAt":{"format":"date-time","type":"string","description":"Agent created at"},"updatedAt":{"format":"date-time","type":"string","description":"Agent updated at"},"deletedAt":{"format":"date-time","type":"string","description":"Agent deleted at"},"userId":{"type":"string","description":"Creator user id"},"tools":{"description":"Agent tools","type":"array","items":{"$ref":"#/components/schemas/AgentToolDto"}},"accessToKnowledge":{"type":"boolean","description":"Is agent allowed to access knowledge"},"knowledgeAccessMode":{"type":"string","description":"Knowledge access mode for the agent","enum":["NONE","ALL","TAGS_ONLY"]},"knowledgeAccessTags":{"description":"Tags that the agent has access to when knowledge access is tag-limited","type":"array","items":{"type":"string"}},"allowFollowUps":{"type":"boolean","description":"Is agent allowed to schedule follow-ups"},"followUpInstructions":{"type":"string","description":"Custom instructions for smart follow-up messages"},"includePrivateData":{"type":"boolean","description":"Whether the user's profile info (owner name, phone, address, DOB, company) is included in the agent prompt"},"useBusinessProfile":{"type":"boolean","description":"Whether business Q&A presets are shared with this agent in prompts"},"useDetachedReceptionistProfile":{"type":"boolean","description":"Whether prompts should use this agent-specific represented receptionist profile"},"receptionistPreferredName":{"type":"string","description":"Prompt-facing represented person, practice, or business name"},"receptionistCompanyName":{"type":"string","description":"Prompt-facing represented company or business name"},"receptionistCompanyWebsite":{"type":"string","description":"Prompt-facing represented company website"},"receptionistCompanyDescription":{"type":"string","description":"Prompt-facing represented company description"},"receptionistCompanyIndustry":{"type":"string","description":"Prompt-facing represented company industry"},"receptionistAddress":{"type":"string","description":"Prompt-facing represented business street address"},"receptionistCityName":{"type":"string","description":"Prompt-facing represented business city"},"receptionistStateName":{"type":"string","description":"Prompt-facing represented business state"},"receptionistZipCode":{"type":"string","description":"Prompt-facing represented business ZIP/postal code"},"receptionistTimezone":{"type":"string","description":"Prompt-facing represented business timezone as an IANA timezone name"},"voice":{"type":"string","description":"Agent voice"},"firstMessage":{"type":"string","description":"First message to be sent to the agent"},"allowOutboundGreetingInterruptions":{"type":"boolean","description":"Whether recipients can interrupt the initial greeting on outbound calls","default":false},"enableVoiceExpressions":{"type":"boolean","description":"Whether the generated voice prompt includes provider-specific expression guidance","default":true},"closingPhrase":{"type":"string","description":"Closing phrase the agent says before ending an inbound call"},"delayAcceptSeconds":{"type":"number","description":"Seconds to wait before the voice agent joins an inbound call.","default":0},"voiceRecognition":{"type":"string","description":"Voice recognition mode: EN for English-only (highest accuracy), MULTI for multilingual support","default":"EN"},"temperature":{"type":"number","description":"Temperature for the agent"},"dataCollections":{"description":"Data collections for the agent","type":"array","items":{"$ref":"#/components/schemas/DataCollectionResponseDto"}},"evaluations":{"description":"Evaluations for the agent","type":"array","items":{"$ref":"#/components/schemas/EvaluationResponseDto"}},"welcomingVoiceMailMessageForContacts":{"type":"string","description":"Welcoming voice mail message for contacts"},"welcomingVoiceMailMessageForOthers":{"type":"string","description":"Welcoming voice mail message for others"},"isVoiceMailAgent":{"type":"boolean","description":"Is agent a voice mail agent","default":false},"voiceSpeed":{"type":"number","description":"Voice pace from slow to fast. 0.5 is normal/provider default. Not all voice providers support speed control.","default":0.5,"minimum":0,"maximum":1},"incomingCallTypingSound":{"type":"boolean","description":"Typing sound for the agent","default":true},"incomingCallBackgroundSound":{"type":"boolean","description":"Background sound for the agent","default":true},"outgoingCallBackgroundSound":{"type":"boolean","description":"Background sound for the agent","default":true},"outgoingCallTypingSound":{"type":"boolean","description":"Typing sound for the agent","default":true},"allowIncomingSms":{"type":"boolean","description":"Whether the agent allows incoming SMS messages","default":false},"incomingSmsInstructions":{"type":"string","description":"Instructions for the agent on incoming SMS messages","default":""},"autoRespondToSms":{"type":"boolean","description":"Whether the agent automatically responds to SMS messages","default":true},"smsResponseDelay":{"type":"number","description":"Delay in seconds before responding to SMS messages","default":1},"postCallSmsMessage":{"type":"string","description":"Post-call SMS message to send after incoming calls complete"},"allowRealtimeSms":{"type":"boolean","description":"Whether the agent can send SMS messages during calls via the send_sms tool","default":false},"phoneNumbers":{"description":"Phone numbers for the agent","type":"array","items":{"$ref":"#/components/schemas/NumberItemDto"}},"emailAddress":{"description":"Active email receptionist address for the agent, if any","nullable":true,"allOf":[{"$ref":"#/components/schemas/AgentEmailAddressDto"}]},"requireDataConsent":{"type":"boolean","description":"Whether the agent requires data consent before starting calls","default":false},"dataConsentText":{"type":"string","description":"Custom text/instructions for what consent is being requested for"},"enablePostCallActions":{"type":"boolean","description":"Whether to enable post-call outbound actions (scheduling calls after incoming calls)","default":false},"postCallActionInstructions":{"type":"string","description":"Free-form instructions for post-call actions. Example: \"If HVAC emergency, call John at +1234567890 immediately.\""},"behaviorPreset":{"type":"string","description":"Behavior preset for prompt generation. Supported presets are default, employee, and lead-qualify.","default":"default","enum":["default","employee","lead-qualify"]},"strictSpamFilter":{"type":"boolean","description":"Strictly reject incoming calls detected as spam before connecting to the agent","default":false},"valuableCallRule":{"type":"string","description":"Custom rule for detecting valuable incoming calls after each call.","nullable":true},"overrideCallerId":{"type":"string","description":"UUID of a verified caller ID to use for outbound calls. Null to clear."}},"required":["id","name","isPublic","isActive","instructions","incomingCallInstructions","maxIncomingCallDurationMinutes","maxOutgoingCallDurationMinutes","gatheringInformationOnIncomingCall","createdAt","updatedAt","userId"]},"VoiceMailMessagesDto":{"type":"object","properties":{"transcription":{"type":"string"},"audioUrl":{"type":"string"},"duration":{"type":"number"},"createdAt":{"format":"date-time","type":"string"}},"required":["transcription","audioUrl","duration","createdAt"]},"CallAnalysisDto":{"type":"object","properties":{"sentiment":{"type":"string","description":"Sentiment","enum":["positive","negative","neutral"]},"sentimentScore":{"type":"number","description":"Sentiment score"},"detectedLanguage":{"type":"string","description":"Detected language"},"detectedLanguageConfidence":{"type":"number","description":"Detected language confidence"}},"required":["sentiment","sentimentScore","detectedLanguage","detectedLanguageConfidence"]},"CallFollowUpDto":{"type":"object","properties":{"id":{"type":"string","description":"Follow-up ID"},"type":{"type":"string","description":"Follow-up type","enum":["SMS","EMAIL","CALL"]},"content":{"type":"string","description":"Follow-up content"},"recipientEmail":{"type":"string","description":"Recipient email"},"recipientPhone":{"type":"string","description":"Recipient phone"},"status":{"type":"string","description":"Follow-up status","enum":["PENDING","AWAITING_CLARIFICATION","IN_PROGRESS","COMPLETED","FAILED","CANCELLED","SCHEDULED"]},"createdAt":{"format":"date-time","type":"string","description":"Follow-up created at"},"updatedAt":{"format":"date-time","type":"string","description":"Follow-up updated at"},"triggeredByCallId":{"type":"string","description":"Outbound call that triggered this follow-up, when different from the parent call"}},"required":["id","type","content","status","createdAt","updatedAt"]},"TaskDto":{"type":"object","properties":{"id":{"type":"string","description":"Task ID"},"title":{"type":"string","description":"Task title"},"description":{"type":"string","description":"Task description"},"status":{"type":"string","description":"Task status","enum":["TODO","IN_PROGRESS","COMPLETED"]},"createdAt":{"format":"date-time","type":"string","description":"Task created at"},"updatedAt":{"format":"date-time","type":"string","description":"Task updated at"},"dueDate":{"format":"date-time","type":"string","description":"Task due date"},"priority":{"type":"string","description":"Task priority","enum":["HIGH","MEDIUM","LOW"]},"leadNotes":{"type":"string","description":"Task lead notes"},"leadStatus":{"type":"string","description":"Task lead status"},"tags":{"description":"Task tags","type":"array","items":{"type":"string"}},"isAiGenerated":{"type":"boolean","description":"Task is AI generated"},"completedAt":{"format":"date-time","type":"string","description":"Task completed at"},"completedBy":{"type":"string","description":"Task completed by"}},"required":["id","title","description","status","createdAt","updatedAt","dueDate","priority","leadNotes","leadStatus","tags","isAiGenerated","completedAt","completedBy"]},"TaskResultDto":{"type":"object","properties":{"id":{"type":"string","description":"Task result ID"},"slug":{"type":"string","description":"Task slug (stable identifier)"},"title":{"type":"string","description":"Human-readable task title (from definition, may be null if deleted)","nullable":true},"groupName":{"type":"string","description":"Group the task belongs to (e.g. Collect Information)","nullable":true},"status":{"type":"string","description":"Outcome of the task on this call","enum":["completed","unable","not_attempted"]},"reason":{"type":"string","description":"Agent's explanation or the collected value","nullable":true},"createdAt":{"format":"date-time","type":"string","description":"When the result was recorded"}},"required":["id","slug","status","createdAt"]},"CallForwardingInfoDto":{"type":"object","properties":{"type":{"type":"string","enum":["direct","forwarded"]},"chain":{"type":"array","items":{"type":"string"}}},"required":["type","chain"]},"CallDto":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"phoneNumber":{"type":"string","description":"Phone number to call"},"source":{"type":"string","description":"How the outbound call was created","enum":["LEGACY_UNKNOWN","MANUAL_SCHEDULING","CHAT","POST_CALL_ACTION","CONTACT_ACTION","INTEGRATION","CAMPAIGN","USER_COPY","SMART_RETRY","RECURRING","AGENT_TEST","ADMIN_COPY"]},"callFrom":{"type":"string","description":"Call from #"},"goal":{"type":"string","description":"Call goal"},"goalStatus":{"type":"string","description":"Goal achievement status","enum":["UNKNOWN","SUCCESS","FAILED"],"default":"UNKNOWN"},"scheduledAt":{"format":"date-time","type":"string","description":"Call scheduled at"},"title":{"type":"string","description":"Call title"},"status":{"type":"string","description":"Call status","enum":["QUEUED","IN_PROGRESS","AWAITING_CONNECTION","SUCCESS","FAILED","NOT_STARTED","CANCELLED","CALL_TRANSFERRED"]},"additionalContext":{"type":"string","description":"Additional context"},"minutesUsed":{"type":"number","description":"Minutes used"},"transactions":{"description":"Transactions related to the call","type":"array","items":{"$ref":"#/components/schemas/TransactionDto"}},"voice":{"type":"string","description":"Voice used for the call"},"retryAfterMinutes":{"type":"number","description":"Retry after minutes"},"maxDurationMinutes":{"type":"number","description":"Max duration of the call in minutes"},"doWeNeedToRetry":{"type":"boolean","description":"Do we need to retry the call"},"recordingUrl":{"type":"string","description":"Recording URL"},"userRating":{"type":"boolean","description":"User rating, where true is good and false is bad. null is no rating."},"reviewedAt":{"format":"date-time","type":"string","description":"Reviewed at"},"finalSummary":{"type":"string","description":"Final summary"},"shortFinalSummary":{"type":"string","description":"Short final summary"},"placeWhereToCall":{"type":"string","description":"Place where to call"},"roleplayTranscript":{"description":"Roleplay transcript","type":"array","items":{"$ref":"#/components/schemas/RoleplayTranscriptDto"}},"agent":{"description":"Agent","allOf":[{"$ref":"#/components/schemas/AgentDto"}]},"voicemails":{"description":"Voice mail messages","type":"array","items":{"$ref":"#/components/schemas/VoiceMailMessagesDto"}},"isCallTransferred":{"type":"boolean","description":"Whether the call is transferred","default":false},"dataCollections":{"description":"Data collections","type":"array","items":{"$ref":"#/components/schemas/DataCollectionResultDto"}},"evaluations":{"description":"Evaluations","type":"array","items":{"$ref":"#/components/schemas/EvaluationResultDto"}},"analysis":{"description":"Analysis","allOf":[{"$ref":"#/components/schemas/CallAnalysisDto"}]},"followUps":{"description":"Follow-ups","type":"array","items":{"$ref":"#/components/schemas/CallFollowUpDto"}},"tasks":{"description":"Tasks","type":"array","items":{"$ref":"#/components/schemas/TaskDto"}},"taskResults":{"description":"Per-call results of the agent goals (Call Handling): what it asked/did and the outcome","type":"array","items":{"$ref":"#/components/schemas/TaskResultDto"}},"voiceSpeed":{"type":"number","description":"Voice speed"},"callTypingSound":{"type":"boolean","description":"Typing sound","default":true},"callBackgroundSound":{"type":"boolean","description":"Background sound","default":true},"recommendedNextAction":{"type":"string","description":"Recommended next action (AI generated)"},"testCall":{"type":"boolean","description":"Test call","default":false},"isFavorite":{"type":"boolean","description":"Is this call favorited by the user","default":false},"callInterceptedByUser":{"type":"boolean","description":"Whether the call was intercepted by the user","default":false},"shareHash":{"type":"string","description":"Share hash for public sharing"},"matchedFields":{"description":"Fields that matched the search query (only present in search results)","example":["phone","summary","title","goal"],"type":"array","items":{"type":"string"}},"notes":{"type":"string","description":"User manual notes about this call (max 400 chars)","maxLength":400},"contactId":{"type":"string","description":"Linked contact ID","example":"123e4567-e89b-12d3-a456-426614174000"},"forwardingInfo":{"description":"Parsed called-party forwarding route when SIP evidence is available","allOf":[{"$ref":"#/components/schemas/CallForwardingInfoDto"}]}},"required":["id","userId","phoneNumber","source","goal","goalStatus","scheduledAt","title","status"]},"BaseCallResponseDto":{"type":"object","properties":{"success":{"type":"boolean","description":"Success"},"call":{"description":"Call","allOf":[{"$ref":"#/components/schemas/CallDto"}]}},"required":["success"]},"BaseUnsuccessfulCallResponseDto":{"type":"object","properties":{"success":{"type":"boolean"},"reason":{"type":"string","enum":["success","needs_clarification","denied","system_error","insufficient_credits","normal_error"]},"errorMessage":{"type":"string"},"needsClarification":{"type":"boolean"},"clarificationQuestion":{"type":"string"},"originalGoal":{"type":"string"},"isAllowed":{"type":"boolean"},"moderationReason":{"type":"string"},"moderationSuggestedAction":{"type":"string"}},"required":["success","reason"]},"CallSimpleResponseDto":{"type":"object","properties":{"success":{"type":"boolean","description":"Success"},"message":{"type":"string","description":"Message"}},"required":["success"]},"CopyCallDto":{"type":"object","properties":{"scheduledAt":{"type":"string"},"phoneNumber":{"type":"string"}},"required":["scheduledAt"]},"CallHistoryResponseDto":{"type":"object","properties":{"calls":{"description":"Calls","type":"array","items":{"$ref":"#/components/schemas/CallDto"}},"total":{"type":"number","description":"Total number of calls"},"stats":{"type":"object","description":"Stats"}},"required":["calls","total","stats"]},"SearchCallResultDto":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"phoneNumber":{"type":"string","description":"Phone number to call"},"source":{"type":"string","description":"How the outbound call was created","enum":["LEGACY_UNKNOWN","MANUAL_SCHEDULING","CHAT","POST_CALL_ACTION","CONTACT_ACTION","INTEGRATION","CAMPAIGN","USER_COPY","SMART_RETRY","RECURRING","AGENT_TEST","ADMIN_COPY"]},"callFrom":{"type":"string","description":"Call from #"},"goal":{"type":"string","description":"Call goal"},"goalStatus":{"type":"string","description":"Goal achievement status","enum":["UNKNOWN","SUCCESS","FAILED"],"default":"UNKNOWN"},"scheduledAt":{"format":"date-time","type":"string","description":"Call scheduled at"},"title":{"type":"string","description":"Call title"},"status":{"type":"string","description":"Call status","enum":["QUEUED","IN_PROGRESS","AWAITING_CONNECTION","SUCCESS","FAILED","NOT_STARTED","CANCELLED","CALL_TRANSFERRED"]},"additionalContext":{"type":"string","description":"Additional context"},"minutesUsed":{"type":"number","description":"Minutes used"},"transactions":{"description":"Transactions related to the call","type":"array","items":{"$ref":"#/components/schemas/TransactionDto"}},"voice":{"type":"string","description":"Voice used for the call"},"retryAfterMinutes":{"type":"number","description":"Retry after minutes"},"maxDurationMinutes":{"type":"number","description":"Max duration of the call in minutes"},"doWeNeedToRetry":{"type":"boolean","description":"Do we need to retry the call"},"recordingUrl":{"type":"string","description":"Recording URL"},"userRating":{"type":"boolean","description":"User rating, where true is good and false is bad. null is no rating."},"reviewedAt":{"format":"date-time","type":"string","description":"Reviewed at"},"finalSummary":{"type":"string","description":"Final summary"},"shortFinalSummary":{"type":"string","description":"Short final summary"},"placeWhereToCall":{"type":"string","description":"Place where to call"},"roleplayTranscript":{"description":"Roleplay transcript","type":"array","items":{"$ref":"#/components/schemas/RoleplayTranscriptDto"}},"agent":{"description":"Agent","allOf":[{"$ref":"#/components/schemas/AgentDto"}]},"voicemails":{"description":"Voice mail messages","type":"array","items":{"$ref":"#/components/schemas/VoiceMailMessagesDto"}},"isCallTransferred":{"type":"boolean","description":"Whether the call is transferred","default":false},"dataCollections":{"description":"Data collections","type":"array","items":{"$ref":"#/components/schemas/DataCollectionResultDto"}},"evaluations":{"description":"Evaluations","type":"array","items":{"$ref":"#/components/schemas/EvaluationResultDto"}},"analysis":{"description":"Analysis","allOf":[{"$ref":"#/components/schemas/CallAnalysisDto"}]},"followUps":{"description":"Follow-ups","type":"array","items":{"$ref":"#/components/schemas/CallFollowUpDto"}},"tasks":{"description":"Tasks","type":"array","items":{"$ref":"#/components/schemas/TaskDto"}},"taskResults":{"description":"Per-call results of the agent goals (Call Handling): what it asked/did and the outcome","type":"array","items":{"$ref":"#/components/schemas/TaskResultDto"}},"voiceSpeed":{"type":"number","description":"Voice speed"},"callTypingSound":{"type":"boolean","description":"Typing sound","default":true},"callBackgroundSound":{"type":"boolean","description":"Background sound","default":true},"recommendedNextAction":{"type":"string","description":"Recommended next action (AI generated)"},"testCall":{"type":"boolean","description":"Test call","default":false},"isFavorite":{"type":"boolean","description":"Is this call favorited by the user","default":false},"callInterceptedByUser":{"type":"boolean","description":"Whether the call was intercepted by the user","default":false},"shareHash":{"type":"string","description":"Share hash for public sharing"},"matchedFields":{"description":"Fields that matched the search query (only present in search results)","example":["phone","summary","title","goal"],"type":"array","items":{"type":"string"}},"notes":{"type":"string","description":"User manual notes about this call (max 400 chars)","maxLength":400},"contactId":{"type":"string","description":"Linked contact ID","example":"123e4567-e89b-12d3-a456-426614174000"},"forwardingInfo":{"description":"Parsed called-party forwarding route when SIP evidence is available","allOf":[{"$ref":"#/components/schemas/CallForwardingInfoDto"}]},"callType":{"type":"string","description":"Call type (outgoing or incoming)","enum":["outgoing","incoming"]}},"required":["id","userId","phoneNumber","source","goal","goalStatus","scheduledAt","title","status","callType"]},"SearchCallsResponseDto":{"type":"object","properties":{"calls":{"$ref":"#/components/schemas/SearchCallResultDto"}},"required":["calls"]},"RateCallDto":{"type":"object","properties":{}},"UpdateCallNotesDto":{"type":"object","properties":{"notes":{"type":"string","description":"User notes for the call (max 400 characters)","maxLength":400,"example":"Follow up next week about the pricing"},"isIncomingCall":{"type":"boolean","description":"Whether this is an incoming call (default: false = outgoing)","default":false}},"required":["notes"]},"DataCollectionDto":{"type":"object","properties":{"id":{"type":"string","description":"Data collection ID"},"agentId":{"type":"string","description":"Agent ID"},"createdAt":{"format":"date-time","type":"string","description":"Created at timestamp"},"updatedAt":{"format":"date-time","type":"string","description":"Updated at timestamp"},"deletedAt":{"format":"date-time","type":"string","description":"Deleted at timestamp"},"dataType":{"type":"string","description":"Data collection type","enum":["STRING","NUMBER","BOOLEAN","INTEGER","DATE"]},"dataIdentifier":{"type":"string","description":"Data collection identifier"},"description":{"type":"string","description":"Data collection description"}},"required":["id","agentId","createdAt","updatedAt","dataType","dataIdentifier","description"]},"EvaluationDto":{"type":"object","properties":{"id":{"type":"string","description":"Evaluation ID"},"agentId":{"type":"string","description":"Agent ID"},"createdAt":{"format":"date-time","type":"string","description":"Created at timestamp"},"updatedAt":{"format":"date-time","type":"string","description":"Updated at timestamp"},"deletedAt":{"format":"date-time","type":"string","description":"Deleted at timestamp"},"name":{"type":"string","description":"Evaluation name"},"prompt":{"type":"string","description":"Evaluation prompt"}},"required":["id","agentId","createdAt","updatedAt","name","prompt"]},"CallBookingDto":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"startTime":{"format":"date-time","type":"string"},"endTime":{"format":"date-time","type":"string"},"durationMinutes":{"type":"number"},"guestPhone":{"type":"string"},"guestEmail":{"type":"string"},"guestName":{"type":"string"},"sourceType":{"type":"string","enum":["INBOUND_CALL","OUTBOUND_CALL","SMS","MANUAL"]},"calendarProvider":{"type":"string","enum":["GOOGLE","CALENDLY","CALCOM","SQUARE","OUTLOOK","GHL","APPLE"]},"externalEventUrl":{"type":"string","description":"Link to the event in external calendar"},"timezone":{"type":"string"},"createdAt":{"format":"date-time","type":"string"}},"required":["id","title","startTime","endTime","durationMinutes","sourceType","calendarProvider","createdAt"]},"IncomingCallDto":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"phoneNumberFrom":{"type":"string","description":"Phone number from call"},"createdAt":{"format":"date-time","type":"string","description":"Started at"},"title":{"type":"string","description":"Call title"},"callerName":{"type":"string","description":"Caller name"},"status":{"type":"string","description":"Call status","enum":["FINISHED","PROCESSED","FAILED","IN_PROGRESS"]},"minutesUsed":{"type":"number","description":"Minutes used"},"transactions":{"description":"Transactions related to the call","type":"array","items":{"$ref":"#/components/schemas/TransactionDto"}},"recordingUrl":{"type":"string","description":"Recording URL"},"userRating":{"type":"boolean","description":"User rating, where true is good and false is bad. null is no rating."},"reviewedAt":{"format":"date-time","type":"string","description":"Reviewed at"},"finalSummary":{"type":"string","description":"Final summary"},"roleplayTranscript":{"description":"Transcript","type":"array","items":{"$ref":"#/components/schemas/RoleplayTranscriptDto"}},"transcript":{"type":"string","description":"Transcript in plain text"},"agent":{"description":"Agent","allOf":[{"$ref":"#/components/schemas/AgentDto"}]},"phoneNumberTo":{"description":"Phone number to","allOf":[{"$ref":"#/components/schemas/NumberItemDto"}]},"followUps":{"description":"Follow ups","type":"array","items":{"$ref":"#/components/schemas/CallFollowUpDto"}},"tasks":{"description":"Tasks","type":"array","items":{"$ref":"#/components/schemas/TaskDto"}},"taskResults":{"description":"Per-call results of the agent goals (Call Handling): what it asked/did and the outcome","type":"array","items":{"$ref":"#/components/schemas/TaskResultDto"}},"dataCollections":{"description":"Data collections","type":"array","items":{"$ref":"#/components/schemas/DataCollectionDto"}},"evaluations":{"description":"Evaluations","type":"array","items":{"$ref":"#/components/schemas/EvaluationDto"}},"recommendedNextAction":{"type":"string","description":"Recommended next action"},"testCall":{"type":"boolean","description":"Test call","default":false},"isFavorite":{"type":"boolean","description":"Is this call favorited by the user","default":false},"isSpam":{"type":"boolean","description":"Whether the call is looks like spam or unwanted call"},"callInterceptedByUser":{"type":"boolean","default":false,"description":"Whether the call was intercepted by the user"},"shareHash":{"type":"string","description":"Share hash for public sharing"},"matchedFields":{"description":"Fields that matched the search query (only present in search results)","example":["phone","summary","title","caller"],"type":"array","items":{"type":"string"}},"bookings":{"description":"Appointments booked during this call","type":"array","items":{"$ref":"#/components/schemas/CallBookingDto"}},"notes":{"type":"string","description":"User manual notes about this call (max 400 chars)","maxLength":400},"contactId":{"type":"string","description":"Linked contact ID","example":"123e4567-e89b-12d3-a456-426614174000"},"forwardingInfo":{"description":"Parsed called-party forwarding route when SIP evidence is available","allOf":[{"$ref":"#/components/schemas/CallForwardingInfoDto"}]}},"required":["id","userId","phoneNumberFrom","createdAt","status","transactions"]},"IncomingCallHistoryResponseDto":{"type":"object","properties":{"calls":{"description":"Incoming calls","type":"array","items":{"$ref":"#/components/schemas/IncomingCallDto"}},"total":{"type":"number","description":"Total number of incoming calls"}},"required":["calls","total"]},"BlockCallerResponseDto":{"type":"object","properties":{"success":{"type":"boolean","description":"Whether the operation succeeded","example":true},"blocked":{"type":"boolean","description":"Whether the phone number is now blocked","example":true},"blockedNumber":{"type":"string","description":"The phone number affected (original format)","example":"+14155551234"}},"required":["success","blocked","blockedNumber"]},"CreateAgentDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"avatar":{"type":"string"},"isPublic":{"type":"boolean"},"isActive":{"type":"boolean"},"instructions":{"type":"string"},"toolIds":{"type":"array","items":{"type":"string"}},"voice":{"type":"string","description":"Voice to use for the agent"},"sttKeyterms":{"description":"Words or short phrases passed to LiveKit as speech-to-text keyterms","maxItems":50,"type":"array","items":{"type":"string"}},"voiceSpeed":{"type":"number","description":"Voice pace from slow to fast. 0.5 is normal/provider default. Not all voice providers support speed control.","default":0.5,"minimum":0,"maximum":1},"accessToKnowledge":{"type":"boolean","description":"Whether the agent has access to knowledge","default":false},"knowledgeAccessMode":{"type":"string","description":"Knowledge access mode for the agent","enum":["NONE","ALL","TAGS_ONLY"],"default":"NONE"},"knowledgeAccessTags":{"description":"Tags that the agent has access to (only used when knowledgeAccessMode is TAGS_ONLY)","default":[],"type":"array","items":{"type":"string"}},"includePrivateData":{"type":"boolean","description":"Include the user's profile info (owner name, phone, address, DOB, company) in the agent prompt.","default":true},"useBusinessProfile":{"type":"boolean","description":"Include business Q&A presets (hours, pricing, services) from /business-profile in the agent prompt","default":true},"useDetachedReceptionistProfile":{"type":"boolean","description":"Use per-agent receptionist profile fields in prompts instead of only the account profile","default":false},"receptionistPreferredName":{"type":"string","description":"Prompt-facing represented person, practice, or business name"},"receptionistCompanyName":{"type":"string","description":"Prompt-facing represented company or business name"},"receptionistCompanyWebsite":{"type":"string","description":"Prompt-facing represented company website"},"receptionistCompanyDescription":{"type":"string","description":"Prompt-facing represented company description"},"receptionistCompanyIndustry":{"type":"string","description":"Prompt-facing represented company industry"},"receptionistAddress":{"type":"string","description":"Prompt-facing represented business street address"},"receptionistCityName":{"type":"string","description":"Prompt-facing represented business city"},"receptionistStateName":{"type":"string","description":"Prompt-facing represented business state"},"receptionistZipCode":{"type":"string","description":"Prompt-facing represented business ZIP/postal code"},"receptionistTimezone":{"type":"string","description":"Prompt-facing represented business timezone as an IANA timezone name","example":"America/New_York"},"firstMessage":{"type":"string","description":"First message to send from the agent"},"allowOutboundGreetingInterruptions":{"type":"boolean","description":"Whether recipients can interrupt the initial greeting on outbound calls","default":false},"enableVoiceExpressions":{"type":"boolean","description":"Whether the generated voice prompt includes provider-specific expression guidance","default":true},"closingPhrase":{"type":"string","description":"Closing phrase the agent says before ending an inbound call"},"delayAcceptSeconds":{"type":"number","description":"Seconds to wait before the voice agent joins an inbound call.","default":0,"minimum":0,"maximum":20},"voiceRecognition":{"type":"string","description":"Voice recognition mode: EN for English-only (highest accuracy), MULTI for multilingual support","enum":["EN","MULTI"],"default":"EN"},"allowFollowUps":{"type":"boolean","description":"Whether the agent allows follow-ups","default":false},"followUpInstructions":{"type":"string","description":"Custom instructions for smart follow-up messages. When provided, the AI uses these to guide follow-up content."},"gatheringInformationOnIncomingCall":{"type":"boolean","description":"Whether the agent allows gathering information on incoming call","default":false},"maxIncomingCallDurationMinutes":{"type":"number","description":"Max duration of incoming call in minutes","default":3},"maxOutgoingCallDurationMinutes":{"type":"number","description":"Max duration of outgoing call in minutes","default":10},"incomingCallInstructions":{"type":"string","description":"Instructions for the agent on incoming calls"},"welcomingVoiceMailMessageForContacts":{"type":"string","description":"Welcoming voice mail message for contacts"},"welcomingVoiceMailMessageForOthers":{"type":"string","description":"Welcoming voice mail message for others"},"isVoiceMailAgent":{"type":"boolean","description":"Is agent a voice mail agent","default":false},"incomingCallTypingSound":{"type":"boolean","description":"Whether the agent has a typing sound for incoming calls","default":true},"incomingCallBackgroundSound":{"type":"boolean","description":"Whether the agent has a background sound for incoming calls","default":true},"outgoingCallTypingSound":{"type":"boolean","description":"Whether the agent has a typing sound for outgoing calls","default":true},"outgoingCallBackgroundSound":{"type":"boolean","description":"Whether the agent has a background sound for outgoing calls","default":true},"allowIncomingSms":{"type":"boolean","description":"Whether the agent allows incoming SMS messages","default":false},"incomingSmsInstructions":{"type":"string","description":"Instructions for the agent on incoming SMS messages","default":""},"autoRespondToSms":{"type":"boolean","description":"Whether the agent automatically responds to SMS messages","default":true},"smsResponseDelay":{"type":"number","description":"Delay in seconds before responding to SMS messages","default":1},"postCallSmsMessage":{"type":"string","description":"Post-call SMS message to send after incoming calls complete"},"allowRealtimeSms":{"type":"boolean","description":"Whether the agent can send SMS messages during calls via the send_sms tool","default":false},"requireDataConsent":{"type":"boolean","description":"Whether the agent requires data consent before starting calls","default":false},"dataConsentText":{"type":"string","description":"Custom text/instructions for what consent is being requested for"},"enablePostCallActions":{"type":"boolean","description":"Whether to enable post-call outbound actions (scheduling calls after incoming calls)","default":false},"postCallActionInstructions":{"type":"string","description":"Free-form instructions for post-call actions. Example: \"If HVAC emergency, call John at +1234567890 immediately. If plumbing issue, call Mike at +1555555555 in 5 minutes.\""},"behaviorPreset":{"type":"string","description":"Behavior preset for normal agent create/update. New agents are currently created as employee; lead-qualify is manual/admin-only.","default":"employee","enum":["default","employee"]},"strictSpamFilter":{"type":"boolean","description":"Strictly reject incoming calls detected as spam before connecting to the agent","default":false},"valuableCallRule":{"type":"string","description":"Custom rule for detecting valuable incoming calls after each call. Max 300 characters.","nullable":true},"overrideCallerId":{"type":"string","description":"UUID of a verified caller ID to use for outbound calls. Null to clear.","nullable":true}},"required":["name","instructions"]},"AgentValidationDto":{"type":"object","properties":{"message":{"type":"string","description":"The message to be displayed to the user"},"reason":{"type":"string","description":"The reason for the validation failure"}},"required":["message","reason"]},"UpdateAgentDto":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"avatar":{"type":"string"},"isPublic":{"type":"boolean"},"isActive":{"type":"boolean"},"instructions":{"type":"string"},"toolIds":{"type":"array","items":{"type":"string"}},"voice":{"type":"string","description":"Voice to use for the agent"},"sttKeyterms":{"description":"Words or short phrases passed to LiveKit as speech-to-text keyterms","maxItems":50,"type":"array","items":{"type":"string"}},"voiceSpeed":{"type":"number","description":"Voice pace from slow to fast. 0.5 is normal/provider default. Not all voice providers support speed control.","default":0.5,"minimum":0,"maximum":1},"accessToKnowledge":{"type":"boolean","description":"Whether the agent has access to knowledge","default":false},"knowledgeAccessMode":{"type":"string","description":"Knowledge access mode for the agent","enum":["NONE","ALL","TAGS_ONLY"],"default":"NONE"},"knowledgeAccessTags":{"description":"Tags that the agent has access to (only used when knowledgeAccessMode is TAGS_ONLY)","default":[],"type":"array","items":{"type":"string"}},"includePrivateData":{"type":"boolean","description":"Include the user's profile info (owner name, phone, address, DOB, company) in the agent prompt.","default":true},"useBusinessProfile":{"type":"boolean","description":"Include business Q&A presets (hours, pricing, services) from /business-profile in the agent prompt","default":true},"useDetachedReceptionistProfile":{"type":"boolean","description":"Use per-agent receptionist profile fields in prompts instead of only the account profile","default":false},"receptionistPreferredName":{"type":"string","description":"Prompt-facing represented person, practice, or business name"},"receptionistCompanyName":{"type":"string","description":"Prompt-facing represented company or business name"},"receptionistCompanyWebsite":{"type":"string","description":"Prompt-facing represented company website"},"receptionistCompanyDescription":{"type":"string","description":"Prompt-facing represented company description"},"receptionistCompanyIndustry":{"type":"string","description":"Prompt-facing represented company industry"},"receptionistAddress":{"type":"string","description":"Prompt-facing represented business street address"},"receptionistCityName":{"type":"string","description":"Prompt-facing represented business city"},"receptionistStateName":{"type":"string","description":"Prompt-facing represented business state"},"receptionistZipCode":{"type":"string","description":"Prompt-facing represented business ZIP/postal code"},"receptionistTimezone":{"type":"string","description":"Prompt-facing represented business timezone as an IANA timezone name","example":"America/New_York"},"firstMessage":{"type":"string","description":"First message to send from the agent"},"allowOutboundGreetingInterruptions":{"type":"boolean","description":"Whether recipients can interrupt the initial greeting on outbound calls","default":false},"enableVoiceExpressions":{"type":"boolean","description":"Whether the generated voice prompt includes provider-specific expression guidance","default":true},"closingPhrase":{"type":"string","description":"Closing phrase the agent says before ending an inbound call"},"delayAcceptSeconds":{"type":"number","description":"Seconds to wait before the voice agent joins an inbound call.","default":0,"minimum":0,"maximum":20},"voiceRecognition":{"type":"string","description":"Voice recognition mode: EN for English-only (highest accuracy), MULTI for multilingual support","enum":["EN","MULTI"],"default":"EN"},"allowFollowUps":{"type":"boolean","description":"Whether the agent allows follow-ups","default":false},"followUpInstructions":{"type":"string","description":"Custom instructions for smart follow-up messages. When provided, the AI uses these to guide follow-up content."},"gatheringInformationOnIncomingCall":{"type":"boolean","description":"Whether the agent allows gathering information on incoming call","default":false},"maxIncomingCallDurationMinutes":{"type":"number","description":"Max duration of incoming call in minutes","default":3},"maxOutgoingCallDurationMinutes":{"type":"number","description":"Max duration of outgoing call in minutes","default":10},"incomingCallInstructions":{"type":"string","description":"Instructions for the agent on incoming calls"},"welcomingVoiceMailMessageForContacts":{"type":"string","description":"Welcoming voice mail message for contacts"},"welcomingVoiceMailMessageForOthers":{"type":"string","description":"Welcoming voice mail message for others"},"isVoiceMailAgent":{"type":"boolean","description":"Is agent a voice mail agent","default":false},"incomingCallTypingSound":{"type":"boolean","description":"Whether the agent has a typing sound for incoming calls","default":true},"incomingCallBackgroundSound":{"type":"boolean","description":"Whether the agent has a background sound for incoming calls","default":true},"outgoingCallTypingSound":{"type":"boolean","description":"Whether the agent has a typing sound for outgoing calls","default":true},"outgoingCallBackgroundSound":{"type":"boolean","description":"Whether the agent has a background sound for outgoing calls","default":true},"allowIncomingSms":{"type":"boolean","description":"Whether the agent allows incoming SMS messages","default":false},"incomingSmsInstructions":{"type":"string","description":"Instructions for the agent on incoming SMS messages","default":""},"autoRespondToSms":{"type":"boolean","description":"Whether the agent automatically responds to SMS messages","default":true},"smsResponseDelay":{"type":"number","description":"Delay in seconds before responding to SMS messages","default":1},"postCallSmsMessage":{"type":"string","description":"Post-call SMS message to send after incoming calls complete"},"allowRealtimeSms":{"type":"boolean","description":"Whether the agent can send SMS messages during calls via the send_sms tool","default":false},"requireDataConsent":{"type":"boolean","description":"Whether the agent requires data consent before starting calls","default":false},"dataConsentText":{"type":"string","description":"Custom text/instructions for what consent is being requested for"},"enablePostCallActions":{"type":"boolean","description":"Whether to enable post-call outbound actions (scheduling calls after incoming calls)","default":false},"postCallActionInstructions":{"type":"string","description":"Free-form instructions for post-call actions. Example: \"If HVAC emergency, call John at +1234567890 immediately. If plumbing issue, call Mike at +1555555555 in 5 minutes.\""},"behaviorPreset":{"type":"string","description":"Behavior preset for normal agent create/update. New agents are currently created as employee; lead-qualify is manual/admin-only.","default":"employee","enum":["default","employee"]},"strictSpamFilter":{"type":"boolean","description":"Strictly reject incoming calls detected as spam before connecting to the agent","default":false},"valuableCallRule":{"type":"string","description":"Custom rule for detecting valuable incoming calls after each call. Max 300 characters.","nullable":true},"overrideCallerId":{"type":"string","description":"UUID of a verified caller ID to use for outbound calls. Null to clear.","nullable":true}}},"AgentAuditLogEntryDto":{"type":"object","properties":{"id":{"type":"string"},"agentId":{"type":"string"},"agentName":{"type":"string","description":"Agent name at time of change"},"action":{"type":"string","description":"Type of change","example":"UPDATE"},"changes":{"type":"object","description":"Changed fields with from/to values","example":{"name":{"from":"Old Name","to":"New Name"}}},"triggeredBy":{"type":"string","description":"What triggered the change"},"createdAt":{"format":"date-time","type":"string"}},"required":["id","agentId","agentName","action","changes","triggeredBy","createdAt"]},"AgentAuditHistoryResponseDto":{"type":"object","properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/AgentAuditLogEntryDto"}},"total":{"type":"number"}},"required":["entries","total"]},"CreateAgentEvaluationDto":{"type":"object","properties":{"name":{"type":"string"},"prompt":{"type":"string"}},"required":["name","prompt"]},"UpdateAgentEvaluationDto":{"type":"object","properties":{"name":{"type":"string"},"prompt":{"type":"string"}},"required":["name","prompt"]},"CreateAgentDataCollectionDto":{"type":"object","properties":{"dataIdentifier":{"type":"string"},"description":{"type":"string"},"dataType":{"type":"string","enum":["STRING","NUMBER","BOOLEAN","INTEGER","DATE"]}},"required":["dataIdentifier","description","dataType"]},"UpdateAgentDataCollectionDto":{"type":"object","properties":{"dataIdentifier":{"type":"string"},"description":{"type":"string"},"dataType":{"type":"string","enum":["STRING","NUMBER","BOOLEAN","INTEGER","DATE"]}},"required":["dataIdentifier","description","dataType"]},"CreateAgentCalendarDto":{"type":"object","properties":{"calendarId":{"type":"string"},"description":{"type":"string"},"defaultDuration":{"type":"number","default":30},"bufferMinutes":{"type":"number","default":15},"timezone":{"type":"string","default":"UTC"},"workHoursByDay":{"type":"object","description":"Work hours by day in HHMM format (e.g., {\"MONDAY\": [900, 1730]})","example":{"MONDAY":[900,1730],"TUESDAY":[900,1730],"WEDNESDAY":[900,1730],"THURSDAY":[900,1730],"FRIDAY":[900,1730]}},"workDays":{"type":"array","default":["MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY"],"items":{"type":"string","enum":["MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY","SUNDAY"]}},"isActive":{"type":"boolean","default":true,"description":"Allow event creation on this calendar"},"showEventNames":{"type":"boolean","default":false,"description":"Share event names with callers instead of just busy/free times"},"allowDoubleBooking":{"type":"boolean","default":false,"description":"Allow booking overlapping appointments on the same time slot"}},"required":["calendarId","defaultDuration","bufferMinutes","workHoursByDay","workDays","isActive"]},"DuplicateAgentCalendarDto":{"type":"object","properties":{"description":{"type":"string","description":"Description/title shown to the AI (e.g., \"New patient — 40 min\"). Defaults to source description + \" (copy)\"."},"defaultDuration":{"type":"number","description":"Default appointment duration in minutes for this virtual calendar. Minimum 5 — sub-5-minute slots are almost always a misconfiguration and confuse the AI when it reads the value back. Falls back to the source value if omitted."}}},"UpdateAgentCalendarDto":{"type":"object","properties":{"calendarId":{"type":"string"},"description":{"type":"string"},"defaultDuration":{"type":"number","default":30},"bufferMinutes":{"type":"number","default":15},"timezone":{"type":"string","default":"UTC"},"workHoursByDay":{"type":"object","description":"Work hours by day in HHMM format (e.g., {\"MONDAY\": [900, 1730]})","example":{"MONDAY":[900,1730],"TUESDAY":[900,1730],"WEDNESDAY":[900,1730],"THURSDAY":[900,1730],"FRIDAY":[900,1730]}},"workDays":{"type":"array","default":["MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY"],"items":{"type":"string","enum":["MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY","SUNDAY"]}},"isActive":{"type":"boolean","default":true,"description":"Allow event creation on this calendar"},"showEventNames":{"type":"boolean","default":false,"description":"Share event names with callers instead of just busy/free times"},"allowDoubleBooking":{"type":"boolean","default":false,"description":"Allow booking overlapping appointments on the same time slot"}}},"CreateWidgetConfigDto":{"type":"object","properties":{"allowedDomains":{"description":"List of allowed domains for widget embedding","example":["example.com","*.mysite.com"],"type":"array","items":{"type":"string"}},"voiceChatEnabled":{"type":"boolean","description":"Enable the voice widget for this embed key","example":true},"textChatEnabled":{"type":"boolean","description":"Enable the text chat widget for this embed key","example":false},"position":{"type":"string","description":"Widget position on the page","example":"bottom-right","enum":["top-left","top-right","bottom-left","bottom-right"]},"autoConnect":{"type":"boolean","description":"Auto-connect to call when widget loads","example":false},"primaryColor":{"type":"string","description":"Primary color for the widget (hex format)","example":"#4ade80"},"callButtonText":{"type":"string","description":"Text displayed on the call button","example":"Start Call"},"mode":{"type":"string","description":"Widget mode","example":"floating","enum":["floating","inline"]},"greeting":{"type":"string","description":"Greeting headline in idle state","example":"Need help?"},"subtitle":{"type":"string","description":"Subtitle text below greeting","example":"Talk to our AI assistant"},"borderRadius":{"type":"string","description":"Widget border radius","example":"16px"},"showBorder":{"type":"boolean","description":"Show widget border","example":true},"showBranding":{"type":"boolean","description":"Show \"Powered by\" branding","example":true},"size":{"type":"string","description":"Widget size preset","example":"default","enum":["compact","default","large"]},"backgroundColor":{"type":"string","description":"Widget background color (hex format)","example":"#ffffff"},"fontFamily":{"type":"string","description":"Font family for widget text","example":"inherit"},"iconUrl":{"type":"string","description":"Custom icon/avatar URL","example":"https://example.com/avatar.png"},"textColor":{"type":"string","description":"Text color on the call button","example":"#ffffff"}},"required":["allowedDomains"]},"WidgetConfigResponseDto":{"type":"object","properties":{"embedKey":{"type":"string","description":"Embed key","example":"pk_embed_abc123..."},"config":{"type":"object","description":"Widget configuration"}},"required":["embedKey","config"]},"CreateTransferNumberDto":{"type":"object","properties":{"label":{"type":"string","description":"Single lowercase word label (e.g., sales, support)","example":"sales"},"description":{"type":"string","description":"Description explaining when AI should transfer to this number","example":"Use for sales inquiries and new customer questions","maxLength":140},"phoneNumber":{"type":"string","description":"Phone number (will be normalized to E.164)","example":"+1234567890"},"workHours":{"type":"object","description":"Work hours schedule by day (e.g., {MONDAY: [900, 1730]}). Null means 24/7","example":{"MONDAY":[900,1730],"TUESDAY":[900,1730]}},"transferType":{"type":"string","description":"Transfer type: \"warm\" (AI briefs recipient before connecting) or \"cold\" (direct transfer)","default":"warm","enum":["warm","cold"]},"isActive":{"type":"boolean","description":"Whether this transfer number is active","default":true}},"required":["label","description","phoneNumber"]},"TransferNumberResponseDto":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"},"description":{"type":"string"},"phoneNumber":{"type":"string"},"workHours":{"type":"object","nullable":true},"transferType":{"type":"string","enum":["warm","cold"],"default":"warm"},"isActive":{"type":"boolean"},"sortOrder":{"type":"number"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","label","description","phoneNumber","transferType","isActive","sortOrder","createdAt","updatedAt"]},"UpdateTransferNumberDto":{"type":"object","properties":{"label":{"type":"string","description":"Single lowercase word label (e.g., sales, support)","example":"sales"},"description":{"type":"string","description":"Description explaining when AI should transfer to this number","example":"Use for sales inquiries and new customer questions","maxLength":140},"phoneNumber":{"type":"string","description":"Phone number (will be normalized to E.164)","example":"+1234567890"},"workHours":{"type":"object","description":"Work hours schedule by day (e.g., {MONDAY: [900, 1730]}). Null means 24/7","example":{"MONDAY":[900,1730],"TUESDAY":[900,1730]}},"transferType":{"type":"string","description":"Transfer type: \"warm\" (AI briefs recipient before connecting) or \"cold\" (direct transfer)","default":"warm","enum":["warm","cold"]},"isActive":{"type":"boolean","description":"Whether this transfer number is active","default":true}}},"TaskDefinitionDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique task definition identifier"},"slug":{"type":"string","description":"URL-friendly task identifier","example":"schedule-appointment"},"title":{"type":"string","description":"Human-readable task title","example":"Schedule Appointment"},"description":{"type":"string","description":"Instruction for the agent on how to perform this task"},"completionCriteria":{"type":"string","description":"Criteria to determine when the task is completed"},"prerequisiteType":{"type":"string","description":"Prerequisite type required before task can be enabled (e.g. \"calendar_connected\")","nullable":true,"example":"calendar_connected"},"groupName":{"type":"string","description":"Group label for frontend task grouping (e.g. \"Scheduling\", \"Communication\")","nullable":true,"example":"Scheduling"},"userId":{"type":"string","description":"Owner user ID (null = system/global task)","nullable":true},"createdAt":{"format":"date-time","type":"string","description":"Task definition creation timestamp"}},"required":["id","slug","title","description","completionCriteria","createdAt"]},"CreateCustomTaskDto":{"type":"object","properties":{"title":{"type":"string","description":"Task title","example":"Collect insurance info"},"description":{"type":"string","description":"Instruction for the agent on how to perform this task","example":"Ask the caller for their insurance provider"},"completionCriteria":{"type":"string","description":"Criteria to determine when the task is completed","example":"Insurance info is collected"},"groupName":{"type":"string","description":"Group label for frontend grouping","example":"Custom"}},"required":["title","description","completionCriteria"]},"AgentScenarioResponseDto":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"agentId":{"type":"string"},"key":{"type":"string","description":"Generated lower-kebab lookup key"},"title":{"type":"string"},"whenToUse":{"type":"string"},"scenario":{"type":"string"},"isEnabled":{"type":"boolean"},"priority":{"type":"number"},"createdAt":{"format":"date-time","type":"string"},"updatedAt":{"format":"date-time","type":"string"}},"required":["id","userId","agentId","key","title","whenToUse","scenario","isEnabled","priority","createdAt","updatedAt"]},"CreateAgentScenarioDto":{"type":"object","properties":{"title":{"type":"string","description":"Human-readable scenario name","example":"Pricing and quotes","maxLength":80},"whenToUse":{"type":"string","description":"Short selector sentence explaining when this scenario applies","example":"Caller asks for price, cost, estimate, quote, or service level.","maxLength":280},"scenario":{"type":"string","description":"Full Markdown guide for the receptionist","minLength":10,"maxLength":12000},"isEnabled":{"type":"boolean","description":"Whether this scenario is available during calls","default":false}},"required":["title","whenToUse","scenario"]},"ReorderAgentScenariosDto":{"type":"object","properties":{"scenarioIds":{"description":"Ordered array of scenario IDs","type":"array","items":{"type":"string"}}},"required":["scenarioIds"]},"UpdateAgentScenarioDto":{"type":"object","properties":{"title":{"type":"string","description":"Human-readable scenario name","maxLength":80},"whenToUse":{"type":"string","description":"Short selector sentence explaining when this scenario applies","maxLength":280},"scenario":{"type":"string","description":"Full Markdown guide for the receptionist","minLength":10,"maxLength":12000},"isEnabled":{"type":"boolean","description":"Whether this scenario is available during calls"}}},"AgentTaskLinkDto":{"type":"object","properties":{"id":{"type":"string","description":"Unique link identifier"},"agentId":{"type":"string","description":"Agent this task is linked to"},"taskId":{"type":"string","description":"Task definition this link references"},"priority":{"type":"number","description":"Priority (lower = higher priority)","example":0},"createdAt":{"format":"date-time","type":"string","description":"Link creation timestamp"},"task":{"description":"Full task definition","allOf":[{"$ref":"#/components/schemas/TaskDefinitionDto"}]}},"required":["id","agentId","taskId","priority","createdAt","task"]},"EnableTaskDto":{"type":"object","properties":{"priority":{"type":"number","description":"Priority (lower = higher priority)","default":0}},"required":["priority"]},"EmailReceptionistSettingsResponseDto":{"type":"object","properties":{"canUseEmailReceptionist":{"type":"boolean","description":"Whether the current user can use Email Receptionist"},"canUseAiReplies":{"type":"boolean","description":"Whether the current user can use AI draft and auto reply modes"},"requiredPlan":{"type":"string","description":"Minimum plan required for AI draft and auto reply modes","example":"Growth"},"enabled":{"type":"boolean","description":"Whether the address is currently enabled"},"status":{"type":"string","description":"Routing status for the address","enum":["ACTIVE","DISABLED"]},"slug":{"type":"string","description":"Current address local-part","nullable":true,"example":"acme-plumbing"},"domain":{"type":"string","description":"Configured SkipCalls receiving domain","example":"inbound.skipcalls.com"},"address":{"type":"string","description":"Full agent email address","nullable":true,"example":"acme-plumbing@inbound.skipcalls.com"},"replyMode":{"type":"string","description":"Reply behavior for inbound email","enum":["MANUAL","DRAFT","AUTO"]},"incomingEmailInstructions":{"type":"string","description":"Email-specific instructions for future draft generation"},"senderDisplayName":{"type":"string","description":"Display name shown beside the agent email address","example":"Acme Plumbing"},"footerText":{"type":"string","description":"Plain-text footer appended to sent emails","example":"Acme Plumbing\nacme.example\n(555) 010-0200"},"updatedAt":{"format":"date-time","type":"string","description":"Timestamp for the last settings update","nullable":true}},"required":["canUseEmailReceptionist","canUseAiReplies","requiredPlan","enabled","status","domain","replyMode","incomingEmailInstructions","senderDisplayName","footerText"]},"UpdateEmailReceptionistSettingsDto":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable or disable receiving email for this agent","example":true},"slug":{"type":"string","description":"Editable local-part for the agent email address","example":"acme-plumbing"},"replyMode":{"type":"string","description":"Reply behavior for inbound email","enum":["MANUAL","DRAFT","AUTO"],"example":"DRAFT"},"incomingEmailInstructions":{"type":"string","description":"Email-specific instructions for future draft generation","example":"Use a concise professional email tone."},"senderDisplayName":{"type":"string","description":"Display name shown beside the agent email address","nullable":true,"maxLength":80,"example":"Acme Plumbing"},"footerText":{"type":"string","description":"Plain-text footer appended to sent emails","nullable":true,"maxLength":1000,"example":"Acme Plumbing\nacme.example\n(555) 010-0200"}}},"ScheduleCallFromContactDto":{"type":"object","properties":{"goal":{"type":"string","description":"Goal of the call"},"scheduledAt":{"type":"string","description":"ISO 8601 date-time for scheduling the call"},"agentId":{"type":"string","description":"Agent ID to use for the call"},"firstMessage":{"type":"string","description":"First message for the AI to say"},"additionalContext":{"type":"string","description":"Additional context for the call"}},"required":["goal"]},"SendSmsFromContactDto":{"type":"object","properties":{"message":{"type":"string","description":"SMS message content"},"agentId":{"type":"string","description":"Agent ID to use for the SMS conversation"}},"required":["message"]}}}}