Browse the documentation

Documentation

API reference

The Open Voice Shield REST API is served under /api on your platform host and authenticates with either a bearer token or an API key sent as X-API-Key. This page lists every customer-facing endpoint with its parameters, request and response shapes and the errors it raises.

Base URL and versioning#

Every path below is served under /api on your platform host, so GET /calls is GET https://your-ovs-host.example/api/calls. The interactive explorer is at /api/docs and the machine-readable schema at /api/openapi.json — that schema is what this page is generated from, so the two cannot disagree.

Requests and responses are JSON unless a row below says otherwise. Timestamps are UTC, ISO 8601. Identifiers are UUIDs. Lists take limit and offset and return a total, so you can page without losing rows.

Authentication#

There are two ways to authenticate, and they are interchangeable on every endpoint marked Bearer or API key:

Bearer token
Authorization: Bearer <access token>. You get one from POST /auth/login or POST /auth/signup. It is short-lived; a browser session renews it with POST /auth/refresh. Use this for a person at a screen.
API key
X-API-Key: <key>. It does not expire and is the right credential for a script, a switch integration or a scheduled job.

Create a key with POST /auth/api-keys as the account owner. The full key is in that one response and is stored only as a hash — it can never be shown again. Lose it and you mint a new one and revoke the old. A key acts as the user who minted it: revoke it with DELETE /auth/api-keys/{key_id}, or deactivate that user, and it stops working at once.

Owner-only endpoints

Anything that mints or revokes a credential, or that changes who can sign in, is owner-only. A member session answers 403 owner_required. Those rows are marked owner only in the Auth column.

Errors#

An error is a JSON body with a detail field and one of the status codes below. The Errors column on each endpoint lists only what that handler raises: 401 on a bad or missing credential and 422 on a malformed parameter apply everywhere and are not repeated row by row.

Status codes used across the API.
CodeMeansWhat to do
401Not authenticatedThe token expired, the key is wrong or was revoked. Refresh or re-issue.
403ForbiddenThe credential is valid but not allowed here — a member on an owner-only route, or a suspended account.
404Not foundNo such record on your account. Another account's record is a 404, never a 403.
409ConflictThe request contradicts what exists — a duplicate, or a state that does not allow it.
422Validation errorA field is missing or out of range. The body names the field.
429Too many requestsBack off. Retry-After carries the number of seconds.

Authentication, sessions and keys#

Create an account, sign in, rotate a session and mint the API keys your own systems use. A key is minted by a signed-in owner and is shown once.

sign in, then mint a key — the key is shown once

API=https://your-ovs-host.example

TOKEN=$(curl -s -X POST $API/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"ops@acme.example","password":"correct-horse-battery"}' \
  | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')

curl -s -X POST $API/api/auth/api-keys \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"name":"noc-integration"}'
# 201 {"id":"...","name":"noc-integration","prefix":"ovs_...","key":"ovs_...","revoked_at":null}
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
GET /auth/api-keys List the account keys, by prefix. The secret is not included. Bearer or API key
POST /auth/api-keys Mint an API key. The full key is in the response and is never shown again. Bearer or API key, owner only
DELETE /auth/api-keys/{key_id} Revoke a key immediately. Bearer or API key, owner only
POST /auth/change-password Set a new password and end every other session. Bearer or API key
GET /auth/config What the sign-in and sign-up screens need to know, before anyone signs in. None
POST /auth/login Sign in with e-mail and password. Returns a token, or a second-factor challenge when a passkey is registered. None
POST /auth/login/passkey Complete a two-factor sign-in by answering the passkey challenge from the password step. None
POST /auth/logout End this browser session and clear its refresh cookie. Refresh cookie + X-Requested-With
POST /auth/logout-all Sign out of every browser session at once. API keys keep working. Bearer or API key
GET /auth/me The account behind the current credentials. Bearer or API key
GET /auth/passkeys List the passkeys registered on the account. Bearer or API key, owner only
DELETE /auth/passkeys/{passkey_id} Remove a passkey. Removing the last one turns two-factor sign-in off. Bearer or API key, owner only
PATCH /auth/passkeys/{passkey_id} Rename a registered passkey. Bearer or API key, owner only
POST /auth/passkeys/register/begin Start registering a passkey: returns the options the browser needs. Bearer or API key, owner only
POST /auth/passkeys/register/complete Finish registering a passkey and turn on two-factor sign-in. Bearer or API key, owner only
POST /auth/refresh Exchange the refresh cookie for a new access token and rotate the cookie. Refresh cookie + X-Requested-With
POST /auth/signup Create an account and return a first access token. None
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
GET /auth/api-keys 200 ApiKeyOut[]
POST /auth/api-keys name string, required 201 ApiKeyCreated 403 owner_required
DELETE /auth/api-keys/{key_id} key_id uuid, required 204 No content 403 owner_required
404 API key not found
POST /auth/change-password current_password string, required
new_password string, required
204 No content 400 invalid_current_password
422 new_password must differ from the current password
GET /auth/config 200 AuthConfigOut
POST /auth/login email email, required
password string, required
200 TokenResponse, or TwoFactorRequired when a passkey is registered 401 Invalid email or password
403 Account suspended
429 Too many requests
POST /auth/login/passkey login_token string, required
assertion object, required
200 TokenResponse 401 invalid_login
POST /auth/logout 204 No content
POST /auth/logout-all 204 No content
GET /auth/me 200 CustomerOut
GET /auth/passkeys 200 PasskeyOut[] 403 owner_required
DELETE /auth/passkeys/{passkey_id} passkey_id uuid, required 204 No content 403 owner_required
404 Passkey not found
PATCH /auth/passkeys/{passkey_id} passkey_id uuid, required name string, required 200 PasskeyOut 403 owner_required
404 Passkey not found
POST /auth/passkeys/register/begin 200 PasskeyRegisterBeginOut 403 owner_required
POST /auth/passkeys/register/complete credential object, required
state string, required
name string or null
201 PasskeyOut 400 Bad request
403 owner_required
409 passkey_already_registered
POST /auth/refresh 200 TokenResponse 401 Not authenticated
POST /auth/signup email email, required
password string, required
company string or null
201 SignupResponse 403 Signup is disabled
409 Email already registered
429 Too many requests

