Documentation
For AI agents
Ask AI about this page
An AI agent can take Open Voice Shield to a verdict: add a destination, set the webhook and alerts, ask for a test call, read the analysis. Through the MCP server at /api/mcp a person signs in once through OAuth and confirms each test call in the portal. A script with an API key uses the same REST endpoints directly.
What an agent can do here#
Everything the portal does is an endpoint. An agent can describe where calls should go, tell the platform where to push results, add alert rules, ask for a real call through that route and read what the analysis made of it. The same agent can run the account afterwards: list calls, pull transcripts and PDF reports, block a caller ID, open a case.
A few steps stay with a person because they decide who is called and who is trusted: signing in to connect an agent, confirming each test call an agent asks for, verifying a phone number, and entering secrets, such as a destination's password or provider key, the webhook signing secret and the Slack connection.
Two doors lead in. The REST API is the full contract, documented in /api/openapi.json, for scripts and agents that hold their own API key. The MCP server at /api/mcp exposes the common steps as tools with plain descriptions, for clients that speak the Model Context Protocol, with an OAuth sign-in and a confirmation step on test calls. Both act on the same account and produce the same audit trail.
Discovery#
Three files are meant to be read by software before any HTML:
- https://ovs.telecomsxchange.com/llms.txt
- What the product is and is not, every page with a summary, the machine-readable endpoints and citation guidance.
- https://ovs.telecomsxchange.com/.well-known/agent.json
- An agent card in the A2A format: the MCP endpoint, how to authenticate, the skills (configure, test call, query calls) and the OpenAPI URL.
- https://ovs.telecomsxchange.com/api/openapi.json
- The complete REST contract. /api/docs renders it.
GET https://ovs.telecomsxchange.com/api/mcp answers with the tool names and the authentication rule, so a client that only has the URL can orient itself.
From nothing to a verdict, with curl#
This is the REST path, for a script or an agent that holds its own API key. The whole run takes a few minutes, most of it the call itself and the analysis after hangup. Every address below is a documentation address; use your own. Through the MCP server the account comes from the OAuth sign-in instead, and a test call waits for a person's confirmation.
1. Sign up#
curl -s -X POST https://ovs.telecomsxchange.com/api/auth/signup \
-H 'Content-Type: application/json' \
-d '{"email":"agent@acme.example","password":"a-long-password-here","company":"Acme Agent","accept_terms":true}'
# 201 {"access_token":"eyJ...","customer":{"id":"...","balance":5.0,...}}
TOKEN=eyJ...
The password must be 12 characters or more. The account starts with credit, so the steps below work immediately.
2. Mint an API key#
curl -s -X POST https://ovs.telecomsxchange.com/api/auth/api-keys \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"agent"}'
# 201 {"id":"...","name":"agent","prefix":"ovs_...","key":"ovs_...","revoked_at":null}
KEY=ovs_...
The key is shown once. The Developers page of the portal creates and revokes keys too. A key is accepted as Authorization: Bearer $KEY or as X-API-Key: $KEY; the examples use the bearer form.
3. Add a destination#
A destination is where calls go on to after the platform: your switch, a carrier, or an AI voice agent over TLS (xAI or OpenAI; GET /customer/voice-providers lists them with the host, port and identifier each expects). The default destination takes any call no routing rule claims.
curl -s -X POST https://ovs.telecomsxchange.com/api/customer/destinations \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"host":"203.0.113.20","port":5060,"transport":"udp","label":"carrier","is_default":true}'
# 201 {"id":"DEST_ID","host":"203.0.113.20","port":5060,"transport":"udp","is_default":true,...}
If your carrier expects a route prefix in front of the dialed number, add it as tech_prefix on the destination; the platform prepends it on the way out. Every account starts empty, so the host, port and prefix are always your own.
Optional: a routing rule sends calls by dialed prefix to a destination (POST /api/customer/routing-rules with prefix and destination_id), and an IP whitelist entry admits INVITEs from your own switch (POST /api/customer/ips with cidr). Neither is needed for test calls, which the platform originates itself.
4. Webhook, alert rules, Slack#
# every analyzed call, signed with HMAC-SHA256 in X-OVS-Signature
curl -s -X PUT https://ovs.telecomsxchange.com/api/customer/webhook \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"url":"https://agent.acme.example/ovs","secret":"a-shared-secret-of-your-own"}'
# a webhook.test event, delivered now, with the outcome in the reply
curl -s -X POST https://ovs.telecomsxchange.com/api/customer/webhook/test -H "Authorization: Bearer $KEY"
# alert when a call is scored 90 or higher with a block recommendation
curl -s -X POST https://ovs.telecomsxchange.com/api/customer/alert-rules \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"name":"Block at 90","min_probability":90,"recommendations":["block"]}'
# a Slack channel, by its incoming-webhook URL; put the returned id in a rule's channel_ids
curl -s -X POST https://ovs.telecomsxchange.com/api/customer/integrations/slack/webhook \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"url":"https://hooks.slack.com/services/T000/B000/XXXX","label":"#fraud-desk"}'
Every account already has one enabled alert rule that e-mails the account address on a high-risk verdict. A webhook is always signed: a URL with no secret given and none on file is refused. Payload shapes are in the API reference; Slack details are under Slack alerts.
5. Place a test call#
The platform dials the number through the destination, waits for an answer, plays the recorded announcement and then the speech sample for the requested time, and hangs up. The call is recorded and analyzed like any other and appears in the calls list with origin test. With an API key on the REST API it is queued at once; asked for with a connector's OAuth token, or through the MCP server, the same request comes back awaiting_confirm with a confirm_url, and nothing rings until a person confirms it there (below).
# scam_sample rings only a number the account has verified
curl -s -X POST https://ovs.telecomsxchange.com/api/customer/test-calls \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"number":"14165550123","destination_id":"DEST_ID","seconds":30,"speech":"scam_sample"}'
# 202 {"id":"TC_ID","status":"queued","sip_call_id":"ovs-test-...","call_id":null,...}
# poll until status is done or failed
curl -s https://ovs.telecomsxchange.com/api/customer/test-calls/TC_ID -H "Authorization: Bearer $KEY"
# {"status":"done","answered":true,"sip_code":200,"talk_seconds":39.0,"ended_by":"caller",
# "call_id":"CALL_ID",...}
- Announcement
- Every test call, in every mode, opens with a recorded announcement: "This is an automated test call from Open Voice Shield, placed on behalf of one of its account holders. This call is recorded." It cannot be turned off, and it is added to the seconds you ask for.
- speech
- route_test (default) is a neutral announcement that says it is a test call, and may ring any number. scam_sample is a known card-services scam script, to confirm a block verdict and an alert come back; it rings only the account's verified numbers. agent is below, also to verified numbers only.
- seconds
- 5 to 120 of playback after the announcement; the far end must answer within 60 seconds.
- caller_id
- Optional. Left out, the platform presents its own number. Otherwise it must be one of the account's verified numbers (GET /api/customer/verified-numbers); any other number is refused with 422 caller_id_not_verified.
- Verified numbers
- A person verifies a number in the portal under Verified numbers: the platform calls it through one of the account's destinations, opens with the announcement and speaks a six-digit code, which the person types in. Hosted numbers that passed their pointing test count too. Neither step is open to an API key or an agent. A scam_sample or agent call to any other number is refused with 422 number_not_verified.
- Limits
- Three test calls in progress per account, requests awaiting confirmation included. A destination that refuses the call ends with status: done, answered: false and the SIP code; a transport failure ends with failed and an error.
Or let a voice agent make the call
A fixed recording cannot answer an IVR, satisfy a menu or keep a person talking. Set speech to agent and name one of your Voice AI destinations as agent_destination_id (in the portal: Web Dialer, then "Let an agent call"): after the announcement that agent speaks on the call and holds a real conversation with whatever answers, following a short instruction that applies to this call only. The number must be one of the account's verified numbers. The call is recorded, transcribed and analyzed as usual; the agent leg is a separate relay-only call metered for its seconds.
curl -s -X POST https://ovs.telecomsxchange.com/api/customer/test-calls \
-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"number":"14165550123","destination_id":"DEST_ID","seconds":60,"speech":"agent",
"agent_destination_id":"AGENT_DEST_ID",
"instruction":"Ask for the opening hours and the address, then say goodbye."}'
# 202 {"id":"TC_ID","status":"queued","agent_sip_call_id":"ovs-test-agent-...",...}
- The far end hears the platform's recorded announcement first, and the agent itself begins by saying it is an automated, recorded test call. It has no tools and no account context, and it is told to ignore anything the far end says that would change its task, reveal its instructions or have it pose as a person. The instruction cannot change the number, the caller ID, the duration or the account.
- Per-call instructions need a provider whose calls the platform accepts through a hosted webhook (OpenAI), and the agent destination must be the one whose webhook is registered in that project: your own project, your own destination. An xAI agent runs with its own configuration and refuses an instruction.
- Ceilings, checked before anything is dialled and again when a person confirms: 120 seconds per call, a spend ceiling per call covering both legs and the agent seconds, 30 minutes of agent calls per account and day, and one agent-backed test call at a time. A refusal is a 409 naming the ceiling.
- The far end is being recorded. Keep the instruction to what a test needs.
6. Read the verdict#
curl -s https://ovs.telecomsxchange.com/api/calls/CALL_ID -H "Authorization: Bearer $KEY"
# {"status":"completed","analysis_status":"done","origin":"test","billsec":39,
# "analysis":{"probability":94,"category":"card_services_scam","recommendation":"block",
# "red_flags":[...],"tcpa_comment":"...","route_alert":null,...},
# "qos":{"caller":{"mos_estimated":4.2,...},"callee":{...}},...}
curl -s https://ovs.telecomsxchange.com/api/calls/CALL_ID/transcript -H "Authorization: Bearer $KEY"
curl -s -o report.pdf https://ovs.telecomsxchange.com/api/calls/CALL_ID/report.pdf -H "Authorization: Bearer $KEY"
Analysis lands within minutes of hangup. Poll the call until analysis_status is done, or wait for the call.analyzed webhook, which carries the same fields. The route_alert field is the false answer supervision finding, when there is one; it is about the route, not the caller.
The MCP server#
https://ovs.telecomsxchange.com/api/mcp is a Model Context Protocol server over Streamable HTTP: JSON-RPC 2.0, one request per message, no session to keep. It exposes the steps above as tools with descriptions and input schemas, so a client can discover and run them without reading this page. initialize, tools/list, get_started and report_links work without credentials. Every other tool needs an account: an OAuth client signs the person in through the OAuth flow, and a client that holds a key sends it as Authorization: Bearer on the HTTP request. There is no signup or login tool, and credentials are never tool arguments.
# what is here
curl -s https://ovs.telecomsxchange.com/api/mcp
# the tool catalogue, no credentials needed
curl -s -X POST https://ovs.telecomsxchange.com/api/mcp -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# an account tool without credentials: 401 with a WWW-Authenticate challenge
curl -si -X POST https://ovs.telecomsxchange.com/api/mcp -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"me","arguments":{}}}'
# a test call request, with a key the person created on the Developers page
curl -s -X POST https://ovs.telecomsxchange.com/api/mcp -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"place_test_call",
"arguments":{"number":"14165550123","destination_id":"DEST_ID","seconds":30,"speech":"route_test"}}}'
# structuredContent: {"id":"TC_ID","status":"awaiting_confirm",
# "confirm_url":"https://ovs.telecomsxchange.com/app/test-calls/TC_ID","confirm_expires_at":"...",...}
Each tool is a thin wrapper over one REST endpoint. The tool result carries the endpoint's JSON as structuredContent and as text, and an HTTP error comes back as an error result with the status and the API's own message, never as a protocol error. Every tool declares an outputSchema taken from the API's own OpenAPI document, so an agent can validate results and compare runs over time: get_call returns the per-leg estimated MOS, jitter and packet loss, post-dial and answer delay, codec, and the analysis with probability, category, recommendation, red flags and route alert as fields, and list_calls takes from and to timestamps to pull a window of runs. The PDF report is the only output meant for people. The tools, in the order an agent needs them: get_started, me, account_balance, add_destination, list_destinations, check_destination, add_routing_rule, whitelist_ip, set_webhook, test_webhook, list_channels, add_alert_rule, list_alert_rules, list_verified_numbers, place_test_call, get_test_call, cancel_test_call, cli_coverage, verify_cli, get_cli_check, list_hosted_numbers, host_number, test_hosted_number, list_calls, get_call, get_transcript, report_links.
A test call through the connector#
place_test_call asks for a call; it does not place one. A person decides that a phone rings.
- The agent calls place_test_call with the number, the destination, the seconds, the speech sample and, if it wants one, a caller ID from list_verified_numbers. The reply has status: awaiting_confirm and a confirm_url, a page in the portal.
- The agent gives the person that link. The page shows the number, the caller ID, the mode and the duration, and nothing rings until the person presses Confirm there. Only a person signed into the portal can confirm; an API key or an agent cannot.
- An unconfirmed request lapses after 10 minutes as expired. The agent can withdraw it sooner with cancel_test_call.
- The agent polls get_test_call: awaiting_confirm, queued, running, then done or failed, or cancelled or expired if it never rang. Once there is a call_id, get_call and get_transcript carry the verdict.
The announcement, caller ID and verified-number rules are the ones in step 5, and the confirmation page checks them again before the call is queued.
What stays in the portal#
Every tool's input schema is closed: an unknown argument is refused, and so is any argument that would carry a secret, such as a password, an API key or a token. What a secret is needed for is set by the person in the portal, and never passes through the conversation:
- Destination credentials
- add_destination takes the host, port, transport and the rest of the route, but not a digest password, a provider API key or a webhook signing secret. Those are entered on the Network page; list_destinations shows needs_credential when one is still missing.
- The webhook signing secret
- set_webhook takes only the url. The secret is set or copied on the Developers page, and a URL is refused until one is on file.
- Slack
- Channels are connected on the Connectors page. list_channels gives their ids for add_alert_rule's channel_ids.
- Verified numbers and API keys
- A number is verified under Verified numbers, and keys are created and revoked on the Developers page.
A client configuration is the server URL. An OAuth client needs nothing else; a client with a key adds the header Authorization: Bearer ovs_.... Everything that goes beyond the tool set, such as automation rules, cases and evidence exports, is in the REST API and reachable with the same key or OAuth token.
Add the server to your agent#
An agent can add this server itself wherever its client allows it. A consumer chat assistant cannot: it only calls tools a person has connected, and its web fetch is read-only. Either way it is one step. The first tool that needs an account then opens our sign-in page, where the person signs in or creates the account, and from there the agent works on its own, except for the test calls the person confirms.
- Claude Code
-
The agent can run this itself:
At first use Claude Code opens the sign-in in the browser. To use a key instead, add --header "Authorization: Bearer ovs_..." with a key from the Developers page.claude mcp add --transport http open-voice-shield https://ovs.telecomsxchange.com/api/mcp - Cursor and VS Code
- Install links, which the agent can hand to the person or open itself: Add to Cursor and Add to VS Code. Both register the URL as an HTTP MCP server; the editor runs the OAuth sign-in at first use.
- Claude Managed Agents
- Declare the server on the agent and put an API key or OAuth tokens in a vault. The Managed Agents section has the agent definition, the credential shapes and the permission policy.
- Agents built on the Claude API
-
One entry in the request attaches the server, so the agent's own code does the
adding:
The token is an API key, or an access token from the OAuth flow. The request needs the MCP client beta header; see Anthropic's documentation for the current value."mcp_servers": [{"type": "url", "url": "https://ovs.telecomsxchange.com/api/mcp", "name": "open-voice-shield", "authorization_token": "ovs_..."}] - Claude (claude.ai and Claude Desktop)
- One link does the adding: Add to Claude. It opens the Add custom connector dialog with the name and URL filled in; the person confirms, and at first use signs in or creates the account on our consent page. Free, Pro and Max accounts add it themselves (Free allows one custom connector). On Team and Enterprise an owner adds it once for the whole organization with the organization link, and members connect from there. Then, in a chat, ask for example "Add my carrier at 203.0.113.20 on Open Voice Shield and place a 20 second route test to my number." The assistant calls get_started, the first account tool brings up the sign-in, and place_test_call hands back the link where you confirm the call. The manual path is the same dialog under Settings, Connectors, with the URL https://ovs.telecomsxchange.com/api/mcp and no OAuth fields: the client registers itself.
- ChatGPT and other assistants with custom connectors
- Add the same URL as a connector with OAuth authentication where the product offers it (in ChatGPT, under Connectors with developer mode on). The tool set is identical.
- Clients that can do neither OAuth nor headers
- They can use the open tools, but not the account. Credentials are not accepted as tool arguments; use the REST API from a script instead.
Claude Managed Agents#
A Managed Agent declares the server on the agent and gets its credential from a vault at session time. A person provisions that credential once; after that the agent runs without stopping, except that each test call it asks for waits for a person's confirmation in the portal. The requests reach us from Anthropic's infrastructure, so nothing in front of your own network matters.
Declare the server on the agent#
{
"name": "Route tester",
"model": "the model your agent runs",
"mcp_servers": [
{"type": "url", "name": "open-voice-shield", "url": "https://ovs.telecomsxchange.com/api/mcp"}
],
"tools": [
{"type": "agent_toolset_20260401"},
{"type": "mcp_toolset", "mcp_server_name": "open-voice-shield",
"default_config": {"permission_policy": "always_allow"},
"configs": [
{"name": "place_test_call", "permission_policy": "always_ask"},
{"name": "whitelist_ip", "enabled": false}
]}
]
}
The toolset's mcp_server_name must match the server's name. The MCP toolset defaults to always_ask, which stops for a confirmation before every call; for an agent that runs on its own set always_allow as the default and keep always_ask on the tools that ring a phone or spend money. Whatever the policy, a test call the agent asks for waits for the person's confirmation on our side. Tools you do not want the agent to have are switched off by name; every tool carries a read-only or destructive hint the policy can use.
Two ways to authenticate#
With no matching credential the connection is made unauthenticated, and only the open tools work; every account tool answers 401.
- static_bearer: an API key of an existing account
-
Create a key on the Developers page of the portal (or with
POST /api/auth/api-keys) and store it as the credential for
our URL. Anthropic sends it as Authorization: Bearer on every
request; the agent never sees it.
POST https://api.anthropic.com/v1/vaults/{vault_id}/credentials { "display_name": "Open Voice Shield key", "auth": {"type": "static_bearer", "mcp_server_url": "https://ovs.telecomsxchange.com/api/mcp", "token": "ovs_..."} } - mcp_oauth: tokens from our OAuth server, refreshed by Anthropic
-
Run the OAuth flow once from your own code (register a client, send
the person to the consent page, exchange the code) and store what came back. Anthropic
refreshes the access token before it expires using the refresh block; our token endpoint
takes a public client, so the auth type is none. Access tokens
live 15 minutes and refresh tokens rotate, which the vault handles.
{ "display_name": "Open Voice Shield (Alice)", "auth": {"type": "mcp_oauth", "mcp_server_url": "https://ovs.telecomsxchange.com/api/mcp", "access_token": "eyJ...", "expires_at": "2026-09-05T18:15:00Z", "refresh": {"token_endpoint": "https://ovs.telecomsxchange.com/api/oauth/token", "client_id": "ovs_c_...", "scope": "account offline_access", "refresh_token": "ovs_r_...", "token_endpoint_auth": {"type": "none"}}} }
Credentials match by URL, so mcp_server_url must be the MCP URL above; the scheme, host, default port and a trailing slash are normalized, a different path is not. Start the session with vault_ids and the credential is injected. A rejected or expired credential surfaces as a session.error of type mcp_authentication_failed_error naming the server, and the connection is retried on the next turn; our server answers such requests with 401 and a WWW-Authenticate challenge, never a tool error, which is what the vault's refresh and validation expect.
Sign in from the client: OAuth for MCP#
Clients that speak OAuth, which is Claude on every surface, Claude Code, Cursor and VS Code, never need a key pasted anywhere. initialize, the tool list, get_started and report_links work without credentials. The first tool that needs an account answers 401 with a WWW-Authenticate challenge, the client follows it to the discovery documents, opens our consent page, and the person signs in or creates the account right there, never in the chat. The client comes back with a token and carries on. An account with a passkey gets a second screen where the browser prompts for it, the same check as the portal's sign-in.
- Discovery
- /.well-known/oauth-protected-resource names the authorization server for /api/mcp; /.well-known/oauth-authorization-server lists the endpoints under /api/oauth. Registration is dynamic (RFC 7591), S256 PKCE is required, scopes are account and offline_access.
- Tokens
- The access token is the same short-lived token the portal uses, so it works on the REST API too, with one difference: a test call asked for with a connector's token, on either door, waits for a person's confirmation. Refresh tokens rotate on every use; a rotated token presented again revokes the whole session, as OAuth 2.1 asks of public clients. Revoke a session under Account in the portal or through /api/oauth/revoke.
- Redirects
- Registered redirect URIs match exactly, except loopback addresses where the port is ignored, which is how Claude Code and other native clients receive the code. The consent page shows where the result goes and warns when that is a loopback address.
- Testing it
- Add https://ovs.telecomsxchange.com/api/mcp as a custom connector in Claude, or point the MCP Inspector at it, ask for anything that needs an account, and the sign-in appears.
What to know before letting an agent loose#
- Real calls, real numbers
- A test call rings a phone and says so: it opens with the recorded announcement and presents the platform's own number or one of your verified numbers. Dial numbers you are allowed to call, and keep seconds short. The destination's own outbound charges are between you and that carrier.
- A person confirms
- Through the MCP server, or with a connector's OAuth token, no test call rings until a person confirms it on the portal page the agent links to. The scam sample and agent calls reach only numbers a person has verified.
- Secrets stay in the portal
- Passwords, keys and signing secrets are never tool arguments. A person enters them in the portal, where the agent cannot read them back.
- Money
- Calling and analysis draw on the prepaid balance. When it runs out, test calls and routed calls are refused with a clear error until a person adds funds.
- Rate limits
- The same limits as the REST API apply per key; the reply says when to retry.
- Audit
- Every write an agent makes is in the account's audit log with the key or connector that made it, and every test call records who asked for it and who confirmed it. Revoke the key on the Developers page, or the connector's session under Account, to stop it.
- Accuracy
- No accuracy figure is published. Treat the verdict as an analyst's read with its evidence attached, not a legal finding; the TCPA note is a reading of the conversation. MOS values are estimated.
Frequently asked questions#
Does any step need a person?
Through the MCP connector, yes: the person signs in or creates the account on our consent page when the client first connects, and confirms each test call the agent asks for on the portal page it links to. Verifying a phone number, and entering secrets such as a destination's password or the webhook signing secret, are also done by a person in the portal. A script working the REST API with its own API key needs no person for the rest. Signup needs an e-mail address and a password, with no card and no e-mail confirmation gate before the API works. A person is also needed to add funds beyond the signup credit.
How does an agent find this without reading the site?
Three files: /llms.txt describes the product and lists every page; /.well-known/agent.json is an agent card with the MCP endpoint, the OpenAPI URL and the skills; /api/openapi.json is the full contract. GET /api/mcp returns the tool names and how to authenticate.
What does a test call actually do?
The platform originates a SIP call to the number you give, through the destination you chose. It presents the platform's own number as the caller ID, or one of the account's verified numbers if you give one. It opens with a recorded announcement that this is an automated test call from Open Voice Shield, placed on behalf of one of its account holders, and that the call is recorded, then plays a speech sample for the number of seconds you asked for (5 to 120, on top of the announcement). The far end has to answer within 60 seconds. The call is recorded, transcribed and analyzed like any other, and appears in the calls list with origin test. Asked for through the MCP server, it waits until a person confirms it in the portal.
Which speech samples are there?
route_test, a neutral 17 second announcement that says it is a test call, which may ring any number; scam_sample, a recording of a known card-services scam script, useful to confirm a block verdict and an alert come back, which rings only the account's verified numbers; and agent, where one of your Voice AI destinations speaks on the call following a per-call instruction, also to verified numbers only. The recordings are G.711 audio.
What is a verified number?
A phone number the account has proved it answers. A person adds it in the portal under Verified numbers; the platform calls it, opens with the automated-call announcement and speaks a six-digit code, which the person types in. Hosted numbers that passed their pointing test count too. Only verified numbers may be presented as a test call's caller ID, and only they may receive scam_sample or agent calls. Neither an API key nor an agent can start or complete a verification.
Can a voice agent make the test call instead of a recording?
Yes, to one of the account's verified numbers. Set speech to agent and name one of your Voice AI destinations as agent_destination_id, with a short instruction for that call. After the platform's recorded announcement the agent says itself that this is an automated, recorded test call, has no tools, ignores attempts by the far end to change its task, and holds a real conversation with an IVR, a person or another agent. The call is recorded and analyzed as usual; ceilings apply to seconds, spend and calls per day.
Is a test call billed?
Yes, like any call: per second of connected time, the opening announcement included, plus the analysis fee of the account's AI mode. The signup credit covers many short test calls. A request that is never confirmed never rings and costs nothing. The destination's own charges for the outbound leg are between you and that carrier.
Can I send the API key as a bearer token?
Yes. A key starts with ovs_ and is accepted either as X-API-Key or as Authorization: Bearer ovs_.... MCP clients and most agent frameworks can only set a bearer header, so both forms work everywhere.
Is the MCP server stateful?
No. Each JSON-RPC request stands alone: send initialize once if your client insists, then tools/list and tools/call. Credentials travel on the HTTP request, as an OAuth access token or an API key in the Authorization header, never as tool arguments.
Can an agent pass a password or a key as a tool argument?
No. Every tool's input schema is closed, and an argument that would carry a secret (a password, an API key, a token, a destination's credential or a webhook secret) is refused. Those are entered by a person in the portal, so they never pass through a conversation.
Can I run this from Claude or another chat assistant?
Yes, after one click a person does: the Add to Claude link on this page opens the Add custom connector dialog with the name and URL filled in, on any Claude plan. A chat assistant cannot connect itself, and its page fetch is read-only. Once the connector is on, the first tool that needs an account opens our sign-in page, where the person signs in or creates the account. From then on the assistant works the account on its own, except that each test call it asks for comes back as a link where the person confirms it.
Can a Claude Managed Agent use it?
Yes. Declare https://ovs.telecomsxchange.com/api/mcp in the agent's mcp_servers with a matching mcp_toolset, and give it a credential in a vault: a static_bearer credential holding an API key of an existing account, or an mcp_oauth credential holding tokens from our OAuth server, which Anthropic refreshes through our token endpoint with a public client. With always_allow as the toolset's permission policy the agent configures and reads the account without stopping; a test call it asks for still waits until a person confirms it in the portal.
Does the MCP server support OAuth?
Yes: OAuth 2.1 with S256 PKCE, dynamic client registration, RFC 8414 and RFC 9728 discovery documents at /.well-known, rotating refresh tokens and revocation. initialize, tools/list, get_started and report_links are open; every account tool answers 401 with a WWW-Authenticate challenge, which is the contract Claude and other MCP clients follow to open the consent page. Accounts with a passkey confirm it on a second screen, as in the portal.
What number should a test call dial?
One you are allowed to call: your own phone, your IVR, a test number at your carrier. route_test may ring any number; scam_sample and agent calls ring only the account's verified numbers. Calls to emergency or premium numbers are your responsibility, as with any trunk.