{"components":{"responses":{"Error":{"content":{"application/json":{"schema":{"properties":{"error":{"properties":{"code":{"type":"string"},"message":{"type":"string"}},"type":"object"}},"type":"object"}}},"description":"Error"}},"securitySchemes":{"apiKey":{"description":"xco_<id>_<secret>","scheme":"bearer","type":"http"},"session":{"in":"cookie","name":"xco_session","type":"apiKey"}}},"info":{"description":"One API for the console, the customer portal and machine integrations. Every query is scoped to the caller's tenant (operator > reseller > customer); every change is audited. Browser sessions must send X-CSRF-Token on POST, PUT, PATCH and DELETE.","title":"xcoswitch node API","version":"0.1.0"},"openapi":"3.1.0","paths":{"/admin/audit":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Audit log, newest first","tags":["admin"],"x-permission":"view_audit"}},"/admin/audit/verify":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Prove the audit log's hash chain","tags":["admin"],"x-permission":"view_audit"}},"/admin/backups":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Backup settings and history","tags":["admin"],"x-permission":"manage_backups"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Take a backup now","tags":["admin"],"x-permission":"manage_backups"}},"/admin/backups/{id}/restore":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Restore a backup (confirm: RESTORE)","tags":["admin"],"x-permission":"manage_backups"}},"/admin/backups/{id}/verify":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Decrypt and verify a backup","tags":["admin"],"x-permission":"manage_backups"}},"/admin/health":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"System health, taps, providers","tags":["admin"],"x-permission":"view_health"}},"/admin/keys":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"API keys","tags":["admin"],"x-permission":"manage_keys"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Create an API key (secret shown once)","tags":["admin"],"x-permission":"manage_keys"}},"/admin/keys/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Revoke an API key","tags":["admin"],"x-permission":"manage_keys"}},"/admin/tenants":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Tenants in scope","tags":["admin"]}},"/admin/users":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Users in scope","tags":["admin"],"x-permission":"manage_users"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Create a user","tags":["admin"],"x-permission":"manage_users"}},"/admin/users/{id}":{"patch":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Update, disable or reset the password of a user","tags":["admin"],"x-permission":"manage_users"}},"/admin/users/{id}/reset-mfa":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Clear a user's second factor","tags":["admin"],"x-permission":"manage_users"}},"/auth/app/grant":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"A refresh token for an app signed in with a password {device_name}","tags":["auth"]}},"/auth/app/refresh":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"Trade a refresh token for a new session and the next refresh token (rotates; reuse revokes)","tags":["auth"]}},"/auth/app/revoke":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"Sign an app out: revoke its refresh token","tags":["auth"]}},"/auth/app/sso":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"App single sign-on in the system browser {redirect_uri (loopback, or a mobile app scheme such as com.xcobean.phone:/oauth2redirect), code_challenge (S256), state}; ends at that address with a one-time code","tags":["auth"]}},"/auth/app/token":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"Trade {code, code_verifier, redirect_uri, device_name} for a session and a refresh token","tags":["auth"]}},"/auth/config":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"Sign-in options (SSO, second-factor policy)","tags":["auth"]}},"/auth/login":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"Sign in with username and password; may return a second-factor ticket","tags":["auth"]}},"/auth/logout":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"End this session","tags":["auth"]}},"/auth/me":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Who am I: user, tenant, permissions, CSRF token","tags":["auth"]}},"/auth/mfa":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"My second-factor status","tags":["auth"]}},"/auth/mfa/confirm":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Confirm enrolment with a code; returns recovery codes once","tags":["auth"]}},"/auth/mfa/disable":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Turn TOTP off (not for roles that require it)","tags":["auth"]}},"/auth/mfa/enroll":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Start TOTP enrolment: secret, otpauth URI and QR code","tags":["auth"]}},"/auth/mfa/recovery":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Replace my recovery codes","tags":["auth"]}},"/auth/mfa/verify":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"Trade a second-factor ticket and a TOTP or recovery code for a session","tags":["auth"]}},"/auth/oidc/callback":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"OIDC redirect target","tags":["auth"]}},"/auth/oidc/login":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"Start single sign-on (redirect to the OIDC issuer)","tags":["auth"]}},"/auth/password":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Change my password","tags":["auth"]}},"/billing/balance":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Balance and credit limit","tags":["commerce"],"x-permission":"view_billing"}},"/billing/disputes":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Vendor reconciliation","tags":["commerce"],"x-permission":"view_billing"}},"/billing/invoices":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Invoices","tags":["commerce"],"x-permission":"view_billing"}},"/billing/invoices/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One invoice with lines","tags":["commerce"],"x-permission":"view_billing"}},"/callcentre":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Queues with their waiting callers, agents, time conditions and supervisors (engine)","tags":["callcentre"],"x-permission":"view_calls"}},"/callcentre/agents/{id}/disposition":{"put":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Record a wrap-up disposition code for the agent's last queue call","tags":["callcentre"],"x-permission":"control_calls"}},"/callcentre/agents/{id}/status":{"put":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Set an agent available, available-on-demand, on-break or logged-out","tags":["callcentre"],"x-permission":"control_calls"}},"/callcentre/reports/agents":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Agent history in 15 or 30 minute intervals: ACD calls and time, AHT, staffed, busy and break time (operator; JSON or CSV)","tags":["callcentre"],"x-permission":"view_calls"}},"/callcentre/reports/queues":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Queue history in 15 or 30 minute intervals: offered, answered, abandoned, SL, ASR, AHT, ACD (JSON or CSV)","tags":["callcentre"],"x-permission":"view_calls"}},"/callcentre/times/{id}":{"put":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Force a time condition open or closed, or back to its schedule (auto)","tags":["callcentre"],"x-permission":"control_calls"}},"/callcentre/voicemail":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Voicemail messages, newest first (box= one box)","tags":["callcentre"],"x-permission":"listen_recordings"}},"/callcentre/voicemail/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Delete a voicemail message (the box's phones are told)","tags":["callcentre"],"x-permission":"listen_recordings"}},"/callcentre/voicemail/{id}/audio":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Play a voicemail message (WAV, audited)","tags":["callcentre"],"x-permission":"listen_recordings"}},"/callcentre/voicemail/{id}/heard":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Mark a voicemail message heard or new","tags":["callcentre"],"x-permission":"listen_recordings"}},"/callcentre/wallboard":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Live wallboard: per-queue depth, service level, ASR, AHT, agents by state and totals","tags":["callcentre"],"x-permission":"view_calls"}},"/calls":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Live calls","tags":["operations"],"x-permission":"view_calls"}},"/calls/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One live call with SIP ladder and quality","tags":["operations"],"x-permission":"view_calls"}},"/calls/{id}/hangup":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Hang up a live call (CallControl)","tags":["operations"],"x-permission":"control_calls"}},"/calls/{id}/hold":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Hold one side of a live call (music to it, nothing passes)","tags":["operations"],"x-permission":"control_calls"}},"/calls/{id}/mute":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Mute one side of a live call","tags":["operations"],"x-permission":"control_calls"}},"/calls/{id}/supervise":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Listen, whisper or barge: on the engine, ring the supervisor's phone (endpoint), move a session (monitor, mode) or stop it","tags":["operations"],"x-permission":"supervise_calls"}},"/calls/{id}/transfer":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Blind transfer a call to another number","tags":["operations"],"x-permission":"control_calls"}},"/capabilities":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"What this node offers: feature booleans, modes, endpoints, trunks","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/cdrs":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Search call records","tags":["operations"],"x-permission":"view_cdrs"}},"/cdrs/export.csv":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Export call records as CSV","tags":["operations"],"x-permission":"view_cdrs"}},"/cdrs/seals":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Sealed ledger days and their verification","tags":["operations"],"x-permission":"view_cdrs"}},"/cdrs/seals/verify":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Verify one sealed day","tags":["operations"],"x-permission":"view_cdrs"}},"/cdrs/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One call record: trace events, chain status, ladder, recording","tags":["operations"],"x-permission":"view_cdrs"}},"/customers":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Customers and resellers in scope","tags":["commerce"],"x-permission":"view_customers"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Create a customer or reseller","tags":["commerce"],"x-permission":"manage_customers"}},"/customers/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One customer: trunks, limits, balance, portal users","tags":["commerce"],"x-permission":"view_customers"},"patch":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Update a customer (customers may edit their own trunks)","tags":["commerce"],"x-permission":"manage_customers"}},"/customers/{id}/topup":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Credit or debit a balance","tags":["commerce"],"x-permission":"top_up"}},"/dashboard":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"KPIs with sparkline series, top destinations, alarms","tags":["operations"],"x-permission":"view_dashboard"}},"/diagnostics/analyze":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Diagnose one call","tags":["network"],"x-permission":"run_diagnostics"}},"/diagnostics/findings":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Diagnostic findings with platform-specific fixes","tags":["network"],"x-permission":"view_diagnostics"}},"/diagnostics/test-call":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Place a test call (demo diagnostics provider)","tags":["network"],"x-permission":"test_call"}},"/dialer/agents":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Open agent sessions","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/agents/{agent_id}/session":{"delete":{"parameters":[{"in":"path","name":"agent_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Log an agent out","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"},"post":{"parameters":[{"in":"path","name":"agent_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Log an agent in {campaigns[], endpoint, endpoint_address?} -> 201 {session_id, state}","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/agents/{agent_id}/state":{"put":{"parameters":[{"in":"path","name":"agent_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Set ready | not_ready | wrap_up (+reason)","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Recent dialler calls","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}":{"get":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One call record","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/disposition":{"post":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Store the agent's disposition {code, notes, promise, callback_at} on the call record","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/dtmf":{"post":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Send DTMF {digits}","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/hangup":{"post":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Hang up","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/hold":{"post":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Hold the customer","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/mpesa-prompt":{"post":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"M-Pesa prompt on a live call {amount_kes, account, phone?} -> 202 {prompt_id, status: pending, reference}; result as payment.result; 503 not_configured without a platform key","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/mute":{"post":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Mute the agent","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/recording":{"get":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"A fresh signed recording URL {url, expires_at}","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/transcript":{"get":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"The call's transcript {text, language, segments, summary, promise, sentiment, url, expires_at}; 409 not_ready while it runs, 422 transcript_failed","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/transfer":{"post":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Blind transfer {to}","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/unhold":{"post":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Resume","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/calls/{call_id}/unmute":{"post":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Unmute the agent","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/campaigns":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Campaigns in scope with stats","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Create a campaign (CampaignPayload) -> 201 {id, status}","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/campaigns/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One campaign with status and stats","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"},"patch":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Update a campaign (any subset of the create fields)","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/campaigns/{id}/contacts":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Contacts with attempt counts and dialability","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"},"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Upsert up to 500 contacts by external_id -> {accepted, rejected[]}","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/campaigns/{id}/contacts/{external_id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"path","name":"external_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove a contact (never redialled)","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"},"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"path","name":"external_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One contact: attempts, next_attempt_at, skip_reason","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/campaigns/{id}/contacts/{external_id}/dial":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"path","name":"external_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Preview dial for an agent -> 202 {call_id, status}","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/campaigns/{id}/pause":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Pause: no new dials, live calls finish","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/campaigns/{id}/start":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Start (or resume) dialling","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/campaigns/{id}/stop":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Stop for good","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/dnc":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Tenant do-not-call list","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Add numbers [{number, reason}] -> {accepted, rejected[]}","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/dnc/{number}":{"delete":{"parameters":[{"in":"path","name":"number","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove a number","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/events":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Recent events emitted for the tenant (debugging)","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/payments/callback/{tenant}":{"post":{"parameters":[{"in":"path","name":"tenant","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"Xcobean platform settlement callback (X-Xcobean-Signature = hex HMAC-SHA256(raw body, checkout secret)); settles the prompt named by account_ref","tags":["dialer"],"x-status":"live"}},"/dialer/ping":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Test connection: {ok, provider, tenant, version}","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/platform":{"delete":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove a tenant's platform credentials (?tenant=)","tags":["dialer"],"x-permission":"manage_billing","x-status":"live"},"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Whether the tenant has Xcobean platform credentials {configured, key_hint, checkout_secret, mpesa_prompt} (?tenant= for operator staff)","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"},"put":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Set a tenant's platform credentials {tenant?, base_url?, api_key, checkout_secret}; sealed at rest","tags":["dialer"],"x-permission":"manage_billing","x-status":"live"}},"/dialer/recordings/{call_id}/audio":{"get":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"The recording behind a signed link (?exp&sig), audio/wav","tags":["dialer"],"x-status":"live"}},"/dialer/transcripts/{call_id}":{"get":{"parameters":[{"in":"path","name":"call_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"The transcript behind a signed link (?exp&sig), JSON","tags":["dialer"],"x-status":"live"}},"/dialer/webhooks":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Webhook targets (no secrets)","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Register a target {url, secret} -> 201 {id}","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/webhooks/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove a target and its queue","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/webhooks/{id}/deliveries":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Delivery log: attempts, next_at, outcome","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/dialer/webhooks/{id}/test":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Queue a ping event to one target","tags":["dialer"],"x-permission":"use_dialer","x-status":"live"}},"/fraud/alerts":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Fraud and security alerts","tags":["network"],"x-permission":"view_fraud"}},"/fraud/alerts/{id}/ack":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Acknowledge an alert","tags":["network"],"x-permission":"act_fraud"}},"/fraud/engine":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Engine fraud guard: alerts, block and allow lists, counters, per-tenant international calls and spend","tags":["network"],"x-permission":"view_fraud"}},"/fraud/engine/allow":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Never flag or count a number, prefix or range","tags":["network"],"x-permission":"act_fraud"}},"/fraud/engine/block":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Block a number, prefix or range both ways (optionally for one tenant, with an expiry)","tags":["network"],"x-permission":"act_fraud"}},"/fraud/engine/reset":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Forget a tenant's (or every) window, spend and automatic blocks","tags":["network"],"x-permission":"act_fraud"}},"/fraud/engine/unallow":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove a run-time allow entry","tags":["network"],"x-permission":"act_fraud"}},"/fraud/engine/unblock":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove a run-time block","tags":["network"],"x-permission":"act_fraud"}},"/fraud/rules":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Fraud rules","tags":["network"],"x-permission":"view_fraud"}},"/fraud/rules/{id}":{"patch":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Enable, disable or change a rule's action","tags":["network"],"x-permission":"act_fraud"}},"/gsm":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Whether GSM gateways are configured on this node and xcogsm answers","tags":["gsm"],"x-permission":"view_gsm"}},"/gsm/events":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"GSM event log: SIM disabled or enabled, low balance, gateway down or up (?tenant&gateway&limit)","tags":["gsm"],"x-permission":"view_gsm"}},"/gsm/gateways":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"GSM gateways in scope with link state and SIM counts (?tenant)","tags":["gsm"],"x-permission":"view_gsm"}},"/gsm/gateways/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One GSM gateway","tags":["gsm"],"x-permission":"view_gsm"}},"/gsm/gateways/{id}/poll":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Poll the gateway now (audited)","tags":["gsm"],"x-permission":"manage_gsm"}},"/gsm/gateways/{id}/ports":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Every SIM of a gateway: status, network, counters, caps, why it may not be used","tags":["gsm"],"x-permission":"view_gsm"}},"/gsm/gateways/{id}/ports/{port}/{action}":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"path","name":"port","required":true,"schema":{"type":"string"}},{"in":"path","name":"action","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"SIM control, audited: disable {reason}, enable, balance, probe, ussd {code}","tags":["gsm"],"x-permission":"manage_gsm"}},"/gsm/sms":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"SMS through the SIMs, both ways, newest first (?tenant&direction&limit)","tags":["gsm"],"x-permission":"view_gsm"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Send an SMS on the tenant's own SIMs {to, text, gateway?, port?, client_ref?}; 202 with the record","tags":["gsm"],"x-permission":"voice_calls"}},"/gsm/sms/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One SMS record","tags":["gsm"],"x-permission":"view_gsm"}},"/health":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"Liveness: the process answers","tags":["system"]}},"/lists":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Whitelists and blacklists in scope","tags":["lists"],"x-permission":"view_lists"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Create a list","tags":["lists"],"x-permission":"manage_lists"}},"/lists/auto-rules":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Auto-add and auto-reset rules","tags":["lists"],"x-permission":"view_lists"}},"/lists/auto-rules/{id}":{"patch":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Enable or disable an auto-rule","tags":["lists"],"x-permission":"manage_lists"}},"/lists/decide":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Test a call: the decision and which list and entry matched","tags":["lists"],"x-permission":"view_lists"}},"/lists/policies":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Policies per scope: strict, monitor, rejection codes","tags":["lists"],"x-permission":"view_lists"}},"/lists/policies/{id}":{"patch":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Change a policy","tags":["lists"],"x-permission":"manage_lists"}},"/lists/{id}/apply":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Apply a plan (confirm: APPLY)","tags":["lists"],"x-permission":"manage_lists"}},"/lists/{id}/discard":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Discard staged changes","tags":["lists"],"x-permission":"manage_lists"}},"/lists/{id}/entries":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"A page of entries (server-side search and paging)","tags":["lists"],"x-permission":"view_lists"}},"/lists/{id}/export.csv":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Export the whole list as CSV (streamed)","tags":["lists"],"x-permission":"view_lists"}},"/lists/{id}/history":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Applied versions","tags":["lists"],"x-permission":"view_lists"}},"/lists/{id}/import":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Bulk CSV import: validation report, staged only if clean","tags":["lists"],"x-permission":"manage_lists"}},"/lists/{id}/plan":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Plan the staged changes","tags":["lists"],"x-permission":"manage_lists"}},"/lists/{id}/rollback":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Undo the latest apply (confirm: ROLLBACK)","tags":["lists"],"x-permission":"manage_lists"}},"/lists/{id}/stage":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Stage additions and removals","tags":["lists"],"x-permission":"manage_lists"}},"/me/phone":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"My phone: assigned extension, display name, ws_url, sdk_url, whether the softphone is live","tags":["softphone"],"x-status":"live"}},"/me/phone/token":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"A softphone token for my own extension only (rate limited) -> 201 {token, ws_url, ice_servers, extension}","tags":["softphone"],"x-status":"live"}},"/me/views":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"My saved table views","tags":["console"]},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Save a table view","tags":["console"]}},"/me/views/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Delete a saved view","tags":["console"]}},"/meet/{code}":{"get":{"parameters":[{"in":"path","name":"code","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"What a guest link points at: title, whether a PIN is needed","tags":["meetings"]}},"/meet/{code}/join":{"post":{"parameters":[{"in":"path","name":"code","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"Join as a guest with a name (and PIN): returns the media server URL and a token","tags":["meetings"]}},"/meetings":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Meetings in scope","tags":["meetings"],"x-permission":"view_meetings"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Schedule a meeting, or start an instant one","tags":["meetings"],"x-permission":"manage_meetings"}},"/meetings/webhook":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"LiveKit webhooks (JWT in Authorization, signed with the API secret)","tags":["meetings"]}},"/meetings/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"End and delete a meeting","tags":["meetings"],"x-permission":"manage_meetings"},"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One meeting","tags":["meetings"],"x-permission":"view_meetings"},"patch":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Change title, schedule, join or recording policy","tags":["meetings"],"x-permission":"manage_meetings"}},"/meetings/{id}/dial-in":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Phone numbers, PIN and SIP URI for dialling in","tags":["meetings"],"x-permission":"view_meetings"}},"/meetings/{id}/dial-out":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Ring a phone number into the meeting","tags":["meetings"],"x-permission":"manage_meetings"}},"/meetings/{id}/end":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"End the meeting for everyone","tags":["meetings"],"x-permission":"manage_meetings"}},"/meetings/{id}/guest-link":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Rotate the guest link expiry and optionally the PIN","tags":["meetings"],"x-permission":"manage_meetings"}},"/meetings/{id}/join":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"A join token for the signed-in user (starts the room if the host)","tags":["meetings"],"x-permission":"view_meetings"}},"/meetings/{id}/message":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Send a host announcement to the room","tags":["meetings"],"x-permission":"manage_meetings"}},"/meetings/{id}/participants":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Who is in the room now, and who was","tags":["meetings"],"x-permission":"view_meetings"}},"/meetings/{id}/participants/{identity}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"path","name":"identity","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove a participant","tags":["meetings"],"x-permission":"manage_meetings"}},"/meetings/{id}/participants/{identity}/mute":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"path","name":"identity","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Mute or unmute a participant's audio or video","tags":["meetings"],"x-permission":"manage_meetings"}},"/meetings/{id}/quality":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"A participant reports its own connection quality (bearer: its join token)","tags":["meetings"]}},"/meetings/{id}/recording/start":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Start recording (grid or speaker layout, optionally audio only)","tags":["meetings"],"x-permission":"manage_meetings"}},"/meetings/{id}/recording/stop":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Stop the running recording","tags":["meetings"],"x-permission":"manage_meetings"}},"/meetings/{id}/recordings":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Recordings of this meeting","tags":["meetings"],"x-permission":"view_meetings"}},"/meetings/{id}/trace":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"The meeting's immutable record, its usage and rating","tags":["meetings"],"x-permission":"view_meetings"}},"/modules":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Modules this caller may open, and which provider answers each","tags":["console"]}},"/notifications":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Notification channels (webhook, Telegram)","tags":["admin"],"x-permission":"manage_notifications"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Add a channel","tags":["admin"],"x-permission":"manage_notifications"}},"/notifications/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove a channel","tags":["admin"],"x-permission":"manage_notifications"},"put":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Update a channel","tags":["admin"],"x-permission":"manage_notifications"}},"/notifications/{id}/test":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Send a test notification","tags":["admin"],"x-permission":"manage_notifications"}},"/numbering/mnp":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Number portability: imported table, cache, lookups, provider counters","tags":["network"],"x-permission":"view_sbc"}},"/numbering/mnp/flush":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Drop the cached provider answers","tags":["network"],"x-permission":"apply_sbc"}},"/numbering/mnp/import":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Import ported numbers (CSV number,network[,routing_number]; replace or merge)","tags":["network"],"x-permission":"apply_sbc"}},"/numbering/mnp/lookup/{number}":{"get":{"parameters":[{"in":"path","name":"number","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Look a number's network up as a call would (table, cache, providers)","tags":["network"],"x-permission":"view_sbc"}},"/numbering/stir":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"STIR/SHAKEN: signing, trusted roots, verification counters","tags":["network"],"x-permission":"view_sbc"}},"/numbers":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"DID inventory","tags":["commerce"],"x-permission":"view_numbers"}},"/numbers/{number}/assign":{"post":{"parameters":[{"in":"path","name":"number","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Assign a number to a customer or back to a pool","tags":["commerce"],"x-permission":"manage_numbers"}},"/openapi.json":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"This document","tags":["system"]}},"/prov/{token}/{file}":{"get":{"parameters":[{"in":"path","name":"token","required":true,"schema":{"type":"string"}},{"in":"path","name":"file","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"security":[],"summary":"For phones: a configuration file under a tenant's provisioning URL. HTTP Digest per device (or a trusted source network); answers the file, 401 with a challenge, 404 or 429, never JSON","tags":["provisioning"]}},"/provisioning":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Whether provisioning is configured: public URL, node defaults, vendors, redirect clouds","tags":["provisioning"],"x-permission":"view_provisioning"}},"/provisioning/actions/{action}":{"post":{"parameters":[{"in":"path","name":"action","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"The same action on a tenant's phones {tenant?, site?, macs?}: paced, at most 100 phones, each listed accepted, refused, no_answer or unavailable (audited)","tags":["provisioning"],"x-permission":"control_phones"}},"/provisioning/devices":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Desk phones in scope (?tenant=&state=); never passwords or hashes","tags":["provisioning"],"x-permission":"view_provisioning"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Add a phone {mac, tenant?, label?, vendor?, model?, lines?, keys?, settings?} -> 201 {device, new_passwords (shown once)}","tags":["provisioning"],"x-permission":"manage_provisioning"}},"/provisioning/devices/import":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Bulk add {tenant?, csv: mac,label,model,vendor,extension,display_name} -> {created, skipped, new_passwords}","tags":["provisioning"],"x-permission":"manage_provisioning"}},"/provisioning/devices/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove a phone","tags":["provisioning"],"x-permission":"manage_provisioning"},"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One phone by MAC","tags":["provisioning"],"x-permission":"view_provisioning"},"patch":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Change {label?, vendor?, model?, lines?, keys?, settings?, claim?}; lines replace the list, passwords kept per index","tags":["provisioning"],"x-permission":"manage_provisioning"}},"/provisioning/devices/{id}/actions/{action}":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"path","name":"action","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remote action now: resync, reboot or firmware {firmware_url?}, by SIP NOTIFY from this node's registrar; 409 unavailable when the phone registers elsewhere or not at all (audited)","tags":["provisioning"],"x-permission":"control_phones"}},"/provisioning/devices/{id}/cloud":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Ask the vendor's redirect cloud (Yealink RPS) where this MAC points","tags":["provisioning"],"x-permission":"view_provisioning"}},"/provisioning/devices/{id}/cloud/bind":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Bind the MAC at the redirect cloud to the tenant URL with the phone's credentials","tags":["provisioning"],"x-permission":"manage_provisioning"}},"/provisioning/devices/{id}/cloud/unbind":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove the MAC from our account at the redirect cloud","tags":["provisioning"],"x-permission":"manage_provisioning"}},"/provisioning/devices/{id}/credentials":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"The phone's own provisioning credentials and admin password, and the URL with credentials (logged)","tags":["provisioning"],"x-permission":"manage_provisioning"}},"/provisioning/devices/{id}/lines/{index}/password":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"path","name":"index","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Generate a line password (shown once) or set {password} for a line on another PBX","tags":["provisioning"],"x-permission":"manage_provisioning"}},"/provisioning/devices/{id}/preview":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"The rendered files with every secret replaced by ********, and render warnings","tags":["provisioning"],"x-permission":"view_provisioning"}},"/provisioning/devices/{id}/reprovision":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"New revision of the files; the phone takes it at its next periodic check","tags":["provisioning"],"x-permission":"manage_provisioning"}},"/provisioning/tenant":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"The tenant's provisioning URL and DHCP option 66 value, claim and trusted networks (?tenant=)","tags":["provisioning"],"x-permission":"view_provisioning"},"put":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Set {tenant?, allow_claim?, trusted_networks?, sip_server?}","tags":["provisioning"],"x-permission":"manage_provisioning"}},"/provisioning/tenant/rotate":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"New provisioning URL for {tenant?}; the old one stops working","tags":["provisioning"],"x-permission":"manage_provisioning"}},"/rates/compare":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Vendor deck comparison per destination","tags":["commerce"],"x-permission":"view_rates"}},"/rates/decks":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Rate decks visible to the caller","tags":["commerce"],"x-permission":"view_rates"}},"/rates/decks/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One deck with its rows","tags":["commerce"],"x-permission":"view_rates"}},"/rates/decks/{id}/publish":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Publish a validated upload","tags":["commerce"],"x-permission":"manage_rates"}},"/rates/decks/{id}/validate":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Upload a CSV: validation report and diff, nothing published","tags":["commerce"],"x-permission":"manage_rates"}},"/recordings":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Search recordings","tags":["operations"],"x-permission":"listen_recordings"}},"/recordings/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One recording","tags":["operations"],"x-permission":"listen_recordings"}},"/recordings/{id}/audio":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Play a recording (audited)","tags":["operations"],"x-permission":"listen_recordings"}},"/routing/groups":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Destination groups and strategies","tags":["commerce"],"x-permission":"view_routing"}},"/routing/groups/{id}":{"patch":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Change a group's strategy","tags":["commerce"],"x-permission":"manage_routing"}},"/routing/test":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Test a number: ranked routes and why, plus the matching xcoroute route","tags":["commerce"],"x-permission":"view_routing"}},"/sbc":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Current routing file, its origin, check result and structure","tags":["network"],"x-permission":"view_sbc"}},"/sbc/apply":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Apply a plan (confirm: APPLY); refused if anything changed since","tags":["network"],"x-permission":"apply_sbc"}},"/sbc/check":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Check a routing file (errors and warnings)","tags":["network"],"x-permission":"view_sbc"}},"/sbc/draft":{"put":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Save a draft routing file","tags":["network"],"x-permission":"plan_sbc"}},"/sbc/health":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Gateway health checks (engine target): up, down or unknown, last response","tags":["network"],"x-permission":"view_sbc"}},"/sbc/history":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Applied versions, who applied them","tags":["network"],"x-permission":"view_sbc"}},"/sbc/plan":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Plan: the exact file diff against the switch configuration","tags":["network"],"x-permission":"plan_sbc"}},"/sbc/rollback":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Roll back the latest apply (confirm: ROLLBACK)","tags":["network"],"x-permission":"apply_sbc"}},"/search":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Global search: customers, numbers, live calls, call records","tags":["console"]}},"/siptrace":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Search the engine's SIP capture by Call-ID, number, time, tenant and response code","tags":["operations"],"x-permission":"view_diagnostics"}},"/siptrace/{tenant}/{call}":{"get":{"parameters":[{"in":"path","name":"tenant","required":true,"schema":{"type":"string"}},{"in":"path","name":"call","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One call's SIP messages (masked) and the ladder's participants","tags":["operations"],"x-permission":"view_diagnostics"}},"/siptrace/{tenant}/{call}/pcap":{"get":{"parameters":[{"in":"path","name":"tenant","required":true,"schema":{"type":"string"}},{"in":"path","name":"call","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One call's SIP messages as a pcap (SIP over UDP, for Wireshark)","tags":["operations"],"x-permission":"view_diagnostics"}},"/siptrace/{tenant}/{call}/text":{"get":{"parameters":[{"in":"path","name":"tenant","required":true,"schema":{"type":"string"}},{"in":"path","name":"call","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One call's SIP messages as text","tags":["operations"],"x-permission":"view_diagnostics"}},"/softphone/tokens":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Short-lived softphone token {agent_id, display_name} -> 201 {token, expires_at, ws_url, ice_servers}","tags":["softphone"],"x-permission":"use_dialer","x-status":"live"}},"/stream":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Server-sent events: KPIs and live calls every 2 s","tags":["operations"],"x-permission":"view_dashboard"}},"/test-calls":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Test calls placed, newest first, with ladder, timings and verdict","tags":["network"],"x-permission":"test_call"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Place a judged test call through the traffic engine (to, via|trunk, scenario|expect, duration_secs, record); progress on /stream","tags":["network"],"x-permission":"test_call"}},"/test-calls/scenarios":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Named test-call scenarios: what the far end does and what to expect","tags":["network"],"x-permission":"test_call"}},"/test-calls/suite":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Run every scenario against the lab far end or a switch (operators)","tags":["network"],"x-permission":"run_diagnostics"}},"/test-calls/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One test call with its full report","tags":["network"],"x-permission":"test_call"}},"/test-calls/{id}/recording":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"The answered audio of a recorded test call (WAV)","tags":["network"],"x-permission":"test_call"}},"/vendors":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Vendors, gateways, capacity and quality","tags":["commerce"],"x-permission":"view_vendors"}},"/vendors/{id}/status":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Enable or disable a vendor","tags":["commerce"],"x-permission":"manage_vendors"}},"/voice/applications":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Applications: named sets of flow URLs","tags":["voice"],"x-permission":"view_calls"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Create an application","tags":["voice"],"x-permission":"manage_voice"}},"/voice/applications/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Delete an application","tags":["voice"],"x-permission":"manage_voice"},"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One application and the numbers using it","tags":["voice"],"x-permission":"view_calls"},"put":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Update an application","tags":["voice"],"x-permission":"manage_voice"}},"/voice/calls":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"List calls (newest first); filter by status","tags":["voice"],"x-permission":"view_calls"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Place an outbound call: to, from, flow_url or inline flow, amd, status_callback, timeout_secs, record","tags":["voice"],"x-permission":"voice_calls"}},"/voice/calls/inbound":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Simulate an inbound call on a configured number (demo switch)","tags":["voice"],"x-permission":"voice_calls"}},"/voice/calls/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One call: status, price, verbs run, recordings, transcriptions","tags":["voice"],"x-permission":"view_calls"}},"/voice/calls/{id}/hangup":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Hang up a live call","tags":["voice"],"x-permission":"voice_calls"}},"/voice/calls/{id}/hold":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Hold or resume the caller ({\"on\": true})","tags":["voice"],"x-permission":"voice_calls"}},"/voice/calls/{id}/mute":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Mute or unmute the caller ({\"on\": true})","tags":["voice"],"x-permission":"voice_calls"}},"/voice/calls/{id}/redirect":{"post":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Send a live call to a new flow URL","tags":["voice"],"x-permission":"voice_calls"}},"/voice/flows/validate":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Validate a flow document (JSON or XML); errors carry line and verb","tags":["voice"]}},"/voice/host-calls":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Host approval call: read a script (prompt, keys, retries, language) to a person and post the key pressed to callback_url; idempotency_key repeats return the first call","tags":["voice"],"x-permission":"voice_calls"}},"/voice/keys":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"API keys for this tenant with rate limits","tags":["voice"],"x-permission":"manage_keys"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Create a developer API key with an optional rate_limit_per_min","tags":["voice"],"x-permission":"manage_keys"}},"/voice/keys/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Revoke a key","tags":["voice"],"x-permission":"manage_keys"}},"/voice/log":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Recent voice API requests","tags":["voice"],"x-permission":"view_calls"}},"/voice/numbers":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Numbers and their inbound flow configuration","tags":["voice"],"x-permission":"view_numbers"}},"/voice/numbers/{number}":{"delete":{"parameters":[{"in":"path","name":"number","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Remove a number's configuration","tags":["voice"],"x-permission":"manage_voice"},"put":{"parameters":[{"in":"path","name":"number","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Set a number's flow_url, method, sms_url, application, status_callback","tags":["voice"],"x-permission":"manage_voice"}},"/voice/recordings":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Recordings made by record and dial verbs","tags":["voice"],"x-permission":"listen_recordings"}},"/voice/recordings/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Delete a recording","tags":["voice"],"x-permission":"manage_voice"},"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One recording and its audio URL","tags":["voice"],"x-permission":"listen_recordings"}},"/voice/recordings/{id}/audio":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"The audio (audited)","tags":["voice"],"x-permission":"listen_recordings"}},"/voice/signing-secret":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"The tenant's webhook signing secret (audited)","tags":["voice"],"x-permission":"manage_voice"}},"/voice/signing-secret/rotate":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Rotate the signing secret","tags":["voice"],"x-permission":"manage_voice"}},"/voice/sms":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"List messages","tags":["voice"],"x-permission":"view_calls"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Send an SMS through the SMS router","tags":["voice"],"x-permission":"voice_calls"}},"/voice/sms/inbound":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"An inbound SMS for a number: stored and forwarded to its sms_url","tags":["voice"],"x-permission":"voice_calls"}},"/voice/sms/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One message","tags":["voice"],"x-permission":"view_calls"}},"/voice/transcriptions":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Transcriptions of recordings","tags":["voice"],"x-permission":"listen_recordings"}},"/voice/transcriptions/{id}":{"get":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"One transcription","tags":["voice"],"x-permission":"listen_recordings"}},"/voice/webhooks":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Recent webhook deliveries with status and attempts","tags":["voice"],"x-permission":"view_calls"}},"/wfm/adherence":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Adherence per agent over a range: rostered time spent as rostered, from the agent-state history (operator)","tags":["callcentre"],"x-permission":"view_calls"}},"/wfm/forecast":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"WFM forecast for a day: offered volume and Erlang C agents required per interval, against the roster (operator)","tags":["callcentre"],"x-permission":"view_calls"}},"/wfm/shifts":{"get":{"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"The WFM roster: shifts in a range, optionally for one agent (operator)","tags":["callcentre"],"x-permission":"view_calls"},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Add a shift or replace one by id; overlapping blocks are refused (operator, audited)","tags":["callcentre"],"x-permission":"control_calls"}},"/wfm/shifts/{id}":{"delete":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK. Module responses carry `source`: `live` or `demo`."},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"summary":"Delete a shift (operator, audited)","tags":["callcentre"],"x-permission":"control_calls"}}},"security":[{"session":[]},{"apiKey":[]}],"servers":[{"url":"/api/v1"}],"webhooks":{"agent.state":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"agent_id, state: ready|not_ready|wrap_up|on_call, reason?, call_id?","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"agent.state","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"Every agent state change, including the node's own","x-status":"live"}},"call.answered":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"call_id, answered_by: human|machine|unknown, amd: {verdict, confidence, log_odds, elapsed_ms, evidence[{kind, weight, note}]}","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"call.answered","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"The far end answered; AMD verdict","x-status":"live"}},"call.connected":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"call_id, agent_id, external_id, campaign_id, number, data (the contact's opaque data)","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"call.connected","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"Bridged to the agent","x-status":"live"}},"call.dialing":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"call_id, campaign_id, external_id, number, agent_id?, attempt, caller_id","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"call.dialing","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"The customer leg is being placed","x-status":"live"}},"call.dtmf":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"call_id, digit","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"call.dtmf","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"The customer pressed a key","x-status":"live"}},"call.ended":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"call_id, campaign_id, external_id, duration, talk_time, sip_code, hangup_cause, disposition: answered|no_answer|busy|failed|machine|abandoned|cancelled, answered_by?, agent_id?, ended_by: customer|agent|system, transferred_to?","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"call.ended","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"The call is over","x-status":"live"}},"call.ringing":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"call_id","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"call.ringing","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"180/183 from the far end","x-status":"live"}},"campaign.state":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"campaign_id, status, reason?, stats?","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"campaign.state","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"start, pause, stop, or finished (reason)","x-status":"live"}},"payment.result":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"call_id, status: success|failed|cancelled, amount_kes, receipt?, account, prompt_id, reference, reason?","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"payment.result","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"Outcome of an M-Pesa prompt, once per prompt (platform callback, or polling; cancelled with reason timeout after 10 min)","x-status":"live"}},"ping":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"webhook","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"ping","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"POST /dialer/webhooks/{id}/test","x-status":"live"}},"recording.ready":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"call_id, url (signed, 24 h), expires_at, duration","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"recording.ready","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"The recording is closed","x-status":"live"}},"transcript.failed":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"call_id, reason, attempts","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"transcript.failed","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"Transcription gave up after three attempts","x-status":"live"}},"transcript.ready":{"post":{"parameters":[{"in":"header","name":"X-XcoSwitch-Timestamp","required":true,"schema":{"type":"string"}},{"description":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + body))","in":"header","name":"X-XcoSwitch-Signature","required":true,"schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Event","schema":{"type":"string"}},{"in":"header","name":"X-XcoSwitch-Delivery","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"data":{"description":"call_id, text, language, summary|null, promise: {amount_kes, date|null}|null, promise_source: model|rules|none, sentiment: positive|neutral|negative|unknown, engine {stt, summary}, url (signed, 24 h), expires_at","type":"object"},"event_id":{"maxLength":64,"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"tenant":{"description":"the xcoswitch tenant id","type":"string"},"type":{"const":"transcript.ready","type":"string"}},"required":["event_id","type","occurred_at","tenant","data"],"type":"object"}}}},"responses":{"200":{"description":"duplicate event_id, ignored"},"202":{"description":"accepted"},"401":{"description":"bad signature or stale timestamp; retried"}},"summary":"Transcript, summary and promise flag after a recorded call","x-status":"live"}}},"x-contract":{"document":"docs/collect-integration.md","errors":{"planned":"501 not_implemented + task","shape":{"error":{"code":"string","message":"string"}},"unsupported_here":"501 not_supported"},"name":"xcoswitch <-> CollectPoa dialler contract v1","webhook_headers":{"idempotency":"event_id","max_skew_secs":300,"retry":"non-2xx or transport error: backoff 1s doubling, capped 1h, for 24h, in order per target","scheme":"sha256=hex(HMAC-SHA256(secret, timestamp + '.' + raw body))","signature":"X-XcoSwitch-Signature","timestamp":"X-XcoSwitch-Timestamp"}}}