Users on your account#

Every person who signs in to your account has a user row. Owners invite, rename and deactivate; members can read the list.

invite a member (owner only)

curl -s -X POST $API/api/customer/users \
  -H "X-API-Key: $OVS_KEY" -H 'Content-Type: application/json' \
  -d '{"email":"analyst@acme.example","name":"Night shift"}'
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
GET /customer/users List the people who can sign in to the account, owner first. Bearer or API key
POST /customer/users Invite a member. They receive a temporary password and must change it on first sign-in. Bearer or API key, owner only
PATCH /customer/users/{user_id} Rename, deactivate or reactivate a member. The owner cannot be deactivated. Bearer or API key, owner only
POST /customer/users/{user_id}/resend-invite Issue a new temporary password and re-send the invitation. The old one stops working. Bearer or API key, owner only
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
GET /customer/users 200 CustomerUserList
POST /customer/users email email, required
name string or null
201 CustomerUserInvited 403 owner_required
409 Email already registered
PATCH /customer/users/{user_id} user_id uuid, required name string or null
is_active boolean or null
200 CustomerUserOut 400 cannot_deactivate_owner
403 owner_required
404 User not found
POST /customer/users/{user_id}/resend-invite user_id uuid, required 200 CustomerUserInvited 400 cannot_reset_owner
403 owner_required
404 User not found

Trunk, whitelist, destinations and routing#

The connection itself: the address your switch sends to, the source addresses allowed to send, where a call goes next, and the prefix rules that choose between destinations.

whitelist the address your switch sends from

curl -s $API/api/customer/network-info -H "X-API-Key: $OVS_KEY"

curl -s -X POST $API/api/customer/ips \
  -H "X-API-Key: $OVS_KEY" -H 'Content-Type: application/json' \
  -d '{"cidr":"203.0.113.7/32","label":"Toronto SBC"}'
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
GET /customer/destinations Where analyzed calls are handed on to. Bearer or API key
POST /customer/destinations Add a destination — the SBC, PBX or carrier the call was already going to. Bearer or API key
DELETE /customer/destinations/{dest_id} Remove a destination. Bearer or API key
PATCH /customer/destinations/{dest_id} Change a destination, or make it the default. Bearer or API key
GET /customer/ips The source addresses allowed to send you traffic. Bearer or API key
POST /customer/ips Whitelist a source address or range. Traffic from anywhere else is rejected. Bearer or API key
DELETE /customer/ips/{ip_id} Remove a whitelisted address. Bearer or API key
GET /customer/network-info The host, port and transports your switch sends the INVITE to. Bearer or API key
GET /customer/routing-rules The prefix rules that choose a destination. Bearer or API key
POST /customer/routing-rules Route a dialled prefix to a specific destination. Bearer or API key
DELETE /customer/routing-rules/{rule_id} Remove a prefix rule. Bearer or API key
PATCH /customer/routing-rules/{rule_id} Change a prefix rule, its priority or its destination. Bearer or API key
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
GET /customer/destinations 200 DestinationOut[]
POST /customer/destinations host string, required
port integer, default 5060
transport "udp" | "tcp" | "tls", default "udp"
is_default boolean, default false
label string or null
kind "sip" | "voice_ai", default "sip"
provider string or null
agent_id string or null
config object or null
tech_prefix string or null
201 DestinationOut 409 Maximum number of destinations reached
DELETE /customer/destinations/{dest_id} dest_id uuid, required 204 No content 404 Destination not found
PATCH /customer/destinations/{dest_id} dest_id uuid, required host string or null
port integer or null
transport "udp" | "tcp" | "tls" or null
is_default boolean or null
label string or null
kind "sip" | "voice_ai" or null
provider string or null
agent_id string or null
config object or null
tech_prefix string or null
200 DestinationOut 404 Destination not found
GET /customer/ips 200 IpOut[]
POST /customer/ips cidr string, required
label string or null
destination_id uuid or null
enabled boolean, default true
201 IpOut 404 Destination not found
409 CIDR already whitelisted
422 Validation error
503 Whitelist busy, retry
DELETE /customer/ips/{ip_id} ip_id uuid, required 204 No content 404 IP entry not found
GET /customer/network-info 200 NetworkInfoOut
GET /customer/routing-rules 200 RoutingRuleOut[]
POST /customer/routing-rules prefix string, required
destination_id uuid, required
enabled boolean, default true
priority integer, default 100
label string or null
201 RoutingRuleOut 404 Destination not found
409 Conflict
DELETE /customer/routing-rules/{rule_id} rule_id uuid, required 204 No content 404 Routing rule not found
PATCH /customer/routing-rules/{rule_id} rule_id uuid, required prefix string or null
destination_id uuid or null
enabled boolean or null
priority integer or null
label string or null
200 RoutingRuleOut 404 Destination not found
409 Conflict

Calls and analysis#

Every call that traversed the platform, its verdict, its transcript, its recording, its SIP flow and a self-contained evidence bundle.

the high-risk calls of the last day, then one verdict

curl -s "$API/api/calls?min_probability=70&limit=20" -H "X-API-Key: $OVS_KEY"

curl -s $API/api/calls/$CALL_ID/analysis -H "X-API-Key: $OVS_KEY"
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
GET /calls Search your calls by time, status, verdict or your own reference. Bearer or API key
GET /calls/{call_id} One call: numbers, timing, where it was routed and its verdict. Bearer or API key
GET /calls/{call_id}/analysis The verdict on its own: probability, category, red flags and recommendation. Bearer or API key
GET /calls/{call_id}/export Download a self-contained evidence bundle for the call — it opens offline, with no account. Bearer or API key
GET /calls/{call_id}/pcap Download the media capture of the call. Bearer or API key
GET /calls/{call_id}/recording Download the call audio as a stereo WAV. Bearer or API key
GET /calls/{call_id}/sip-log The SIP message flow of the call, as rows and as a plain-text log. Bearer or API key
GET /calls/{call_id}/transcript The transcript of the call, with its language and confidence. Bearer or API key
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
GET /calls status string or null
analysis_status string or null
from timestamp or null
to timestamp or null
min_probability integer or null, 0–100
external_id string or null
limit integer, default 50, 1–500
offset integer, default 0
200 CallList 422 Validation error
GET /calls/{call_id} call_id uuid, required 200 CallDetail 404 Call not found
GET /calls/{call_id}/analysis call_id uuid, required 200 AnalysisOut 404 Call not found
GET /calls/{call_id}/export call_id uuid, required 200 application/zip — the evidence bundle 404 Call not found
429 too_many_exports
GET /calls/{call_id}/pcap call_id uuid, required 200 The capture file, or a zip when the call had several media legs 404 Call not found
GET /calls/{call_id}/recording call_id uuid, required 200 audio/wav — the file, or a redirect to a short-lived download URL 404 Call not found
GET /calls/{call_id}/sip-log call_id uuid, required 200 SipLogOut 404 Call not found
GET /calls/{call_id}/transcript call_id uuid, required 200 TranscriptOut 404 Call not found

Sharing a call outside your account#

A password-protected link to one call, for a carrier or a customer who has no account. The owner side is authenticated; the reader side is not.

share one call, then open it as the reader would

curl -s -X POST $API/api/calls/$CALL_ID/share \
  -H "X-API-Key: $OVS_KEY" -H 'Content-Type: application/json' \
  -d '{"expires_in_hours":72,"label":"carrier dispute"}'
# 201 — "password" is in this response and in no other

curl -s -X POST $API/api/public/shares/$TOKEN/unlock \
  -H 'Content-Type: application/json' -d '{"password":"..."}'

curl -s $API/api/public/shares/$TOKEN -H "X-Share-Token: $VIEW_TOKEN"
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
POST /calls/{call_id}/share Create a password-protected public link to one call. The password is returned once. Bearer or API key
GET /calls/{call_id}/shares The links that exist for this call. Passwords are never included. Bearer or API key
DELETE /calls/shares/{share_id} Revoke a link. It stops opening immediately. Bearer or API key
POST /calls/shares/{share_id}/rotate Issue a new password for the same link, returned once. Bearer or API key
GET /public/shares/{token} The shared call, once unlocked. View token
GET /public/shares/{token}/meta Whether a link is real and still live, and who shared it. Nothing about the call. None
GET /public/shares/{token}/recording The shared call audio, once unlocked. View token
POST /public/shares/{token}/unlock Exchange the link password for a short-lived view token. None
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
POST /calls/{call_id}/share call_id uuid, required expires_in_hours integer or null
label string or null
201 CallShareCreated 404 Call not found
GET /calls/{call_id}/shares call_id uuid, required 200 CallShareList 404 Call not found
DELETE /calls/shares/{share_id} share_id uuid, required 200 CallShareOut 404 Share link not found
POST /calls/shares/{share_id}/rotate share_id uuid, required 200 CallShareCreated 404 Share link not found
409 This link is revoked or expired
GET /public/shares/{token} token string, required
t string or null
200 PublicSharePayload 401 Invalid link or password
404 This link is no longer available
GET /public/shares/{token}/meta token string, required 200 ShareMetaOut
GET /public/shares/{token}/recording token string, required
t string or null
200 audio/wav — the file, or a redirect to a short-lived download URL 401 Invalid link or password
404 This link is no longer available
POST /public/shares/{token}/unlock token string, required password string, required 200 ShareUnlockOut 401 Invalid link or password
429 too_many_attempts

Cases#

The investigation record attached to a call: title, severity, status, assignee and a comment thread.

open a case on a call and comment on it

CASE=$(curl -s -X POST $API/api/cases \
  -H "X-API-Key: $OVS_KEY" -H 'Content-Type: application/json' \
  -d '{"title":"Wangiri from +1 555","severity":"high","call_id":"'$CALL_ID'"}')

curl -s -X POST $API/api/cases/$CASE_ID/comments \
  -H "X-API-Key: $OVS_KEY" -H 'Content-Type: application/json' \
  -d '{"body":"Carrier notified."}'
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
GET /cases Search cases by status, severity or assignee. Bearer or API key
POST /cases Open a case, optionally attached to a call. Bearer or API key
GET /cases/{case_id} One case, with its comment thread. Bearer or API key
PATCH /cases/{case_id} Change status, severity, text or assignee. The new assignee is notified. Bearer or API key
POST /cases/{case_id}/comments Add a comment to a case. Bearer or API key
GET /cases/prefill Suggested title, severity and description for a case about a given call. Bearer or API key
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
GET /cases status string or null
severity string or null
assigned_to uuid or null
call_id uuid or null
limit integer, default 50, 1–200
offset integer, default 0
200 CaseList 422 Validation error
POST /cases title string, required
description string or null
severity "low" | "medium" | "high" | "critical", default "medium"
call_id uuid or null
201 CaseOut 404 Call not found
409 case_already_exists_for_call
GET /cases/{case_id} case_id uuid, required 200 CaseDetail 404 Case not found
PATCH /cases/{case_id} case_id uuid, required title string or null
description string or null
status "open" | "in_review" | "resolved" | "dismissed" or null
severity "low" | "medium" | "high" | "critical" or null
assigned_to uuid or null
clear_assigned_to boolean, default false
200 CaseOut 404 Case not found
422 assigned_to must be an active user of this account
POST /cases/{case_id}/comments case_id uuid, required body string, required 201 CaseCommentOut 404 Case not found
GET /cases/prefill call_id uuid, required 200 JSON object: title, severity, description, existing_case_id 404 Call not found

Automation and controlled numbers#

Rules that act on a verdict without a human — block or divert a number for a set time — and the table of numbers currently under control.

block a number for 24 hours when the verdict is 90 or above

curl -s -X POST $API/api/automation/rules \
  -H "X-API-Key: $OVS_KEY" -H 'Content-Type: application/json' \
  -d '{"name":"auto-block","min_probability":90,"action":"block","duration_hours":24}'

curl -s $API/api/automation/controls -H "X-API-Key: $OVS_KEY"
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
GET /automation/controls The numbers currently blocked or diverted by a rule. Bearer or API key
POST /automation/controls/{control_id}/release Release a controlled number so it is treated normally again. Bearer or API key
GET /automation/rules The automation rules on the account. Bearer or API key
POST /automation/rules Add a rule that blocks or diverts a number when a verdict crosses a threshold. Bearer or API key
DELETE /automation/rules/{rule_id} Remove a rule. Bearer or API key
PATCH /automation/rules/{rule_id} Change a rule, or turn it off. Bearer or API key
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
GET /automation/controls include_released boolean, default false
limit integer, default 50, 1–500
offset integer, default 0
200 AniControlList
POST /automation/controls/{control_id}/release control_id uuid, required 200 AniControlOut 404 control not found
409 control already released
GET /automation/rules 200 AutomationRuleOut[]
POST /automation/rules name string, required
enabled boolean, default true
min_probability integer, default 90
recommendations string[] or null, default ["block"]
action "block" | "divert", default "block"
divert_destination_id uuid or null
duration_hours integer or null
201 AutomationRuleOut 404 divert destination not found
409 Maximum number of automation rules reached
DELETE /automation/rules/{rule_id} rule_id uuid, required 204 No content 404 automation rule not found
PATCH /automation/rules/{rule_id} rule_id uuid, required name string or null
enabled boolean or null
min_probability integer or null
recommendations string[] or null
action "block" | "divert" or null
divert_destination_id uuid or null
duration_hours integer or null
clear_duration boolean, default false
200 AutomationRuleOut 404 divert destination not found
422 divert_destination_id is required when action is 'divert'

Alerts and webhooks#

Push a verdict out: e-mail alert rules with their own thresholds, and one signed HTTP webhook for your own systems.

point a webhook at your own system and test it

curl -s -X PUT $API/api/customer/webhook \
  -H "X-API-Key: $OVS_KEY" -H 'Content-Type: application/json' \
  -d '{"url":"https://noc.acme.example/hooks/ovs","secret":"a-long-random-string"}'

curl -s -X POST $API/api/customer/webhook/test -H "X-API-Key: $OVS_KEY"
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
GET /customer/alert-rules The e-mail alert rules on the account. Bearer or API key
POST /customer/alert-rules Alert named recipients when a verdict crosses a threshold. Bearer or API key
DELETE /customer/alert-rules/{rule_id} Remove an alert rule. Bearer or API key
PATCH /customer/alert-rules/{rule_id} Change an alert rule, or turn it off. Bearer or API key
POST /customer/alert-rules/{rule_id}/test Send a sample alert to the rule recipients now. Bearer or API key
GET /customer/webhook The webhook URL configured for the account. Bearer or API key
PUT /customer/webhook Set or clear the webhook URL and its signing secret. Bearer or API key
POST /customer/webhook/test Deliver one signed test event now and report what the endpoint answered. Bearer or API key
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
GET /customer/alert-rules 200 AlertRuleOut[]
POST /customer/alert-rules name string, required
enabled boolean, default true
min_probability integer, default 70
categories string[] or null
recommendations string[] or null
recipients string[] or null
throttle_minutes integer, default 0
include_transcript boolean, default false
201 AlertRuleOut 409 Maximum number of alert rules reached
DELETE /customer/alert-rules/{rule_id} rule_id uuid, required 204 No content 404 alert rule not found
PATCH /customer/alert-rules/{rule_id} rule_id uuid, required name string or null
enabled boolean or null
min_probability integer or null
categories string[] or null
recommendations string[] or null
recipients string[] or null
throttle_minutes integer or null
include_transcript boolean or null
200 AlertRuleOut 404 alert rule not found
POST /customer/alert-rules/{rule_id}/test rule_id uuid, required 200 AlertRuleTestOut 404 alert rule not found
409 smtp_not_configured
GET /customer/webhook 200 WebhookOut
PUT /customer/webhook url string or null
secret string or null
200 WebhookOut
POST /customer/webhook/test 200 WebhookTestOut

Plans, balance and payments#

What the plans are, what you are on, what you have spent and how to add credit or subscribe by card.

what the plans cost, and what is left

curl -s $API/api/plans

curl -s $API/api/customer/balance -H "X-API-Key: $OVS_KEY"
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
GET /customer/balance Current credit, plan and the minutes left in the cycle. Bearer or API key
GET /customer/ledger Every credit and debit on the account, newest first. Bearer or API key
POST /customer/payments/checkout Start a one-off top-up and return the URL to send the browser to. Bearer or API key
GET /customer/payments/config Whether card payment is enabled, and the presets the billing page offers. Bearer or API key
POST /customer/payments/subscribe Start a card subscription to a plan and return the URL to send the browser to. Bearer or API key
POST /customer/plan Move the account to another plan. Bearer or API key
GET /plans The plans on offer, with their prices and included minutes. None
POST /webhooks/stripe Payment-provider callback. Credits a top-up and renews a plan cycle. Not called by you. Provider signature
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
GET /customer/balance 200 BalanceOut
GET /customer/ledger limit integer, default 50, 1–500
offset integer, default 0
200 LedgerList
POST /customer/payments/checkout amount number or string, required 200 CheckoutSessionOut 409 Conflict
502 Payment provider error
GET /customer/payments/config 200 PaymentsPublicConfig
POST /customer/payments/subscribe plan_code string, required 200 CheckoutSessionOut 400 Pay-as-you-go has no monthly fee — nothing to subscribe to
404 Plan not found
409 Conflict
502 Payment provider error
POST /customer/plan plan_code string, required 200 CustomerOut 402 Insufficient balance for the first month's fee
404 Plan not found
409 Already subscribed to this plan
GET /plans 200 PlanOut[]
POST /webhooks/stripe 200 JSON object acknowledging the event 400 Invalid signature
409 Conflict

Dashboard, statistics and live calls#

Aggregates for a dashboard, and the calls that are in progress right now.

a week of activity, and what is on the wire now

curl -s "$API/api/customer/dashboard?days=7" -H "X-API-Key: $OVS_KEY"

curl -s $API/api/customer/live-calls -H "X-API-Key: $OVS_KEY"
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
GET /customer/dashboard Calls, minutes, spend and risk distribution over the last N days. Bearer or API key
GET /customer/live-calls Calls in progress right now, with elapsed time and the credit countdown. Bearer or API key
GET /customer/stats Headline counters for the account. Bearer or API key
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
GET /customer/dashboard days integer, default 30, 1–366 200 CustomerDashboardOut
GET /customer/live-calls 200 LiveCallsOut
GET /customer/stats from timestamp or null
to timestamp or null
200 StatsOut

Service health#

One unauthenticated endpoint to poll from your own monitoring.

poll from your monitoring

curl -s $API/api/health
# {"status":"ok",...}
Endpoints in this group. Prefix every path with /api.
MethodPathDoesAuth
GET /health Liveness of the service. No credentials needed. None
Parameters, payloads and the errors each endpoint raises.
EndpointPath and queryRequest bodyReturnsErrors
GET /health 200 HealthOut

Objects#

Every object named above, with its fields as the API returns and accepts them. A field marked or null can be absent.

AlertRuleCreate
FieldTypeRequired
namestringyes
enabledbooleandefault true
min_probabilityintegerdefault 70
categoriesstring[] or nullno
recommendationsstring[] or nullno
recipientsstring[] or nullno
throttle_minutesintegerdefault 0
include_transcriptbooleandefault false
AlertRuleOut
FieldTypeRequired
iduuidyes
namestringyes
enabledbooleanyes
min_probabilityintegeryes
categoriesstring[] or nullyes
recommendationsstring[] or nullyes
recipientsstring[] or nullyes
throttle_minutesintegeryes
include_transcriptbooleanyes
created_attimestampyes
updated_attimestampyes
AlertRuleTestOut
FieldTypeRequired
sentbooleanyes
errorstring or nullno
latency_msintegeryes
recipientsstring[]yes
AlertRuleUpdate
FieldTypeRequired
namestring or nullno
enabledboolean or nullno
min_probabilityinteger or nullno
categoriesstring[] or nullno
recommendationsstring[] or nullno
recipientsstring[] or nullno
throttle_minutesinteger or nullno
include_transcriptboolean or nullno
AnalysisOut
FieldTypeRequired
iduuidyes
providerstring or nullno
modelstring or nullno
locationstring or nullno
prompt_versionstringyes
titlestring or nullyes
probabilityintegeryes
categorystringyes
entitystring or nullyes
caller_identitystring or nullyes
red_flagsstring[] or nullyes
languagestring or nullyes
tcpa_commentstring or nullyes
summarystring or nullyes
recommendationstringyes
keywordsstring[] or nullyes
input_tokensintegeryes
output_tokensintegeryes
costnumberyes
latency_msintegeryes
created_attimestampyes
AnalysisSummary
FieldTypeRequired
titlestring or nullyes
probabilityintegeryes
categorystringyes
recommendationstringyes
red_flagsstring[] or nullyes
AniControlList
FieldTypeRequired
totalintegeryes
limitintegeryes
offsetintegeryes
itemsAniControlOut[]yes
AniControlOut
FieldTypeRequired
iduuidyes
anistringyes
actionstringyes
divert_destination_iduuid or nullyes
reasonstring or nullyes
expires_attimestamp or nullyes
released_attimestamp or nullyes
created_attimestampyes
ApiKeyCreate
FieldTypeRequired
namestringyes
ApiKeyCreated
FieldTypeRequired
iduuidyes
namestringyes
prefixstringyes
last_used_attimestamp or nullyes
revoked_attimestamp or nullyes
created_attimestampyes
keystringyes
ApiKeyOut
FieldTypeRequired
iduuidyes
namestringyes
prefixstringyes
last_used_attimestamp or nullyes
revoked_attimestamp or nullyes
created_attimestampyes
AuthConfigOut
FieldTypeRequired
signup_enabledbooleanyes
password_min_lengthintegerdefault 12
access_token_ttl_secintegeryes
AutomationRuleCreate
FieldTypeRequired
namestringyes
enabledbooleandefault true
min_probabilityintegerdefault 90
recommendationsstring[] or nulldefault ["block"]
action"block" | "divert"default "block"
divert_destination_iduuid or nullno
duration_hoursinteger or nullno
AutomationRuleOut
FieldTypeRequired
iduuidyes
namestringyes
enabledbooleanyes
min_probabilityintegeryes
recommendationsstring[] or nullyes
actionstringyes
divert_destination_iduuid or nullyes
duration_hoursinteger or nullyes
created_attimestampyes
updated_attimestampyes
AutomationRuleUpdate
FieldTypeRequired
namestring or nullno
enabledboolean or nullno
min_probabilityinteger or nullno
recommendationsstring[] or nullno
action"block" | "divert" or nullno
divert_destination_iduuid or nullno
duration_hoursinteger or nullno
clear_durationbooleandefault false
BalanceOut
FieldTypeRequired
balancenumberyes
planstringyes
plan_namestringyes
portsintegeryes
active_callsintegeryes
cycle_minutes_usednumberyes
included_minutesinteger or nullyes
per_minute_ratenumberyes
plan_renews_attimestamp or nullyes
CallDetail
FieldTypeRequired
iduuidyes
sip_call_idstringyes
customer_iduuidyes
src_ipstringyes
anistring or nullyes
dialedstring or nullyes
dest_hoststringyes
dest_portintegeryes
dest_transportstringyes
media_ipstring or nullyes
external_idstring or nullno
external_namestring or nullno
routed_destination_iduuid or nullno
route_prefixstring or nullno
dest_kindstringdefault "sip"
dest_tech_prefixstring or nullno
directionstringyes
statusstringyes
sip_codeinteger or nullyes
end_reasonstring or nullyes
started_attimestampyes
answered_attimestamp or nullyes
ended_attimestamp or nullyes
duration_secinteger or nullyes
billsecinteger or nullyes
charged_amountnumberyes
rate_appliednumber or nullyes
recording_wav_pathstring or nullyes
transcript_statusstringyes
analysis_statusstringyes
processing_errorstring or nullyes
created_attimestampyes
analysisAnalysisOut or nullno
recording_pcap_pathsstring[] or nullyes
captured_headersobject or nullno
case_iduuid or nullno
routed_to_labelstring or nullno
transcriptTranscriptMeta or nullno
transcript_summarystring or nullno
CallList
FieldTypeRequired
totalintegeryes
limitintegeryes
offsetintegeryes
itemsCallOut[]yes
CallOut
FieldTypeRequired
iduuidyes
sip_call_idstringyes
customer_iduuidyes
src_ipstringyes
anistring or nullyes
dialedstring or nullyes
dest_hoststringyes
dest_portintegeryes
dest_transportstringyes
media_ipstring or nullyes
external_idstring or nullno
external_namestring or nullno
routed_destination_iduuid or nullno
route_prefixstring or nullno
dest_kindstringdefault "sip"
dest_tech_prefixstring or nullno
directionstringyes
statusstringyes
sip_codeinteger or nullyes
end_reasonstring or nullyes
started_attimestampyes
answered_attimestamp or nullyes
ended_attimestamp or nullyes
duration_secinteger or nullyes
billsecinteger or nullyes
charged_amountnumberyes
rate_appliednumber or nullyes
recording_wav_pathstring or nullyes
transcript_statusstringyes
analysis_statusstringyes
processing_errorstring or nullyes
created_attimestampyes
analysisAnalysisSummary or nullno
CallShareCreated
FieldTypeRequired
iduuidyes
call_iduuidyes
urlstringyes
labelstring or nullyes
created_bystring or nullyes
created_attimestampyes
expires_attimestamp or nullyes
revoked_attimestamp or nullyes
view_countintegeryes
last_viewed_attimestamp or nullyes
activebooleanyes
passwordstringyes
CallShareList
FieldTypeRequired
itemsCallShareOut[]yes
CallShareOut
FieldTypeRequired
iduuidyes
call_iduuidyes
urlstringyes
labelstring or nullyes
created_bystring or nullyes
created_attimestampyes
expires_attimestamp or nullyes
revoked_attimestamp or nullyes
view_countintegeryes
last_viewed_attimestamp or nullyes
activebooleanyes
CallsPerDay
FieldTypeRequired
datestringyes
callsintegeryes
high_riskintegeryes
CaseCommentCreate
FieldTypeRequired
bodystringyes
CaseCommentOut
FieldTypeRequired
iduuidyes
author_kindstringyes
author_labelstring or nullyes
bodystringyes
created_attimestampyes
CaseCreate
FieldTypeRequired
titlestringyes
descriptionstring or nullno
severity"low" | "medium" | "high" | "critical"default "medium"
call_iduuid or nullno
CaseDetail
FieldTypeRequired
iduuidyes
case_nointegeryes
customer_iduuidyes
call_iduuid or nullyes
titlestringyes
descriptionstring or nullyes
statusstringyes
severitystringyes
created_bystring or nullyes
assigned_touuid or nullyes
created_attimestampyes
updated_attimestampyes
assigned_to_labelstring or nullno
comment_countintegerdefault 0
commentsCaseCommentOut[]default []
callCallOut or nullno
CaseList
FieldTypeRequired
totalintegeryes
limitintegeryes
offsetintegeryes
itemsCaseOut[]yes
CaseOut
FieldTypeRequired
iduuidyes
case_nointegeryes
customer_iduuidyes
call_iduuid or nullyes
titlestringyes
descriptionstring or nullyes
statusstringyes
severitystringyes
created_bystring or nullyes
assigned_touuid or nullyes
created_attimestampyes
updated_attimestampyes
assigned_to_labelstring or nullno
comment_countintegerdefault 0
CaseUpdate
FieldTypeRequired
titlestring or nullno
descriptionstring or nullno
status"open" | "in_review" | "resolved" | "dismissed" or nullno
severity"low" | "medium" | "high" | "critical" or nullno
assigned_touuid or nullno
clear_assigned_tobooleandefault false
ChangePasswordRequest
FieldTypeRequired
current_passwordstringyes
new_passwordstringyes
CheckoutRequest
FieldTypeRequired
amountnumber or stringyes
CheckoutSessionOut
FieldTypeRequired
session_idstringyes
urlstringyes
CustomerDashboardOut
FieldTypeRequired
daysintegeryes
fromtimestampyes
totimestampyes
calls_todayintegeryes
calls_periodintegeryes
minutes_periodnumberyes
spend_periodnumberyes
high_risk_pctnumberyes
risk_distributionRiskBucket[]yes
calls_per_dayCallsPerDay[]yes
recent_high_riskCallOut[]yes
balancenumberyes
planDashboardPlanyes
cycle_minutes_usednumberyes
active_callsintegeryes
CustomerOut
FieldTypeRequired
iduuidyes
emailstringyes
companystring or nullyes
rolestringyes
statusstringyes
must_change_passwordbooleandefault false
balancenumberyes
plan_codestringyes
portsintegeryes
plan_started_attimestamp or nullyes
plan_renews_attimestamp or nullyes
cycle_minutes_usednumberyes
webhook_urlstring or nullyes
created_attimestampyes
twofa_enabledbooleandefault false
impersonated_bystring or nullno
pilotPilotStatus or nullno
CustomerUserInvite
FieldTypeRequired
emailemailyes
namestring or nullno
CustomerUserInvited
FieldTypeRequired
userCustomerUserOutyes
welcome_emailWelcomeEmailStatus or nullno
CustomerUserList
FieldTypeRequired
itemsCustomerUserOut[]yes
max_usersintegerdefault 10
CustomerUserOut
FieldTypeRequired
iduuidyes
emailstringyes
namestring or nullyes
rolestringyes
is_activebooleanyes
must_change_passwordbooleandefault false
last_login_attimestamp or nullyes
created_attimestampyes
CustomerUserUpdate
FieldTypeRequired
namestring or nullno
is_activeboolean or nullno
DashboardPlan
FieldTypeRequired
codestringyes
namestringyes
portsintegeryes
included_minutesinteger or nullyes
renews_attimestamp or nullyes
DestinationCreate
FieldTypeRequired
hoststringyes
portintegerdefault 5060
transport"udp" | "tcp" | "tls"default "udp"
is_defaultbooleandefault false
labelstring or nullno
kind"sip" | "voice_ai"default "sip"
providerstring or nullno
agent_idstring or nullno
configobject or nullno
tech_prefixstring or nullno
DestinationOut
FieldTypeRequired
iduuidyes
hoststringyes
portintegeryes
transportstringyes
is_defaultbooleanyes
labelstring or nullyes
kindstringyes
providerstring or nullyes
agent_idstring or nullyes
configobject or nullyes
tech_prefixstring or nullyes
created_attimestampyes
DestinationUpdate
FieldTypeRequired
hoststring or nullno
portinteger or nullno
transport"udp" | "tcp" | "tls" or nullno
is_defaultboolean or nullno
labelstring or nullno
kind"sip" | "voice_ai" or nullno
providerstring or nullno
agent_idstring or nullno
configobject or nullno
tech_prefixstring or nullno
HealthOut
FieldTypeRequired
statusstringyes
dbbooleanyes
versionstringyes
IpCreate
FieldTypeRequired
cidrstringyes
labelstring or nullno
destination_iduuid or nullno
enabledbooleandefault true
IpOut
FieldTypeRequired
iduuidyes
cidrstringyes
labelstring or nullyes
destination_iduuid or nullyes
enabledbooleanyes
created_attimestampyes
LedgerList
FieldTypeRequired
totalintegeryes
limitintegeryes
offsetintegeryes
itemsLedgerOut[]yes
LedgerOut
FieldTypeRequired
iduuidyes
typestringyes
amountnumberyes
balance_afternumberyes
call_iduuid or nullyes
descriptionstring or nullyes
waived_amountnumberdefault 0
created_attimestampyes
LiveCall
FieldTypeRequired
iduuidyes
statusstringyes
anistring or nullyes
dialedstring or nullyes
external_idstring or nullyes
external_namestring or nullyes
dest_hoststringyes
dest_portintegeryes
dest_transportstringyes
dest_kindstringyes
route_prefixstring or nullyes
media_nodestring or nullyes
started_attimestampyes
answered_attimestamp or nullyes
elapsed_secintegeryes
max_call_secondsinteger or nullyes
remaining_secinteger or nullyes
LiveCallsOut
FieldTypeRequired
itemsLiveCall[]yes
active_countintegeryes
portsintegeryes
ports_in_useintegeryes
LoginRequest
FieldTypeRequired
emailemailyes
passwordstringyes
NetworkInfoOut
FieldTypeRequired
ingress_hoststringyes
ingress_portintegerdefault 5060
transportsstring[]default ["udp","tcp"]
PasskeyLoginRequest
FieldTypeRequired
login_tokenstringyes
assertionobjectyes
PasskeyOut
FieldTypeRequired
iduuidyes
namestringyes
transportsstring[] or nullno
created_attimestampyes
last_used_attimestamp or nullyes
PasskeyRegisterBeginOut
FieldTypeRequired
optionsobjectyes
statestringyes
PasskeyRegisterComplete
FieldTypeRequired
credentialobjectyes
statestringyes
namestring or nullno
PasskeyRename
FieldTypeRequired
namestringyes
PaymentsPublicConfig
FieldTypeRequired
enabledbooleanyes
publishable_keystringyes
currencystringyes
preset_amountsinteger[]default [25,50,100,250]
min_custom_amountintegerdefault 10
PilotStatus
FieldTypeRequired
activebooleandefault false
started_attimestamp or nullno
ends_attimestamp or nullno
days_leftintegerdefault 0
minutes_limitinteger or nullno
minutes_usednumberdefault 0
exhaustedbooleandefault false
waived_totalnumberdefault 0
PlanChange
FieldTypeRequired
plan_codestringyes
PlanOut
FieldTypeRequired
codestringyes
namestringyes
monthly_feenumberyes
portsintegeryes
included_minutesinteger or nullyes
per_minute_ratenumberyes
min_billable_secondsintegeryes
activebooleanyes
descriptionstring or nullyes
PublicShareAnalysis
FieldTypeRequired
titlestring or nullno
probabilityinteger or nullno
categorystring or nullno
entitystring or nullno
red_flagsstring[] or nullno
tcpa_commentstring or nullno
summarystring or nullno
recommendationstring or nullno
PublicShareCall
FieldTypeRequired
dialedstring or nullno
anistring or nullno
directionstring or nullno
started_attimestamp or nullno
duration_secinteger or nullno
PublicSharePayload
FieldTypeRequired
shared_bystring or nullno
shared_attimestamp or nullno
labelstring or nullno
expires_attimestamp or nullno
callPublicShareCallyes
analysisPublicShareAnalysis or nullno
transcriptPublicShareTranscript or nullno
has_recordingbooleandefault false
PublicShareTranscript
FieldTypeRequired
textstringdefault ""
segmentsobject[] or nullno
RiskBucket
FieldTypeRequired
bucket"0-29" | "30-69" | "70-100"yes
countintegeryes
RoutingRuleCreate
FieldTypeRequired
prefixstringyes
destination_iduuidyes
enabledbooleandefault true
priorityintegerdefault 100
labelstring or nullno
RoutingRuleOut
FieldTypeRequired
iduuidyes
prefixstringyes
destination_iduuidyes
enabledbooleanyes
priorityintegeryes
labelstring or nullyes
created_attimestampyes
updated_attimestampyes
RoutingRuleUpdate
FieldTypeRequired
prefixstring or nullno
destination_iduuid or nullno
enabledboolean or nullno
priorityinteger or nullno
labelstring or nullno
SessionCustomer
FieldTypeRequired
iduuidyes
emailstringyes
companystring or nullyes
rolestringyes
must_change_passwordbooleandefault false
statusstringyes
ShareCreate
FieldTypeRequired
expires_in_hoursinteger or nullno
labelstring or nullno
ShareMetaOut
FieldTypeRequired
existsbooleanyes
requires_passwordbooleandefault true
revokedbooleandefault false
expiredbooleandefault false
company_namestring or nullno
ShareUnlockOut
FieldTypeRequired
view_tokenstringyes
expires_inintegeryes
ShareUnlockRequest
FieldTypeRequired
passwordstringyes
SignupRequest
FieldTypeRequired
emailemailyes
passwordstringyes
companystring or nullno
SignupResponse
FieldTypeRequired
customerCustomerOutyes
access_tokenstringyes
token_typestringdefault "bearer"
expires_inintegeryes
SipLogMessage
FieldTypeRequired
time_stamptimestampyes
directionstringyes
methodstringyes
statusstring or nullno
fromipstringyes
toipstringyes
fromtagstring or nullno
totagstring or nullno
first_linestringyes
headersobject or nullno
SipLogOut
FieldTypeRequired
call_iduuidyes
sip_call_idstringyes
messagesSipLogMessage[]yes
textstringyes
StatsOut
FieldTypeRequired
fromtimestamp or nullno
totimestamp or nullno
callsintegeryes
answered_callsintegeryes
minutesnumberyes
spendnumberyes
by_categoryobjectyes
by_recommendationobjectyes
avg_probabilitynumber or nullyes
TokenResponse
FieldTypeRequired
access_tokenstringyes
token_typestringdefault "bearer"
expires_inintegeryes
customerSessionCustomer or nullno
TranscriptMeta
FieldTypeRequired
iduuidyes
providerstring or nullno
modelstring or nullno
locationstring or nullno
languagestring or nullyes
audio_secondsnumber or nullyes
costnumberyes
created_attimestampyes
TranscriptOut
FieldTypeRequired
iduuidyes
providerstring or nullno
modelstring or nullno
locationstring or nullno
languagestring or nullyes
textstringyes
segmentsobject[] or nullyes
audio_secondsnumber or nullyes
costnumberyes
created_attimestampyes
WebhookOut
FieldTypeRequired
urlstring or nullyes
secret_setbooleanyes
WebhookTestOut
FieldTypeRequired
deliveredbooleanyes
status_codeinteger or nullno
errorstring or nullno
latency_msintegeryes
WebhookUpdate
FieldTypeRequired
urlstring or nullno
secretstring or nullno
WelcomeEmailStatus
FieldTypeRequired
sentbooleandefault false
errorstring or nullno
skipped_reasonstring or nullno

Generated from the platform's own API schema on 2026-08-27: 81 operations over 66 paths, and 87 objects. Operator-only endpoints are not part of this reference and never appear here.