# APIFleet API and MCP reference Manage voice-agent resources from code or a compatible MCP client. The operation catalog below identifies the exact REST routes, MCP tools and workflows that require the dashboard. All authenticated operations remain scoped to the workspace key. ## Authentication REST base URL: https://apifleet.dev. Resource routes are at the root, such as /assistants; there is no /api/v1 prefix. The MCP server is https://apifleet.dev/mcp. Both use Authorization: Bearer . Create a key at https://apifleet.dev/app/api-keys. It starts with af_live_, is shown once and is stored as a SHA-256 hash. Revoked keys cannot authenticate. Current keys have full management access to their workspace, including permission to create additional workspace keys; APIFleet does not currently offer a read-only or signup-only key scope. Keep the key in server-side environment variables or your MCP client's private settings, not in public browser code. The dashboard uses Google/email sign-in and a session cookie. MCP always requires the Bearer key and ignores dashboard cookies. The workspace is resolved from the key; you do not supply a tenant ID or choose another user's workspace. MCP does not currently provide an OAuth authorization server, refresh tokens or connected-app grants. Dashboard Google OAuth is not MCP OAuth. Repeated invalid credentials are throttled by source IP, with a Retry-After response header. Valid credentials are resolved before that failure block. There is no documented general 300-requests/minute allowance or subscription quota; do not assume another product's limits apply. REST and MCP use the same native workspace/resource checks. A full key remains a full key even if an agent chooses only read tools. Request bodies are JSON with Content-Type: application/json. The server request-body limit is 1 MiB; individual resources have tighter validation limits. Timestamps are ISO 8601; phone numbers use E.164. Currency fields ending in microusd are integer millionths of USD. First read: ```bash curl https://apifleet.dev/assistants \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` ## Errors Most management errors return { "error": { "message": "..." } }. Some errors also include code, details or current_revision. Do not assume every response has a stable code: some provider/catalog errors use their own documented response shape. | HTTP status | Meaning and next step | | --- | --- | | 400 | Invalid input. Correct the named field or JSON shape before trying again. | | 401 | Missing, invalid, expired or revoked credentials. Check your workspace key. | | 403 | The authenticated role cannot perform the action, or a browser Origin is not allowed for MCP. | | 404 | The resource does not exist in this workspace. Another workspace's identifier does not grant access. | | 409 | A state, revision or billing conflict. Inspect the returned code/details. | | 429 | Invalid-credential throttling; wait for Retry-After. Provider limits may also apply. | | 500 | Unexpected server error. The response hides private internal error details. | | 503 | A required service or feature is disabled or unavailable. | ASSISTANT_REVISION_CONFLICT is returned with HTTP 409 and current_revision when an assistant's If-Match revision is stale. Reload the assistant and review the changes before saving. Never remove the revision condition merely to overwrite a newer edit. Billing errors carry codes such as billing_insufficient_balance and can have status 409 or a service-specific status. Follow the actual returned code and the workspace wallet/policy. APIFleet uses prepaid usage, not subscription_required or a free allowance. MCP transport errors use HTTP status (401, 403, 405, 415 or unsupported-version 400). JSON-RPC envelope errors use error.code: -32600 for invalid requests, -32601 for unknown methods and -32602 for unknown tools/arguments. A native management failure returns result.isError: true, result.structuredContent.status with the REST status, and the native body in result.structuredContent.data. Read this even when HTTP is 200. The same body is encoded in result.content[0].text for clients without structured output support. check_entitlements is a read: it may successfully return a wallet that needs funds, with a nested error.code of billing_insufficient_balance. It does not execute a paid action. Creating an assistant does not call anyone. An outbound-call timeout or simulation-start timeout does not prove that work was rejected. Reconcile the existing call/run before retrying; there is no universal Idempotency-Key guarantee for those actions. ## MCP Server URL: https://apifleet.dev/mcp. Transport: stateless Streamable HTTP, JSON responses over POST. Every request needs the workspace Bearer key. No session ID is required. Versions 2025-03-26, 2025-06-18 and 2025-11-25 are supported; newer protocol revisions must negotiate a supported version. Browser requests must use the APIFleet origin. The server does not allow arbitrary cross-origin browser access. Tools use the same handlers as REST, including resource ownership, input validation, assistant lifecycle events and runtime billing gates. Their readOnlyHint, destructiveHint, idempotentHint and openWorldHint annotations describe their effects. A read can still disclose private workspace data. Ask the user before changing live routing, deleting resources, managing credentials/access, placing calls or starting paid tests. Paid MCP calls/runs additionally require confirm: true; that flag is a caller acknowledgment, not a payment authorization or a replacement for user approval. Provider secret entry, owner checkout and binary audio workflows are explicitly marked REST/dashboard-only in the operation catalog. MCP cannot bypass those controls. There is no MCP OAuth flow or verified marketplace listing at present. ### Codex In ~/.codex/config.toml: ```toml [mcp_servers.apifleet] url = "https://apifleet.dev/mcp" bearer_token_env_var = "APIFLEET_API_KEY" ``` Set APIFLEET_API_KEY in the environment from which Codex starts. This setting sends the value as a Bearer token; it is not a provider key. Connection options: [official Codex MCP documentation](https://developers.openai.com/codex/mcp). ### Claude Code ```bash claude mcp add --transport http --scope user apifleet https://apifleet.dev/mcp \ --header "Authorization: Bearer $APIFLEET_API_KEY" ``` The shell expands the variable when this command runs; the saved client configuration contains the key. Keep that configuration private. Use /mcp to inspect the connection. [Official Claude Code setup](https://code.claude.com/docs/en/mcp). ### Cursor In ~/.cursor/mcp.json: ```json { "mcpServers": { "apifleet": { "url": "https://apifleet.dev/mcp", "headers": { "Authorization": "Bearer ${env:APIFLEET_API_KEY}" } } } } ``` Launch Cursor with APIFLEET_API_KEY available in its environment. A desktop app launched separately may not inherit terminal environment variables. [Official Cursor MCP documentation](https://cursor.com/docs/mcp). ### ChatGPT, Claude hosted connectors and Grok Bot Use https://apifleet.dev/mcp only if the client supports supplying an APIFleet Bearer key. If it requires OAuth, this server cannot currently complete that flow. Do not select an unauthenticated connection for private workspace data. These hosted integrations are not claimed as tested or registered APIFleet apps. ChatGPT's custom-MCP setup is documented in [OpenAI's connection guide](https://developers.openai.com/plugins/deploy/connect-chatgpt); account/workspace controls and supported authentication apply. Use one of the key-capable clients above for the documented configuration today. ### Initialize and discover tools ```bash curl https://apifleet.dev/mcp \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "MCP-Protocol-Version: 2025-11-25" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"example-client","version":"1.0.0"}}}' ``` An MCP client sends notifications/initialized after initialization (a notification has no id; the server returns HTTP 202), then tools/list: ```bash curl https://apifleet.dev/mcp \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "MCP-Protocol-Version: 2025-11-25" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' ``` ### Check prepaid access ```bash curl https://apifleet.dev/mcp \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -H "MCP-Protocol-Version: 2025-11-25" \ -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"check_entitlements","arguments":{}}}' ``` This returns billing_model, platform_usd_per_minute, minimum_funding_usd, provider_and_carrier_costs_additional, selected policy fields, wallet and funding_url. It never starts checkout. For every operation below, the MCP example uses the same tools/call envelope and the exact listed arguments. ### Tool result format ```json { "jsonrpc": "2.0", "id": 4, "result": { "content": [ { "type": "text", "text": "[{\"id\":\"ASSISTANT_ID\",\"name\":\"Example receptionist\"}]" } ], "structuredContent": { "status": 200, "data": [ { "id": "ASSISTANT_ID", "name": "Example receptionist" } ] }, "isError": false } } ``` The result above is a shortened illustrative list response; native assistant results include additional configuration fields. A successful DELETE has data: null and status: 204. Parse structuredContent.data, or JSON.parse(content[0].text). Assistant reads/updates can include an etag in structuredContent for revision checks. ## Billing and action costs APIFleet charges USD 0.03 per connected AI minute, billed per second, on top of AI provider and carrier usage. Minimum prepaid top-up is USD 10. No monthly subscription, free trial or free credits. Usage paid directly through customer-owned provider credentials is not charged a second time by APIFleet. Internal exempt workspaces have their own actual billing policy; consumers cannot opt into that exception. Read get_wallet / GET /billing/wallet for balance_microusd, reserved_microusd, available_microusd, spending_blocked, funding_required, collection_enabled and runtime_enforcement_enabled. Divide micro-USD amounts by 1,000,000. check_entitlements combines selected wallet/policy fields; its output is not a guarantee that a provider, number or call is ready. Owners fund at https://apifleet.dev/app/billing. Workspace API keys cannot open the owner-only checkout flow. The MCP tools cannot change a tariff, credit a wallet or mark an unpaid payment as paid. Calls can hold funds while they run; billing is finalized from recorded usage, and held funds are distinct from available funds. Payment records and the ledger are better evidence than a model's estimate. ## Endpoints Examples use placeholder identifiers. Replace them with values returned by your own workspace. Values are examples, not customer results. Resource input fields beyond the common ones below are documented in /docs. ## Assistants ### List assistants Anchor: https://apifleet.dev/docs/api#list-assistants GET /assistants · MCP tool: list_assistants. List assistants in the authenticated workspace. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON array. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/assistants" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_assistants", "arguments": {} } } ``` ### Get assistant Anchor: https://apifleet.dev/docs/api#get-assistant GET /assistants/{id} · MCP tool: get_assistant. Get one assistant belonging to this workspace. Effects: read-only; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/assistants/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_assistant", "arguments": { "id": "RESOURCE_ID" } } } ``` ### Create assistant Anchor: https://apifleet.dev/docs/api#create-assistant POST /assistants · MCP tool: create_assistant. Create a assistant. Saving configuration does not place a call. The REST response includes revision, configuration and attached resource identifiers. Effects: changes workspace state; do not automatically repeat; may reach an external service. - JSON request body: Resource fields. Saving configuration does not place a call. The REST response includes revision, configuration and attached resource identifiers. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - name (body, string): Display name. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - instructions (body, string): Business instructions for the assistant. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - first_message (body, string): Opening message. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - model (body, string): Supported model identifier. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - voice (body, string): Voice identifier. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - pipeline_mode (body, string): realtime | cascading Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/assistants" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Example receptionist","instructions":"Answer questions about opening hours. Do not invent bookings.","first_message":"Hello, how can I help?"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "create_assistant", "arguments": { "data": { "name": "Example receptionist", "instructions": "Answer questions about opening hours. Do not invent bookings.", "first_message": "Hello, how can I help?" } } } } ``` ### Update assistant Anchor: https://apifleet.dev/docs/api#update-assistant PATCH /assistants/{id} · MCP tool: update_assistant. Update selected assistant fields. Omitted fields retain their values. Effects: changes workspace state; do not automatically repeat; may reach an external service. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Resource fields. Saving configuration does not place a call. The REST response includes revision, configuration and attached resource identifiers. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - name (body, string): Display name. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - instructions (body, string): Business instructions for the assistant. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - first_message (body, string): Opening message. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - model (body, string): Supported model identifier. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - voice (body, string): Voice identifier. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - pipeline_mode (body, string): realtime | cascading Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - If-Match (REST header) / if_revision (MCP integer): optional current assistant revision for optimistic concurrency. A stale revision returns 409. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PATCH "https://apifleet.dev/assistants/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Updated example"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "update_assistant", "arguments": { "id": "RESOURCE_ID", "data": { "name": "Updated example" } } } } ``` ### Delete assistant Anchor: https://apifleet.dev/docs/api#delete-assistant DELETE /assistants/{id} · MCP tool: delete_assistant. Delete this assistant. Review the identifier before deleting; the change cannot be undone. Effects: changes workspace state; repeat has the same intended effect; may reach an external service. - id (path, string, required): Resource identifier returned by a previous request. - If-Match (REST header) / if_revision (MCP integer): optional current assistant revision for optimistic concurrency. A stale revision returns 409. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/assistants/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "delete_assistant", "arguments": { "id": "RESOURCE_ID" } } } ``` ### Set assistant tools Anchor: https://apifleet.dev/docs/api#set-assistant-tools PUT /assistants/{id}/tools · MCP tool: set_assistant_tools. Replace all attached HTTP tools with existing tools owned by this workspace. Empty tool_ids detaches every tool. Effects: changes workspace state; repeat has the same intended effect; may reach an external service. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Attachment set. In MCP, put this object in data. - tool_ids (body, array): Complete replacement list; an empty list removes every attachment. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PUT "https://apifleet.dev/assistants/ASSISTANT_ID/tools" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tool_ids":["TOOL_ID"]}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "set_assistant_tools", "arguments": { "id": "ASSISTANT_ID", "data": { "tool_ids": [ "TOOL_ID" ] } } } } ``` ### Set assistant knowledge Anchor: https://apifleet.dev/docs/api#set-assistant-knowledge PUT /assistants/{id}/knowledge · MCP tool: set_assistant_knowledge. Replace all attached knowledge documents. Each document must belong to this workspace. Effects: changes workspace state; repeat has the same intended effect; may reach an external service. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Attachment set. In MCP, put this object in data. - knowledge_ids (body, array): Complete replacement list; an empty list removes every attachment. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PUT "https://apifleet.dev/assistants/ASSISTANT_ID/knowledge" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"knowledge_ids":["DOCUMENT_ID"]}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "set_assistant_knowledge", "arguments": { "id": "ASSISTANT_ID", "data": { "knowledge_ids": [ "DOCUMENT_ID" ] } } } } ``` ### Create browser test token Anchor: https://apifleet.dev/docs/api#create-browser-test-token POST /assistants/{id}/test-token · MCP tool: create_browser_test_token. Issue a short-lived browser voice-test URL. Opening its WebSocket can incur usage. Never publish the returned token. Effects: changes workspace state; do not automatically repeat; may reach an external service. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Test session options. In MCP, put this object in data. - ttl_seconds (body, integer): Token lifetime, clamped to 30–3600 seconds. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - max_duration_seconds (body, integer): Call duration limit, clamped to 30–3600 seconds. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/assistants/ASSISTANT_ID/test-token" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"ttl_seconds":300,"max_duration_seconds":60}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "create_browser_test_token", "arguments": { "id": "ASSISTANT_ID", "data": { "ttl_seconds": 300, "max_duration_seconds": 60 } } } } ``` ## Phone numbers ### List numbers Anchor: https://apifleet.dev/docs/api#list-numbers GET /numbers · MCP tool: list_numbers. List number bindings. This does not buy phone numbers from a carrier. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON array. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/numbers" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_numbers", "arguments": {} } } ``` ### Bind number Anchor: https://apifleet.dev/docs/api#bind-number PUT /numbers/{number} · MCP tool: bind_number. Bind an existing carrier number to a workspace assistant. This changes incoming call routing; configure the carrier webhook separately. Effects: changes workspace state; do not automatically repeat. - number (path, string, required): International E.164 number, including the leading +. - JSON request body: Number binding. In MCP, put this object in data. - assistant_id (body, string): Resource identifier returned by a previous request. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - provider (body, string): telnyx | twilio | voximplant | voipcloud Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - region (body, string): Carrier region, when required. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PUT "https://apifleet.dev/numbers/%2B13125550100" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"assistant_id":"ASSISTANT_ID","provider":"telnyx"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "bind_number", "arguments": { "number": "+13125550100", "data": { "assistant_id": "ASSISTANT_ID", "provider": "telnyx" } } } } ``` ### Unbind number Anchor: https://apifleet.dev/docs/api#unbind-number DELETE /numbers/{number} · MCP tool: unbind_number. Remove the routing binding. This does not release or cancel the carrier number. Effects: changes workspace state; repeat has the same intended effect. - number (path, string, required): International E.164 number, including the leading +. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/numbers/%2B13125550100" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "unbind_number", "arguments": { "number": "+13125550100" } } } ``` ## Calls ### List calls Anchor: https://apifleet.dev/docs/api#list-calls GET /calls · MCP tool: list_calls. Read call logs, summary statistics and pagination. Each row may contain transcript, analysis, costs and recording links; recordings require separate authentication. Effects: read-only; repeat has the same intended effect. - page (query, integer, optional): Page number; default 1. - limit (query, integer, optional): Rows per page; default 200, maximum 1000. - search (query, string, optional): Text or call identifier search. - assistant_id (query, string, optional): Resource identifier returned by a previous request. - source (query, string, optional): Call source filter. - model (query, string, optional): Model filter. - voice (query, string, optional): Voice filter. - outcome (query, string, optional): Outcome filter. - sentiment (query, string, optional): Sentiment filter. - date_from (query, string, optional): Start date filter. - date_to (query, string, optional): End date filter. - sort (query, string, optional): Supported sort column; default started_at. - order (query, string, optional): Filter. Allowed: asc, desc. Response: HTTP 200 with a JSON object. An object containing calls[], stats and pagination, not a bare array. REST example: ```bash curl "https://apifleet.dev/calls?page=1&limit=10" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_calls", "arguments": { "page": 1, "limit": 10 } } } ``` ### Create outbound call Anchor: https://apifleet.dev/docs/api#create-outbound-call POST /calls/outbound · MCP tool: create_outbound_call. Place a real telephone call. Ask the user to approve recipient, caller number and expected usage first. Billing/provider/carrier checks are the same as REST. No automatic retry or universal idempotency guarantee. Effects: changes workspace state; do not automatically repeat; can incur usage; may reach an external service. - JSON request body: Call request. In MCP, put this object in data. - assistant_id (body, string): Resource identifier returned by a previous request. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - to (body, string): International E.164 number, including the leading +. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - from (body, string): International E.164 number, including the leading +. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - user_number (body, string): International E.164 number, including the leading +. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - confirm (MCP boolean, required): must be true after the user approves this paid action. Not part of the REST body. Response: HTTP 201 with a JSON object. 201 means the carrier accepted initiation; it does not mean the conversation completed. Inspect call logs afterward. REST example: ```bash curl -X POST "https://apifleet.dev/calls/outbound" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"assistant_id":"ASSISTANT_ID","to":"+13125550101","from":"+13125550100"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "create_outbound_call", "arguments": { "data": { "assistant_id": "ASSISTANT_ID", "to": "+13125550101", "from": "+13125550100" }, "confirm": true } } } ``` ### Get recording Anchor: https://apifleet.dev/docs/api#get-recording GET /calls/{id}/recording · MCP: unavailable for this workflow; use REST or the dashboard. Download authenticated recording bytes, supporting Range requests. Keep customer recordings private. Effects: read-only; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: Binary audio response; this is not a JSON document. REST example: ```bash curl "https://apifleet.dev/calls/CALL_ID/recording" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ --output recording.wav ``` ### Get waveform Anchor: https://apifleet.dev/docs/api#get-waveform GET /calls/{id}/waveform · MCP tool: get_waveform. Read recording waveform metadata and available audio channels. Effects: read-only; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/calls/CALL_ID/waveform" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_waveform", "arguments": { "id": "CALL_ID" } } } ``` ### Delete recording Anchor: https://apifleet.dev/docs/api#delete-recording DELETE /calls/{id}/recording · MCP tool: delete_recording. Permanently remove a call recording. The call log remains. Confirm the identifier before deleting. Effects: changes workspace state; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/calls/CALL_ID/recording" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "delete_recording", "arguments": { "id": "CALL_ID" } } } ``` ## HTTP tools ### List tools Anchor: https://apifleet.dev/docs/api#list-tools GET /tools · MCP tool: list_tools. List http tools in the authenticated workspace. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON array. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/tools" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_tools", "arguments": {} } } ``` ### Get tool Anchor: https://apifleet.dev/docs/api#get-tool GET /tools/{id} · MCP tool: get_tool. Get one tool belonging to this workspace. Effects: read-only; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/tools/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_tool", "arguments": { "id": "RESOURCE_ID" } } } ``` ### Create tool Anchor: https://apifleet.dev/docs/api#create-tool POST /tools · MCP tool: create_tool. Create a tool. Creating a tool returns its signing secret once. Configuring a tool does not invoke its URL; attached tools can call it during conversations. Effects: changes workspace state; do not automatically repeat. - JSON request body: Resource fields. Creating a tool returns its signing secret once. Configuring a tool does not invoke its URL; attached tools can call it during conversations. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - name (body, string): Function name: letters, digits and underscore; cannot start with a digit. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - url (body, string): Public HTTPS callback URL; private network targets are rejected. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - method (body, string): GET | POST | PUT | PATCH | DELETE Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - description (body, string): Tool purpose. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - parameters (body, object): JSON Schema for tool arguments. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - timeout_ms (body, integer): Resource option. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/tools" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"lookup_hours","description":"Read opening hours.","url":"https://example.com/voice/hours","method":"GET","parameters":{"type":"object","properties":{}}}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "create_tool", "arguments": { "data": { "name": "lookup_hours", "description": "Read opening hours.", "url": "https://example.com/voice/hours", "method": "GET", "parameters": { "type": "object", "properties": {} } } } } } ``` ### Update tool Anchor: https://apifleet.dev/docs/api#update-tool PATCH /tools/{id} · MCP tool: update_tool. Update selected tool fields. Omitted fields retain their values. Effects: changes workspace state; do not automatically repeat. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Resource fields. Creating a tool returns its signing secret once. Configuring a tool does not invoke its URL; attached tools can call it during conversations. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - name (body, string): Function name: letters, digits and underscore; cannot start with a digit. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - url (body, string): Public HTTPS callback URL; private network targets are rejected. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - method (body, string): GET | POST | PUT | PATCH | DELETE Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - description (body, string): Tool purpose. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - parameters (body, object): JSON Schema for tool arguments. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - timeout_ms (body, integer): Resource option. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PATCH "https://apifleet.dev/tools/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Updated example"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "update_tool", "arguments": { "id": "RESOURCE_ID", "data": { "name": "Updated example" } } } } ``` ### Delete tool Anchor: https://apifleet.dev/docs/api#delete-tool DELETE /tools/{id} · MCP tool: delete_tool. Delete this tool. Review the identifier before deleting; the change cannot be undone. Effects: changes workspace state; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/tools/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "delete_tool", "arguments": { "id": "RESOURCE_ID" } } } ``` ## Knowledge ### List knowledge documents Anchor: https://apifleet.dev/docs/api#list-knowledge-documents GET /knowledge · MCP tool: list_knowledge_documents. List knowledge in the authenticated workspace. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON array. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/knowledge" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_knowledge_documents", "arguments": {} } } ``` ### Get knowledge document Anchor: https://apifleet.dev/docs/api#get-knowledge-document GET /knowledge/{id} · MCP tool: get_knowledge_document. Get one knowledge document belonging to this workspace. Effects: read-only; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/knowledge/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_knowledge_document", "arguments": { "id": "RESOURCE_ID" } } } ``` ### Create knowledge document Anchor: https://apifleet.dev/docs/api#create-knowledge-document POST /knowledge · MCP tool: create_knowledge_document. Create a knowledge document. Attach documents separately to use them in an assistant. Total injected knowledge has a 200 KiB limit. Effects: changes workspace state; do not automatically repeat. - JSON request body: Resource fields. Attach documents separately to use them in an assistant. Total injected knowledge has a 200 KiB limit. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - name (body, string): Unique document name in this workspace. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - content (body, string): Plain text; maximum 50 KiB per document. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - source (body, string): Source label; defaults to text. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/knowledge" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Opening hours","content":"Open Monday to Friday, 09:00–17:00.","source":"text"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "create_knowledge_document", "arguments": { "data": { "name": "Opening hours", "content": "Open Monday to Friday, 09:00–17:00.", "source": "text" } } } } ``` ### Update knowledge document Anchor: https://apifleet.dev/docs/api#update-knowledge-document PATCH /knowledge/{id} · MCP tool: update_knowledge_document. Update selected knowledge document fields. Omitted fields retain their values. Effects: changes workspace state; do not automatically repeat. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Resource fields. Attach documents separately to use them in an assistant. Total injected knowledge has a 200 KiB limit. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - name (body, string): Unique document name in this workspace. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - content (body, string): Plain text; maximum 50 KiB per document. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - source (body, string): Source label; defaults to text. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PATCH "https://apifleet.dev/knowledge/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Updated example"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "update_knowledge_document", "arguments": { "id": "RESOURCE_ID", "data": { "name": "Updated example" } } } } ``` ### Delete knowledge document Anchor: https://apifleet.dev/docs/api#delete-knowledge-document DELETE /knowledge/{id} · MCP tool: delete_knowledge_document. Delete this knowledge document. Review the identifier before deleting; the change cannot be undone. Effects: changes workspace state; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/knowledge/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "delete_knowledge_document", "arguments": { "id": "RESOURCE_ID" } } } ``` ## Webhooks ### List webhooks Anchor: https://apifleet.dev/docs/api#list-webhooks GET /webhooks · MCP tool: list_webhooks. List webhooks in the authenticated workspace. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON array. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/webhooks" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_webhooks", "arguments": {} } } ``` ### Create webhook Anchor: https://apifleet.dev/docs/api#create-webhook POST /webhooks · MCP tool: create_webhook. Create a webhook. Creation returns a signing secret once; verify delivery signatures against the raw body. Events may be retried. Effects: changes workspace state; do not automatically repeat. - JSON request body: Resource fields. Creation returns a signing secret once; verify delivery signatures against the raw body. Events may be retried. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - url (body, string): Public HTTPS receiver. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - events (body, array): Resource option. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - enabled (body, boolean): Resource option. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/webhooks" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url":"https://example.com/hooks/apifleet","events":["call.ended"]}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "create_webhook", "arguments": { "data": { "url": "https://example.com/hooks/apifleet", "events": [ "call.ended" ] } } } } ``` ### Update webhook Anchor: https://apifleet.dev/docs/api#update-webhook PATCH /webhooks/{id} · MCP tool: update_webhook. Update selected webhook fields. Omitted fields retain their values. Effects: changes workspace state; do not automatically repeat. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Resource fields. Creation returns a signing secret once; verify delivery signatures against the raw body. Events may be retried. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - url (body, string): Public HTTPS receiver. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - events (body, array): Resource option. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - enabled (body, boolean): Resource option. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PATCH "https://apifleet.dev/webhooks/WEBHOOK_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"enabled":false}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "update_webhook", "arguments": { "id": "WEBHOOK_ID", "data": { "enabled": false } } } } ``` ### Delete webhook Anchor: https://apifleet.dev/docs/api#delete-webhook DELETE /webhooks/{id} · MCP tool: delete_webhook. Delete this webhook. Review the identifier before deleting; the change cannot be undone. Effects: changes workspace state; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/webhooks/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "delete_webhook", "arguments": { "id": "RESOURCE_ID" } } } ``` ## Simulation personas ### List simulation personas Anchor: https://apifleet.dev/docs/api#list-simulation-personas GET /simulations/personas · MCP tool: list_simulation_personas. List simulation personas in the authenticated workspace. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON array. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/simulations/personas" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_simulation_personas", "arguments": {} } } ``` ### Get simulation persona Anchor: https://apifleet.dev/docs/api#get-simulation-persona GET /simulations/personas/{id} · MCP tool: get_simulation_persona. Get one simulation persona belonging to this workspace. Effects: read-only; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/simulations/personas/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_simulation_persona", "arguments": { "id": "RESOURCE_ID" } } } ``` ### Create simulation persona Anchor: https://apifleet.dev/docs/api#create-simulation-persona POST /simulations/personas · MCP tool: create_simulation_persona. Create a simulation persona. Effects: changes workspace state; do not automatically repeat. - JSON request body: Resource fields. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - name (body, string): Persona name. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - system_prompt (body, string): Instructions for the simulated caller. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/simulations/personas" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Opening-hours caller","system_prompt":"Ask when the business closes on Friday."}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "create_simulation_persona", "arguments": { "data": { "name": "Opening-hours caller", "system_prompt": "Ask when the business closes on Friday." } } } } ``` ### Update simulation persona Anchor: https://apifleet.dev/docs/api#update-simulation-persona PATCH /simulations/personas/{id} · MCP tool: update_simulation_persona. Update selected simulation persona fields. Omitted fields retain their values. Effects: changes workspace state; do not automatically repeat. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Resource fields. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - name (body, string): Persona name. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - system_prompt (body, string): Instructions for the simulated caller. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PATCH "https://apifleet.dev/simulations/personas/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Updated example"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "update_simulation_persona", "arguments": { "id": "RESOURCE_ID", "data": { "name": "Updated example" } } } } ``` ### Delete simulation persona Anchor: https://apifleet.dev/docs/api#delete-simulation-persona DELETE /simulations/personas/{id} · MCP tool: delete_simulation_persona. Delete this simulation persona. Review the identifier before deleting; the change cannot be undone. Effects: changes workspace state; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/simulations/personas/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "delete_simulation_persona", "arguments": { "id": "RESOURCE_ID" } } } ``` ## Simulation scenarios ### List simulation scenarios Anchor: https://apifleet.dev/docs/api#list-simulation-scenarios GET /simulations/scenarios · MCP tool: list_simulation_scenarios. List simulation scenarios in the authenticated workspace. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON array. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/simulations/scenarios" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_simulation_scenarios", "arguments": {} } } ``` ### Get simulation scenario Anchor: https://apifleet.dev/docs/api#get-simulation-scenario GET /simulations/scenarios/{id} · MCP tool: get_simulation_scenario. Get one simulation scenario belonging to this workspace. Effects: read-only; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/simulations/scenarios/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_simulation_scenario", "arguments": { "id": "RESOURCE_ID" } } } ``` ### Create simulation scenario Anchor: https://apifleet.dev/docs/api#create-simulation-scenario POST /simulations/scenarios · MCP tool: create_simulation_scenario. Create a simulation scenario. Effects: changes workspace state; do not automatically repeat. - JSON request body: Resource fields. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - name (body, string): Scenario name. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - instructions (body, string): Scenario instructions. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - evaluations (body, array): Resource option. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/simulations/scenarios" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Ask opening hours","instructions":"Find out when the business closes on Friday.","evaluations":[{"kind":"transcript","role":"assistant","includes":"17:00"}]}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "create_simulation_scenario", "arguments": { "data": { "name": "Ask opening hours", "instructions": "Find out when the business closes on Friday.", "evaluations": [ { "kind": "transcript", "role": "assistant", "includes": "17:00" } ] } } } } ``` ### Update simulation scenario Anchor: https://apifleet.dev/docs/api#update-simulation-scenario PATCH /simulations/scenarios/{id} · MCP tool: update_simulation_scenario. Update selected simulation scenario fields. Omitted fields retain their values. Effects: changes workspace state; do not automatically repeat. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Resource fields. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - name (body, string): Scenario name. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - instructions (body, string): Scenario instructions. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - evaluations (body, array): Resource option. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PATCH "https://apifleet.dev/simulations/scenarios/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Updated example"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "update_simulation_scenario", "arguments": { "id": "RESOURCE_ID", "data": { "name": "Updated example" } } } } ``` ### Delete simulation scenario Anchor: https://apifleet.dev/docs/api#delete-simulation-scenario DELETE /simulations/scenarios/{id} · MCP tool: delete_simulation_scenario. Delete this simulation scenario. Review the identifier before deleting; the change cannot be undone. Effects: changes workspace state; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/simulations/scenarios/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "delete_simulation_scenario", "arguments": { "id": "RESOURCE_ID" } } } ``` ## Simulations ### List simulations Anchor: https://apifleet.dev/docs/api#list-simulations GET /simulations · MCP tool: list_simulations. List simulations in the authenticated workspace. Effects: read-only; repeat has the same intended effect. - assistant_id (query, string, optional): Resource identifier returned by a previous request. Response: HTTP 200 with a JSON array. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/simulations" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_simulations", "arguments": {} } } ``` ### Get simulation Anchor: https://apifleet.dev/docs/api#get-simulation GET /simulations/{id} · MCP tool: get_simulation. Get one simulation belonging to this workspace. Effects: read-only; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/simulations/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_simulation", "arguments": { "id": "RESOURCE_ID" } } } ``` ### Create simulation Anchor: https://apifleet.dev/docs/api#create-simulation POST /simulations · MCP tool: create_simulation. Create a simulation. Effects: changes workspace state; do not automatically repeat. - JSON request body: Resource fields. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - assistant_id (body, string): Resource identifier returned by a previous request. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - persona_id (body, string): Resource identifier returned by a previous request. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - scenario_id (body, string): Resource identifier returned by a previous request. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - name (body, string): Optional simulation name. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/simulations" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"assistant_id":"ASSISTANT_ID","persona_id":"PERSONA_ID","scenario_id":"SCENARIO_ID"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "create_simulation", "arguments": { "data": { "assistant_id": "ASSISTANT_ID", "persona_id": "PERSONA_ID", "scenario_id": "SCENARIO_ID" } } } } ``` ### Update simulation Anchor: https://apifleet.dev/docs/api#update-simulation PATCH /simulations/{id} · MCP tool: update_simulation. Update selected simulation fields. Omitted fields retain their values. Effects: changes workspace state; do not automatically repeat. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Resource fields. Additional settings are documented in https://apifleet.dev/docs In MCP, put this object in data. - assistant_id (body, string): Resource identifier returned by a previous request. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - persona_id (body, string): Resource identifier returned by a previous request. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - scenario_id (body, string): Resource identifier returned by a previous request. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - name (body, string): Optional simulation name. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PATCH "https://apifleet.dev/simulations/SIMULATION_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Friday hours check"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "update_simulation", "arguments": { "id": "SIMULATION_ID", "data": { "name": "Friday hours check" } } } } ``` ### Delete simulation Anchor: https://apifleet.dev/docs/api#delete-simulation DELETE /simulations/{id} · MCP tool: delete_simulation. Delete this simulation. Review the identifier before deleting; the change cannot be undone. Effects: changes workspace state; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/simulations/RESOURCE_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "delete_simulation", "arguments": { "id": "RESOURCE_ID" } } } ``` ## Simulation runs ### List simulation runs Anchor: https://apifleet.dev/docs/api#list-simulation-runs GET /simulations/runs · MCP tool: list_simulation_runs. List simulation runs and pagination; inspect status before starting another run. Effects: read-only; repeat has the same intended effect. - assistant_id (query, string, optional): Resource identifier returned by a previous request. - simulation_id (query, string, optional): Resource identifier returned by a previous request. - batch_id (query, string, optional): Resource identifier returned by a previous request. - status (query, string, optional): Filter. Allowed: queued, running, completed, error. - page (query, integer, optional): Page number. - limit (query, integer, optional): Rows per page. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/simulations/runs?page=1&limit=10" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_simulation_runs", "arguments": { "page": 1, "limit": 10 } } } ``` ### Get simulation run Anchor: https://apifleet.dev/docs/api#get-simulation-run GET /simulations/runs/{id} · MCP tool: get_simulation_run. Read a run, its evaluations and linked call when available. Effects: read-only; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/simulations/runs/RUN_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_simulation_run", "arguments": { "id": "RUN_ID" } } } ``` ### Delete simulation run Anchor: https://apifleet.dev/docs/api#delete-simulation-run DELETE /simulations/runs/{id} · MCP tool: delete_simulation_run. Delete a completed simulation result. Running runs may reject deletion. Effects: changes workspace state; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/simulations/runs/RUN_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "delete_simulation_run", "arguments": { "id": "RUN_ID" } } } ``` ### Start simulation run Anchor: https://apifleet.dev/docs/api#start-simulation-run POST /simulations/{id}/runs · MCP tool: start_simulation_run. Queue an asynchronous test. Models and speech can incur usage. Approve the run first and poll the returned identifier; do not enqueue again while it is running. Effects: changes workspace state; do not automatically repeat; can incur usage; may reach an external service. - id (path, string, required): Resource identifier returned by a previous request. - JSON request body: Run options. In MCP, put this object in data. - mode (body, string): chat | voice Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - confirm (MCP boolean, required): must be true after the user approves this paid action. Not part of the REST body. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/simulations/SIMULATION_ID/runs" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"mode":"chat"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "start_simulation_run", "arguments": { "id": "SIMULATION_ID", "data": { "mode": "chat" }, "confirm": true } } } ``` ### Start simulation batch Anchor: https://apifleet.dev/docs/api#start-simulation-batch POST /simulations/runs/batch · MCP tool: start_simulation_batch. Queue every simulation for one assistant. This can incur multiple test runs; approve the batch first. Effects: changes workspace state; do not automatically repeat; can incur usage; may reach an external service. - JSON request body: Batch options. In MCP, put this object in data. - assistant_id (body, string): Resource identifier returned by a previous request. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - mode (body, string): chat | voice Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. - confirm (MCP boolean, required): must be true after the user approves this paid action. Not part of the REST body. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/simulations/runs/batch" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"assistant_id":"ASSISTANT_ID","mode":"chat"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "start_simulation_batch", "arguments": { "data": { "assistant_id": "ASSISTANT_ID", "mode": "chat" }, "confirm": true } } } ``` ## Voice and speech ### List tts rates Anchor: https://apifleet.dev/docs/api#list-tts-rates GET /tts/rates · MCP tool: list_tts_rates. Read configured voice-cost reference rates. These are not an invoice or a complete call price. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/tts/rates" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_tts_rates", "arguments": {} } } ``` ### List tts voices Anchor: https://apifleet.dev/docs/api#list-tts-voices GET /tts/voices · MCP tool: list_tts_voices. Read a provider voice catalog using configured server-side credentials. Catalog failure may return an empty list and error; it is not evidence the provider has no voices. Effects: read-only; repeat has the same intended effect; may reach an external service. - provider (query, string, optional): Voice provider identifier. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/tts/voices?provider=piper" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_tts_voices", "arguments": { "provider": "piper" } } } ``` ### List voice presets Anchor: https://apifleet.dev/docs/api#list-voice-presets GET /voice-presets · MCP tool: list_voice_presets. Read configured runnable voice presets. Provider catalog requests may reach a vendor. Effects: read-only; repeat has the same intended effect; may reach an external service. - provider (query, string, optional): Optional catalog provider. - realtime_provider (query, string, optional): Optional realtime provider. - model (query, string, optional): Optional realtime model. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/voice-presets" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_voice_presets", "arguments": {} } } ``` ### Get assistant voice presets Anchor: https://apifleet.dev/docs/api#get-assistant-voice-presets GET /assistants/{id}/voice-presets · MCP tool: get_assistant_voice_presets. Read voices compatible with this assistant configuration. Effects: read-only; repeat has the same intended effect; may reach an external service. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/assistants/ASSISTANT_ID/voice-presets" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_assistant_voice_presets", "arguments": { "id": "ASSISTANT_ID" } } } ``` ### Get tts settings Anchor: https://apifleet.dev/docs/api#get-tts-settings GET /tts/settings-spec · MCP tool: get_tts_settings. Read supported provider voice settings and validation ranges. Effects: read-only; repeat has the same intended effect. - provider (query, string, optional): Optional voice provider. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/tts/settings-spec?provider=piper" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_tts_settings", "arguments": { "provider": "piper" } } } ``` ### Preview voice Anchor: https://apifleet.dev/docs/api#preview-voice POST /tts/preview · MCP: unavailable for this workflow; use REST or the dashboard. Generate a short fixed voice sample. Can incur provider usage; returns audio bytes. Play from the dashboard or call REST directly. Effects: changes workspace state; do not automatically repeat; can incur usage; may reach an external service. - JSON request body: Voice provider and voice selection; see Models & voices. In MCP, put this object in data. Response: Binary audio response; this is not a JSON document. REST example: ```bash curl -X POST "https://apifleet.dev/tts/preview" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"provider":"piper","voice":"en_US-lessac-medium"}' \ --output voice-sample.audio ``` ### Transcribe audio Anchor: https://apifleet.dev/docs/api#transcribe-audio POST /stt/transcribe · MCP: unavailable for this workflow; use REST or the dashboard. Transcribe an uploaded or inline audio sample. Can incur provider usage. Use the REST audio-upload contract; live call transcription is configured on the assistant. Effects: changes workspace state; do not automatically repeat; can incur usage; may reach an external service. - JSON request body: Audio request; see the speech transcription section. In MCP, put this object in data. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/stt/transcribe" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"audio_base64":"BASE64_AUDIO","mime_type":"audio/wav"}' ``` ## Credentials ### List provider credentials Anchor: https://apifleet.dev/docs/api#list-provider-credentials GET /credentials · MCP tool: list_provider_credentials. List which provider credentials are configured. Returns metadata only, never provider secret values. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON array. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/credentials" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_provider_credentials", "arguments": {} } } ``` ### Set provider credentials Anchor: https://apifleet.dev/docs/api#set-provider-credentials PUT /credentials/{provider} · MCP: unavailable for this workflow; use REST or the dashboard. Store provider credentials through a trusted backend or the dashboard. Do not paste provider secrets into a model conversation. Provider fields vary; see Tenant credentials. Effects: changes workspace state; do not automatically repeat. - provider (path, string, required): Provider identifier, e.g. openai or telnyx. - JSON request body: Provider-specific secret fields. In MCP, put this object in data. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X PUT "https://apifleet.dev/credentials/openai" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"api_key":"YOUR_PROVIDER_KEY"}' ``` ### Delete provider credentials Anchor: https://apifleet.dev/docs/api#delete-provider-credentials DELETE /credentials/{provider} · MCP: unavailable for this workflow; use REST or the dashboard. Remove a provider credential. Dependent live calls may stop working. Use REST or the credentials dashboard. Effects: changes workspace state; repeat has the same intended effect. - provider (path, string, required): Provider identifier. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/credentials/openai" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` ## API keys ### List api keys Anchor: https://apifleet.dev/docs/api#list-api-keys GET /api-keys · MCP tool: list_api_keys. List this workspace API-key metadata. Full key values cannot be retrieved. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON array. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/api-keys" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_api_keys", "arguments": {} } } ``` ### Create api key Anchor: https://apifleet.dev/docs/api#create-api-key POST /api-keys · MCP tool: create_api_key. Create a new full workspace key. The secret is returned once. Store it privately; never put it in public client code. Effects: changes workspace state; do not automatically repeat. - JSON request body: Key label. In MCP, put this object in data. - name (body, string): Human-readable key label. Fields omitted on PATCH retain their current values; creation requirements are validated by the resource handler. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl -X POST "https://apifleet.dev/api-keys" \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Backend integration"}' ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "create_api_key", "arguments": { "data": { "name": "Backend integration" } } } } ``` ### Revoke api key Anchor: https://apifleet.dev/docs/api#revoke-api-key DELETE /api-keys/{id} · MCP tool: revoke_api_key. Revoke a workspace API key immediately. Revoking the key in use disconnects this MCP client on its next request. Effects: changes workspace state; repeat has the same intended effect. - id (path, string, required): Resource identifier returned by a previous request. Response: HTTP 204 with an empty body on success. REST example: ```bash curl -X DELETE "https://apifleet.dev/api-keys/KEY_ID" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "revoke_api_key", "arguments": { "id": "KEY_ID" } } } ``` ## Billing ### Get wallet Anchor: https://apifleet.dev/docs/api#get-wallet GET /billing/wallet · MCP tool: get_wallet. Read available, reserved and total prepaid funds, policy, funding availability and runtime enforcement. Amounts ending in microusd are integer millionths of a USD. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/billing/wallet" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_wallet", "arguments": {} } } ``` ### Get billing policy Anchor: https://apifleet.dev/docs/api#get-billing-policy GET /billing/policy · MCP tool: get_billing_policy. Read the actual workspace policy. Internal exempt workspaces can differ from the public tariff. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/billing/policy" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_billing_policy", "arguments": {} } } ``` ### List balance activity Anchor: https://apifleet.dev/docs/api#list-balance-activity GET /billing/ledger · MCP tool: list_balance_activity. Read balance activity and pagination cursor. Funding is credited only after verified payment processing. Effects: read-only; repeat has the same intended effect. - limit (query, integer, optional): Maximum entries; defaults to 50. - before (query, integer, optional): Return entries before this ledger identifier. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/billing/ledger?limit=10" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_balance_activity", "arguments": { "limit": 10 } } } ``` ### List payments Anchor: https://apifleet.dev/docs/api#list-payments GET /billing/payments · MCP tool: list_payments. Read confirmed and pending workspace payment records for the configured live/test environment. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/billing/payments" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "list_payments", "arguments": {} } } ``` ### Create checkout Anchor: https://apifleet.dev/docs/api#create-checkout POST /billing/checkout · MCP: unavailable for this workflow; use REST or the dashboard. Open the owner-only funding flow from the billing dashboard. Workspace API keys cannot start checkout. Effects: changes workspace state; do not automatically repeat. - JSON request body: Checkout is initiated by the dashboard; no amount body is accepted here. In MCP, put this object in data. Response: HTTP 201 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash # Owner session required; integrations normally use /app/billing. # APIFLEET_DASHBOARD_SESSION is the private af_session cookie value. curl -X POST "https://apifleet.dev/billing/checkout" \ --cookie "af_session=$APIFLEET_DASHBOARD_SESSION" \ -H "Origin: https://apifleet.dev" \ -H "Content-Type: application/json" \ -d '{}' ``` ## Metrics ### Get metrics Anchor: https://apifleet.dev/docs/api#get-metrics GET /metrics · MCP tool: get_metrics. Read the authenticated workspace metrics snapshot. Metrics may reset with the application process and are not a complete billing ledger. Effects: read-only; repeat has the same intended effect. No parameters. Response: HTTP 200 with a JSON object. Response fields match the native REST operation; errors retain their native shape. REST example: ```bash curl "https://apifleet.dev/metrics" \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` MCP request body (POST to https://apifleet.dev/mcp with the Bearer and JSON headers above): ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_metrics", "arguments": {} } } ``` --- # APIFleet API Docs: additional configuration Source: https://apifleet.dev/docs - APIFleet API Docs - - - - API Reference [Quick start](#quickstart) [Endpoint & MCP examples](https://apifleet.dev/docs/api) [Authentication](#auth) [Base URL & format](#base) [MCP connection & tools](#mcp) [Prepaid billing](#billing) [Telecom providers](#providers) [Assistants](#assistants) [Phone numbers](#numbers) [Call logs](#calls) [Post-call analytics](#analytics) [Metrics & latency](#metrics) [Tenant credentials](#credentials) [Outbound calls](#outbound) [Tools](#tools) [Built-in tools](#builtins) [DTMF (keypad)](#dtmf) [Voicemail](#voicemail) [Knowledge base](#knowledge) [Simulations](#simulations) [Webhooks](#webhooks) [Models & voices](#models) [Errors](#errors) # APIFleet API Build voice assistants programmatically. Create an assistant, point a phone number at it, and your callers talk to the selected OpenAI or Gemini realtime provider. Every call is logged, costed, and (optionally) forwarded to your backend via signed webhooks. ## Quick start - Sign in at [APIFleet](https://apifleet.dev/app/assistants) with Google or an email sign-in link. Your tenant is provisioned on first login. - Create an API key in the dashboard under API keys. Copy it once — it starts with af_live_. - Create an assistant: ``` curl -X POST https://apifleet.dev/assistants \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Front desk", "instructions": "You are a friendly receptionist for Acme Clinic. Answer questions about hours and bookings.", "first_message": "Thanks for calling Acme, how can I help?", "realtime_provider": "openai", "model": "gpt-realtime-2.1", "voice": "marin" }' ``` - Bind a phone number on a supported provider (Telnyx, Twilio, Voximplant, VoIPCloud). E.164, no spaces: ``` curl -X PUT https://apifleet.dev/numbers/+13125550100 \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"assistant_id": "", "provider": "telnyx"}' ``` provider defaults to telnyx. See [Telecom providers](#providers) for the per-provider webhook URL and setup. - Point your provider at us. Configure your number's voice webhook URL — depending on provider: - Telnyx → https://apifleet.dev/telnyx/route - Twilio → https://apifleet.dev/twilio/route - Voximplant → https://apifleet.dev/voximplant/route (queried from a VoxEngine scenario) - VoIPCloud → https://apifleet.dev/voipcloud/route (PBX queries for forward target) Call the number — you should reach the assistant. Don't want to set up Telnyx yet? Use the Test in browser button in the dashboard to talk to your assistant from the browser with your microphone — the call is logged the same way as a phone call. ## Authentication Every request to a tenant-scoped endpoint must include a Bearer token: ``` Authorization: Bearer af_live_… ``` Keys are shown once at creation and stored hashed (SHA-256). You can revoke them anytime from the dashboard. Three invalid credentials from the same IP within 5 minutes triggers a temporary 429. The dashboard itself uses a session cookie set after Google or email-link sign-in — you don't need an API key for the UI. ## Base URL & format - Base URL: https://apifleet.dev - Request bodies: JSON (Content-Type: application/json) - Responses: JSON, UTF-8 - Timestamps: ISO 8601 (UTC) - Phone numbers: E.164 (+13125550100) — required on bind ## MCP and paired API examples Connect a Bearer-key-capable MCP client to https://apifleet.dev/mcp. REST and MCP use the same workspace handlers, resource ownership checks and billing gates. Use the [complete endpoint and tool reference](https://apifleet.dev/docs/api) for each action's parameters, response, REST request and MCP request. The [MCP connection guide](https://apifleet.dev/docs/mcp) includes Codex, Claude Code and Cursor configuration, initialization, tool discovery, structured results and paid-action approval. Read [authentication](https://apifleet.dev/docs/authentication) and [errors](https://apifleet.dev/docs/errors) before writing an integration. Keys have full workspace access; no MCP OAuth flow is currently offered. Owner checkout, provider secret entry and binary audio workflows are marked REST/dashboard-only. MCP tools can manage configuration and start approved paid calls or tests; inspect their annotations and confirm the user's intent before invoking changes. ## Prepaid billing The platform fee is USD 0.03 per connected AI minute, billed per second, in addition to provider and carrier usage. Top-ups start at USD 10. There is no monthly subscription, free trial or free credit. Usage paid directly through customer-owned provider credentials is not charged twice by APIFleet. GET /billing/wallet returns the workspace's balance, reserved and available amounts in integer micro-USD: divide available_microusd by 1,000,000 to display USD. GET /billing/policy returns the workspace's actual policy; internal exempt workspaces can have a different policy. Funding availability and runtime enforcement are returned by the wallet endpoint. A workspace API key can read these endpoints but cannot use it to start a checkout. Owners add funds through [Billing](https://apifleet.dev/app/billing) and manage provider keys under [Credentials](https://apifleet.dev/app/credentials). ``` curl https://apifleet.dev/billing/wallet \ -H "Authorization: Bearer $APIFLEET_API_KEY" curl https://apifleet.dev/billing/policy \ -H "Authorization: Bearer $APIFLEET_API_KEY" ``` Inspect the billing_insufficient_balance code on paid-operation errors and follow the funding URL when returned. Do not blindly retry an outbound call: a timeout does not establish whether the carrier accepted it. Confirm call state before placing another call. MCP paid actions require explicit acknowledgment. ## Telecom providers A phone number is bound to one telecom provider via the provider field on the binding. The provider determines which webhook URL to configure on the provider side, and how the live media is bridged. | Provider | Webhook URL | Inbound | Outbound dial | Transfer / DTMF | | --- | --- | --- | --- | --- | | Telnyx | /telnyx/route | Full bridge (TeXML + media stream) | Yes (TeXML Calls API) | Yes (Call Control) | | Twilio | /twilio/route | Full bridge (TwiML ) | Yes (REST /Calls.json) | Yes (Update Call w/ TwiML) | | Voximplant | /voximplant/route (JSON) | Full bridge (VoxEngine scenario relays slin16 PCM) | Yes (Management API StartScenarios) | No (use Voximplant SDK directly) | | VoIPCloud | /voipcloud/route (JSON) | Routing-only — PBX forwards to a sibling number on Telnyx/Twilio | Click-to-call (call-to-number API) | No (use BYO SIP trunk pattern) | ### Telnyx setup - Create a TeXML application; set Inbound voice URL to https://apifleet.dev/telnyx/route. - Assign your number to that application. - (Optional) Set TELNYX_ROUTE_SECRET in your tenant env and add header x-telnyx-route-secret on the app. - For outbound + transfer + DTMF, also set TELNYX_API_KEY and TELNYX_CONNECTION_ID server-side. ### Twilio setup - In the Twilio console, open the phone number → Voice → A call comes in. - Set webhook to https://apifleet.dev/twilio/route (HTTP POST). - Bind the number with "provider": "twilio" via PUT /numbers/:number. - For outbound + transfer + DTMF set TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN server-side. ### Voximplant setup Voximplant scenarios run JavaScript in their cloud — bind a minimal scenario like this: ``` // VoxEngine scenario — fetch our routing decision then bridge raw audio. require(Modules.WebSocket); VoxEngine.addEventListener(AppEvents.CallAlerting, async (e) => { const call = e.call; call.answer(); const r = await fetch('https://apifleet.dev/voximplant/route', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'To=' + encodeURIComponent(call.number()) + '&From=' + encodeURIComponent(call.callerid()), }); const action = await r.json(); if (action.action !== 'assistantfleet') { call.hangup(); return; } const ws = VoxEngine.createWebSocket(action.websocket_url); ws.addEventListener(WebSocketEvents.OPEN, () => { call.sendMediaTo(ws, { encoding: 'pcm', sampleRate: 16000 }); ws.sendMediaTo(call); }); ws.addEventListener(WebSocketEvents.CLOSE, () => call.hangup()); }); ``` Audio format must be slin16 (16-bit linear PCM, mono, 16 kHz) — that's what /media/voximplant expects. The scenario is the customer's responsibility; we don't run code in Voximplant. For outbound, configure a second scenario (or extend this one) that reads VoxEngine.customData(), calls VoxEngine.callPSTN(), and bridges to our WS. See the template under [Outbound calls](#outbound). Set VOXIMPLANT_RULE_ID to the Rule that points at that scenario, plus VOXIMPLANT_ACCOUNT_ID and VOXIMPLANT_API_KEY server-side. ### VoIPCloud setup VoIPCloud is a PBX / SIP-trunk provider operating in five regions: - uk → https://uk.voipcloud.online - ie → https://ie.voipcloud.online - nz → https://nz.voipcloud.online - us → https://us.voipcloud.online - ca → https://ca.voipcloud.online Each binding carries its own region, so a single APIFleet deployment can serve VoIPCloud numbers across regions. We don't terminate SIP. There are two paths: Inbound (PBX → AI): - Bind your VoIPCloud number with "provider": "voipcloud", "region": "uk" (or your region). - Also bind a Telnyx or Twilio number to the same assistant — that's where calls actually bridge. - Configure your VoIPCloud PBX to query /voipcloud/route for the forward target; we respond with the sibling Telnyx/Twilio number. - The PBX SIP-forwards the call there; the streaming provider picks it up. Outbound (click-to-call) — verified against VoIPCloud's /api/integration/v2/call-to-number: - Put VOIPCLOUD_API_KEY in the server env. The base URL is derived from each binding's region; you can override with VOIPCLOUD_BASE_URL for single-region installs or testing. - Have a VoIPCloud user/extension whose dial behavior forwards to a sibling Telnyx/Twilio AI number — that puts the AI on the calling leg after the bridge. - POST /calls/outbound with user_number set to that VoIPCloud extension. VoIPCloud rings it first, then dials to and bridges. The Vapi-style AI is the calling leg directly via SIP pattern (used by their warm-transfer-experimental + sipVerb: dial) requires a SIP UAC in the AI stack — Vapi has one, APIFleet doesn't. If that's what you need, use Telnyx/Twilio for outbound or peer their BYO-SIP trunk through your VoIPCloud trunk on the provider side. ## Assistants ### Create POST /assistants | Field | Type | Notes | | --- | --- | --- | | name | string | Required. | | instructions | string | System prompt for the agent. | | first_message | string | Greeting spoken when the call connects. | | greeting_mode | string | natural (default for new assistants) lets the model vary phrasing and cadence while preserving facts; exact speaks the greeting verbatim. Existing assistants migrate to exact. | | realtime_provider | string | Realtime only: openai (default) or gemini. Existing assistants remain on OpenAI. | | live_settings | object|null | GPT-Live only: delegated backend_model (default gpt-5.6-terra, also gpt-5.6-luna or gpt-5.6-sol), reasoning_effort (default low), service_tier (default or fast), max_output_tokens (1,024–32,768, default 4,096), voice_instructions, and customer-selected accent_instructions (each up to 2,000 characters). Business Instructions and attached tools go to the delegated model. Null restores defaults. See [GPT-Live](#gpt-live). | | model | string | See [models](#models). Defaults to gpt-realtime-2.1 for OpenAI or gemini-3.8-live for Gemini. | | voice | string | See [voices](#models). Defaults to marin for OpenAI or Aoede for Gemini. | | transcription_model | string|null | OpenAI Realtime only. Caller transcript model. Omit to snapshot the current default; null follows OPENAI_TRANSCRIPTION_MODEL. Gemini Live uses its built-in input/output transcription. | | language | string | ISO 639-1, default en. Also hints the caller transcript model for better accuracy and latency. | | turn_detection | string | One of semantic_vad (default for new assistants), server_vad, or OpenAI-only none. Gemini Live requires automatic turn detection. | | turn_eagerness | string | auto (default), low, medium, or high. For OpenAI this controls Semantic VAD; for Gemini it maps to automatic VAD end-of-speech sensitivity and silence duration. | | reasoning_effort | string | minimal, low (default), medium, or high; OpenAI Realtime 2 also supports xhigh. Gemini 3.8 Live manages reasoning automatically and ignores this field. Extended Thinking supports low, medium, or high (minimal maps to low). The API rejects xhigh for Gemini; the dashboard maps it to high when switching providers. Higher levels can add cost. | | max_output_tokens | integer | Cap per response. Default 600. | | end_call_enabled | boolean | Whether the assistant can hang up via end_call. Default true. See [built-ins](#builtins). | | transfer_phone_numbers | string[] | E.164 list. If non-empty, exposes transfer_call. See [built-ins](#builtins). | | dtmf_enabled | boolean | Exposes send_dtmf so the assistant can press keys (e.g. navigating IVRs on outbound). Default false. See [DTMF](#dtmf). | | voicemail_action | string | One of continue (default), leave_message, hang_up. Outbound only. See [voicemail](#voicemail). | | voicemail_message | string | Spoken verbatim when voicemail_action: "leave_message". | | pipeline_mode | string | realtime (default) runs one OpenAI or Gemini speech-to-speech model. cascading runs a separate transcriber, model and voice. See [cascading pipeline](#cascading). | | stt_provider | string | Cascading only. deepgram or gemini. Null uses the server default. | | stt_model | string | Cascading only: nova-3 for Deepgram or gemini-3.5-transcribe-live for Gemini. Null uses the provider default. The unary gemini-3.5-transcribe model uses POST /stt/transcribe, not a live call stream. | | stt_language | string|null | Cascading only. A language code such as en, en-IE, or es; multi enables each provider's live automatic/code-switching mode. Null inherits the assistant's primary language. This affects transcription only and is not passed to TTS. | | llm_model | string | Cascading only, e.g. gpt-4.1-mini. Null uses the server default. | | tts_provider | string | Cascading only. One of azure, polly, elevenlabs, cartesia, telnyx, soniox, deepgram, gemini, or self-hosted piper. Null uses the server default. | | tts_voice | string | Cascading only. A readable voice/model for Azure, Polly, Soniox (for example Adrian), Deepgram (for example flux-gemma-en), or Gemini (for example Kore); a VCTK speaker such as p266 for Piper; or an opaque voice id for ElevenLabs/Cartesia. Required for providers without a configured default. | | tts_model | string | Cascading only. Vendor-specific: the Polly engine, Cartesia generation, ElevenLabs/Soniox model, Piper model, or one of gemini-3.1-flash-tts-preview, gemini-2.5-flash-preview-tts, and gemini-2.5-pro-preview-tts. | | tts_settings | object | Cascading only. Provider-specific voice controls. For Soniox, {"audio_tags": true} begins each response with one restrained delivery cue such as [warm] or [serious]; tags affect speech but are omitted from transcripts. For Piper, optional noise_scale and noise_w_scale values from 0.1 to 0.6 override the automatic Vocal delivery preset; leaving them unset follows Minimal, Professional, or Expressive automatically. | Returns 201 with the created assistant (includes id, revision, created_at) and an ETag containing the revision. Responses also include a credential-free effective_runtime_config snapshot with inherited server defaults resolved. ### Cascading pipeline (STT → LLM → TTS) By default an assistant runs on a single OpenAI Realtime model that listens, reasons and speaks over one connection; realtime_provider: "gemini" selects Gemini Live on the same one-connection pipeline. Setting pipeline_mode: "cascading" splits those three jobs across separate vendors instead. The reason to do it is voice coverage and deterministic provider controls. Gemini Live can be prompted to use an Irish accent, but it does not expose an en-IE locale or numeric accent-strength parameter; cascading voices can provide an explicitly regional voice. Per-minute cost is roughly comparable — text-to-speech is billed by characters or tokens and is the expensive leg — and latency is somewhat higher, since a cascading turn pays for endpointing plus a model round-trip before speech begins. At Google's published paid-tier rates, Gemini 3.8 Live, Extended Thinking, and 3.1 Live audio are approximately $0.005/min input plus $0.018/min output. Text, thinking, enabled transcriptions, and conversation context are additional token charges; APIFleet enables a sliding context window to keep long-call growth bounded. ``` { "name": "Dublin native audio", "pipeline_mode": "realtime", "realtime_provider": "gemini", "model": "gemini-3.8-live", "voice": "Aoede", "instructions": "Speak English throughout with a strong, natural Irish accent." } ``` Select gemini-3.8-live-extended-thinking with reasoning_effort: "low", "medium", or "high" for background reasoning. Both 3.8 models support nonblocking tools so speech can continue during tool execution. Extended Thinking can produce more speech or tool calls after an audio turn ends; APIFleet keeps the response active until the server reports idle. Existing assistants can keep gemini-3.1-flash-live-preview. Tools, knowledge, webhooks, recordings, transcripts and post-call analytics behave identically in both modes. Call logs gain cost_stt and cost_tts alongside cost_openai, which keeps meaning "the model leg". ``` curl -X POST https://apifleet.dev/assistants \ -H "Authorization: Bearer af_live_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Dublin front desk", "pipeline_mode": "cascading", "stt_provider": "deepgram", "stt_model": "nova-3", "stt_language": "multi", "llm_model": "gpt-4.1-mini", "tts_provider": "soniox", "tts_voice": "Adrian", "tts_model": "tts-rt-v2", "tts_settings": { "audio_tags": true } }' ``` A deployment with the private Piper sidecar can instead select an Irish VCTK speaker: {"tts_provider":"piper","tts_model":"en_GB-vctk-medium","tts_voice":"p266","delivery_style":"expressive"}. Piper needs no tenant API credential; PIPER_TTS_BASE_URL points AF to the sidecar on the deployment's private network. Minimal, Professional, and Expressive map to conservative Piper variability presets; optional tts_settings overrides can tune noise_scale and noise_w_scale for a tested speaker. Gemini native TTS is available with {"tts_provider":"gemini","tts_model":"gemini-3.1-flash-tts-preview","tts_voice":"Kore"}. Gemini 3.1 streams audio for lower latency; the 2.5 Flash and Pro preview models return each submitted phrase in one response. All three use the same 30 prebuilt voices and support controllable delivery and pacing. Gemini 3.5 Transcribe Live is available with {"stt_provider":"gemini","stt_model":"gemini-3.5-transcribe-live","stt_language":"multi"}. AF converts phone and browser input to Gemini's PCM16 16 kHz stream, forwards speech keyterms as custom vocabulary, and uses Gemini's finalized transcript as the caller turn. The same gemini credential also authorizes TTS. Credentials for each leg are set per tenant through PUT /credentials/:provider using the provider names deepgram, openai, azure_speech, polly, elevenlabs, cartesia, telnyx, and soniox, and gemini. Piper is server-scoped and takes no tenant credential. Anything a tenant has not configured falls back to the server's own keys. ### List, get, update, delete ``` GET /assistants GET /assistants/:id PATCH /assistants/:id # any subset of the create fields DELETE /assistants/:id # 204 on success; unbinds its numbers ``` GET /assistants/:id and successful create/update responses include a monotonic revision and matching ETag. Send that value in If-Match: "" when updating or deleting. A stale write returns 409 ASSISTANT_REVISION_CONFLICT with current_revision. ### Example: update an assistant's prompt ``` curl -X PATCH https://apifleet.dev/assistants/abc123 \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -H 'If-Match: "7"' \ -d '{"instructions": "You are a senior support agent. Stay polite under pressure."}' ``` ## Phone numbers A phone number is bound to exactly one assistant at a time, and a number is globally unique — you cannot bind a number that another tenant has already claimed. ### Bind PUT /numbers/:number — body {"assistant_id": "", "provider": "telnyx"} The path parameter must be E.164. provider defaults to telnyx — see [Telecom providers](#providers) for the supported values. When provider is voipcloud, also pass region: one of uk | ie | nz | us | ca (defaults to uk). The region selects the regional VoIPCloud portal (https://{region}.voipcloud.online) used for the Integration API. ### List ``` GET /numbers # → [{ "phone_number": "13125550100", "assistant_id": "abc", "provider": "telnyx", "region": null, "created_at": "…" }, …] ``` ### Unbind ``` DELETE /numbers/+13125550100 # → 204 No Content ``` ## Call logs GET /calls?page=1&limit=25&sort=started_at&order=desc Returns a tenant-scoped page of calls. Aggregate stats reflect the active filters. Filters: search, assistant_id, source, model, voice, outcome, sentiment, date_from, and date_to. Sort by started_at, source, duration_seconds, from_number, did, assistant_name, model, voice, outcome, ended_reason, sentiment, or cost_total; order is asc or desc. The maximum page size is 1000. ``` { "stats": { "calls": 42, "totalSeconds": 3120, "totalCost": 5.18 }, "calls": [ { "id": "…", "started_at": "2026-05-24T12:01:33Z", "ended_at": "2026-05-24T12:03:01Z", "duration_seconds": 88, "source": "telnyx", // or "web" "did": "13125550100", "from_number": "13644448442", "assistant_id": "abc", "assistant_name": "Front desk", "model": "gpt-realtime-2.1", "voice": "marin", "ended_reason": "assistant_ended_call", "recording_available": true, "recording_url": "/calls/…/recording", "waveform_url": "/calls/…/waveform", "cost_total": 0.1432, "cost_openai": 0.1378, "cost_telnyx": 0.0054, "transcript": [ { "role": "assistant", "text": "Thanks for calling…", "t": "2026-05-24T12:01:34Z" }, { "role": "user", "text": "Hi, I'd like to book…", "t": "2026-05-24T12:01:38Z" } ], "tool_events": [ { "type": "tool", "call_id": "call_…", "name": "check_availability", "arguments": { "date": "2026-05-24" }, "output": { "available": true }, "status": "completed", "started_at": "2026-05-24T12:01:42Z", "completed_at": "2026-05-24T12:01:42.240Z", "duration_ms": 240 } ] } ], "pagination": { "total": 42, "page": 1, "limit": 25, "total_pages": 2, "sort": "started_at", "order": "desc" } } ``` tool_events are ordered into the dashboard transcript timeline by started_at. Stored payloads include bounded model arguments and tool responses, but never configured tool URLs, headers, or signing secrets. A tool event with status: "completed" means the tool returned a result; it does not by itself mean a booking succeeded. Check the tool's output. For the booking tools, output.success: false with output.data.errorCode: "booking_details_confirmation_required" means confirmation is still required. See [booking outcomes](#booking-outcomes). ### Play a recording GET /calls/:id/recording Returns the mixed call audio as audio/wav. The endpoint uses the same tenant authentication as the rest of the management API and supports browser range requests. Recordings are available for calls made after recording support is deployed; older rows cannot be reconstructed from their transcripts. GET /calls/:id/waveform Returns compact 0–255 peak arrays used by the dashboard's interactive waveform. New recordings include separate caller and assistant channels; recordings created before waveform support are analyzed lazily and returned as a single mixed channel. This endpoint is authenticated and tenant-scoped too. Recording is enabled by default. Set APIFLEET_RECORDINGS_ENABLED=0 to disable it or APIFLEET_RECORDINGS_DIR to change storage. Make sure your call flow complies with the recording-consent laws that apply to your callers. ## Post-call analytics When enabled, post-call analysis runs asynchronously after a call ends. The configured provider analyzes the conversation, and AF checks recorded booking-tool results before saving the outcome. Results appear in the Call logs view and GET /calls. Simulation calls use their evaluation judge instead of this post-call pass. | Field | Type | Notes | | --- | --- | --- | | summary | string | null | A short summary grounded in the conversation and booking-tool evidence. | | sentiment | enum | null | positive | neutral | negative. Describes the caller's mood, independently of task completion. Null when unavailable or unknown. | | outcome | enum | null | resolved | follow_up_required | booking_request | no_suitable_availability | complaint | voicemail | abandoned | other. Null when no supported outcome is available. | | action_items | string[] | null | Short concrete to-dos for a human teammate (max 20). Null until available; an empty array means no actions were identified. | | analytics_at | iso8601 | null | When an analysis result was saved. Null can mean pending, disabled, or unavailable; it is not a booking status. | ### Booking outcomes For create_booking, update_booking and cancel_booking, an unfinished or unverified write sets outcome: "follow_up_required", with a summary and a staff action to check the booking records. An assistant saying “confirmed” or a caller saying “thank you” does not prove the write succeeded. A positive sentiment can therefore accompany an unsuccessful booking. Verified success requires a non-mocked result with output.success: true and status: "completed". Legacy events without a status are also accepted when output.success is true. A successful matching retry can resolve an earlier failure. An unrelated success cannot: creating a booking does not complete a failed change or cancellation. AF handles explicit withdrawals in context; “No thanks” to “Anything else?” does not withdraw a pending booking. If the recorded details cannot establish that attempts belong to the same request, AF conservatively keeps the follow-up action. Check the provider before retrying an uncertain write to avoid duplicate bookings. This analysis does not execute or retry booking tools. Example call-row fields after a confirmation step was left incomplete: ``` { "summary": "The booking has no verified completion: the required confirmation step remains incomplete. Follow up with the caller.", "sentiment": "positive", "outcome": "follow_up_required", "action_items": [ "Check booking records and contact the caller to complete the booking." ], "analytics_at": "2026-10-16T12:03:02Z" } ``` ### Timing and configuration Analysis does not block call teardown or webhook delivery. The call.ended payload is captured before analysis and may omit these fields. Re-fetch GET /calls?search= and match calls[].id to read the saved result. AF does not send another call.ended event when analysis finishes. With analysis enabled, unresolved booking-tool evidence can still produce a follow-up result when the provider fails or the transcript is empty; sentiment is null if no sentiment result is available. Without such evidence, a failed analysis leaves the analysis fields unpopulated. Existing calls are not automatically reanalyzed by a deployment. POST_CALL_ANALYTICS_PROVIDER selects typesafe or openai. The default is TypeSafe when TYPESAFE_API_KEY is set, otherwise OpenAI. POST_CALL_ANALYTICS_ENABLED=0 disables post-call analysis, including the booking outcome guard. OPENAI_ANALYTICS_ENABLED=0 disables only the OpenAI path; OPENAI_ANALYTICS_MODEL sets its model (default gpt-4o-mini). TypeSafe failures do not trigger an OpenAI fallback request. ## Metrics & latency GET /metrics returns a JSON snapshot of the in-memory metrics registry (resets on process restart — not Prometheus-persistent). Admin sees aggregate; tenants see their own slice. Use it to sanity-check capacity and turn-latency on real calls. ``` curl https://apifleet.dev/metrics \ -H "Authorization: Bearer af_live_YOUR_KEY" { "uptime_seconds": 12483, "active_calls": 2, "calls_started": 145, "calls_ended": 143, "calls_by_provider": { "telnyx": 138, "twilio": 7 }, "latencies": { "setup_ms": { "n": 143, "min": 220, "p50": 410, "p95": 720, "p99": 980, "max": 1200 }, "greeting_ms": { "n": 142, "min": 320, "p50": 560, "p95": 940, "p99": 1300, "max": 1600 }, "turn_ms": { "n": 412, "min": 380, "p50": 720, "p95": 1180, "p99": 1450, "max": 2100 }, "queue_depth_peak": { "n": 143, "min": 3, "p50": 22, "p95": 58, "p99": 91, "max": 110 } } } ``` What each latency means: - setup_ms — WS open → session.updated. The OpenAI Realtime connection cost. - greeting_ms — session.updated → first audio delta. Time to "Thanks for calling…". - turn_ms — caller speech-start → first response audio delta. What callers actually feel. - queue_depth_peak — max outbound-frame queue size during the call. High values mean we're producing audio faster than the provider can drain it. Samples are rolling (cap 1000 per metric); old values are dropped. Per-call summary lines also appear in the process logs: setup=420ms greeting=560ms turns=4 p50=680ms p95=910ms qpeak=22. ## Tenant credentials Each tenant can bring their own provider accounts — Telnyx, Twilio, Voximplant, VoIPCloud — and they're stored encrypted at rest (AES-256-GCM with the server's APIFLEET_ENCRYPTION_KEY). When a dialer fires it resolves credentials tenant-first, falling back to the server env if the tenant hasn't configured that provider. ### Save credentials ``` curl -X PUT https://apifleet.dev/credentials/twilio \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"account_sid": "AC...", "auth_token": "..."}' ``` Provider-specific shapes: | Provider | Required | Optional | | --- | --- | --- | | telnyx | api_key | connection_id, route_secret, stream_secret | | twilio | account_sid, auth_token | route_secret | | voximplant | account_id, api_key | rule_id, application_id, api_base_url | | voipcloud | api_key | base_url | ### List configured providers ``` GET /credentials # → [{ "provider": "twilio", "configured": true, "created_at": "…", "updated_at": "…" }, …] ``` Secret values are never returned by GET — only the fact that a provider is configured and when it was last updated. ### Clear credentials ``` DELETE /credentials/twilio # → 204 ``` After clearing, the server-env defaults (if any) are used again. ## Outbound calls Dial out from one of your bound Telnyx numbers and bridge the call straight to an assistant — for appointment reminders, follow-ups, surveys, etc. ### Start a call ``` curl -X POST https://apifleet.dev/calls/outbound \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "assistant_id": "", "from": "+13644448442", "to": "+13125550100" }' ``` Returns 201 with Telnyx call ids: ``` { "status": "initiated", "call_sid": "…", "call_control_id": "v3:…", "from": "+13644448442", "to": "+13125550100", "assistant_id": "…" } ``` ### Rules - from must be E.164 and bound to your tenant (use [PUT /numbers/:number](#numbers)). The dial provider is whatever that number is bound on. - to must be E.164. - Telnyx-from: requires TELNYX_API_KEY + TELNYX_CONNECTION_ID server-side, else 503. AI is the calling leg. - Twilio-from: requires TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN, else 503. AI is the calling leg. - Voximplant-from: requires VOXIMPLANT_ACCOUNT_ID + VOXIMPLANT_API_KEY + VOXIMPLANT_RULE_ID (the rule must point at a scenario that reads VoxEngine.customData() and dials via callPSTN — template below). AI is the calling leg. - VoIPCloud-from: requires VOIPCLOUD_API_KEY + VOIPCLOUD_BASE_URL, plus a user_number field in your POST body (your VoIPCloud user/extension that will be rung first). This is a click-to-call flow — VoIPCloud rings your user, then bridges to to. Have your user extension forward to a sibling Telnyx/Twilio number bound to the assistant so the AI ends up on that leg. The AI-as-calling-leg path requires SIP origination through VoIPCloud's BYO SIP trunk — we don't ship a SIP UAC; configure your AI provider's BYO SIP credential for that pattern. ### Voximplant outbound scenario template Configure a VoxEngine scenario tied to the rule you set in VOXIMPLANT_RULE_ID: ``` require(Modules.WebSocket); VoxEngine.addEventListener(AppEvents.Started, async () => { const data = JSON.parse(VoxEngine.customData() || '{}'); if (!data.to || !data.websocket_url) { VoxEngine.terminate(); return; } const call = VoxEngine.callPSTN(data.to, data.from); call.addEventListener(CallEvents.Connected, () => { const ws = VoxEngine.createWebSocket(data.websocket_url); ws.addEventListener(WebSocketEvents.OPEN, () => { call.sendMediaTo(ws, { encoding: 'pcm', sampleRate: 16000 }); ws.sendMediaTo(call); }); ws.addEventListener(WebSocketEvents.CLOSE, () => call.hangup()); }); call.addEventListener(CallEvents.Disconnected, () => VoxEngine.terminate()); call.addEventListener(CallEvents.Failed, () => VoxEngine.terminate()); }); ``` ### VoIPCloud outbound example ``` curl -X POST https://apifleet.dev/calls/outbound \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "assistant_id": "", "from": "+441216306195", // VoIPCloud DID (caller_id) "to": "+447418328008", // destination "user_number": "+44XXXXXXXXXX" // your VoIPCloud user/extension to ring first }' ``` Outbound calls fire the same call.started / call.ended webhooks as inbound, and the resulting call_logs row has direction: "outbound" so you can filter. ## Tools Tools let the assistant call your HTTP endpoint mid-conversation (Vapi-style function calling). You define a tool once, attach it to one or more assistants, and we forward it to the active OpenAI pipeline as a function. When the model decides to call it, we POST signed JSON to your URL and feed the response back so the model can speak the result. ### Create a tool ``` curl -X POST https://apifleet.dev/tools \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "lookup_customer", "description": "Look up a customer by phone number.", "progress_message": "I'll check that now.", "url": "https://your-app.com/tools/lookup", "method": "POST", "parameters": { "type": "object", "properties": { "phone": { "type": "string", "description": "E.164 phone" } }, "required": ["phone"] } }' ``` The response includes a secret shown once — store it; you'll use it to verify our request signature. progress_message is optional and limited to 160 characters. A cascading assistant speaks it only when the model calls that custom tool without first giving its own update. This removes dead air during slow lookups without duplicating a model-generated preamble. Pass null in a PATCH to clear it. ### Attach to an assistant ``` curl -X PUT https://apifleet.dev/assistants//tools \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"tool_ids": ["", ""]}' ``` This replaces the assistant's tool set — pass an empty array to detach all. ### What your endpoint receives ``` POST https://your-app.com/tools/lookup Content-Type: application/json X-APIFleet-Tool: lookup_customer X-APIFleet-Call: X-APIFleet-Signature: sha256= { "call_id": "call_…", "name": "lookup_customer", "arguments": { "phone": "+13125550100" }, "context": { "assistant_id": "…", "did": "13644448442", "from": "15551112222", "source": "telnyx" }, "created_at": "2026-05-24T13:42:01Z" } ``` ### What you return Respond with JSON — anything serializable. The whole body is fed back to the model as the function output, which the model uses to compose its next spoken turn. ``` { "found": true, "customer": { "name": "Mariano", "tier": "gold", "last_visit": "2026-04-12" } } ``` Timeouts (default 8s, configurable per tool 0.5–30s), 5xx, and network errors are returned to the model as a structured {"error": "..."} envelope so it can recover gracefully ("I'm having trouble looking that up — could you try again in a moment?"). Keep responses short: long payloads cost more tokens and make the model verbose. ### Verifying signatures (Node.js) ``` app.post('/tools/lookup', express.raw({ type: '*/*' }), (req, res) => { const sig = req.header('X-APIFleet-Signature') || ''; const expected = 'sha256=' + crypto .createHmac('sha256', process.env.AF_TOOL_SECRET) .update(req.body).digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) return res.sendStatus(401); const { arguments: args, context } = JSON.parse(req.body.toString()); // ... your lookup logic ... res.json({ found: true, customer: { name: 'Mariano' } }); }); ``` ### Manage tools ``` GET /tools GET /tools/:id PATCH /tools/:id # any subset of the create fields DELETE /tools/:id # cascades the assistant attachment ``` ### Tips - The model uses the name + description + parameter schema to decide when to call the tool. Be explicit and concrete in the description. - Function names follow OpenAI's rule: ^[A-Za-z_][A-Za-z0-9_]{0,63}$. - GET tools receive the arguments as query string instead of a body. - Tool URLs must be HTTPS (same SSRF guard as webhooks). ## Built-in tools Runtime tools are baked in — you don't define them as custom HTTP tools. Some are always available and others are enabled by assistant settings. ### wait_for_user Always available. When VAD produces a turn containing only silence, background noise, or no intelligible request, the assistant invokes this no-op and waits without speaking. This avoids awkward filler responses to false turns. ### end_call Lets the assistant hang up cleanly when the conversation is done. Enabled by default on every new assistant; toggle off via: ``` curl -X PATCH https://apifleet.dev/assistants/ \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"end_call_enabled": false}' ``` ### transfer_call Lets the assistant transfer the live call to a human at one of a whitelist of phone numbers (Telnyx Call Control transfer under the hood). Only exposed when you set the list: ``` curl -X PATCH https://apifleet.dev/assistants/ \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"transfer_phone_numbers": ["+13125550100", "+13125550199"]}' ``` The destinations are echoed to the model in the tool description, so it knows the options. The model is instructed to announce the transfer before invoking the tool. ## DTMF (keypad) Touch-tone digits work in both directions on real phone calls (not in web tests). ### Caller → assistant When a caller presses a key, Telnyx forwards a dtmf media event. We surface it to the model as a user text turn ("[Caller pressed keypad: 1]") and trigger a response, so prompts like "Press 1 for sales, 2 for support" just work if the model is instructed to treat keypad input as a choice. ### Assistant → call (e.g. navigating an outbound IVR) Enable on the assistant — exposes a send_dtmf built-in tool: ``` curl -X PATCH https://apifleet.dev/assistants/ \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"dtmf_enabled": true}' ``` The model can then call send_dtmf({digits: "1234#"}); we relay through Telnyx Call Control send_dtmf. Digits accepted: 0-9 * # w W (w/W = half-second pause). ## Voicemail handling (outbound) For outbound calls only, the assistant can be instructed how to react when it lands on a voicemail / answering machine instead of a human. Three modes: - continue (default) — talk to the machine the same as a human. - hang_up — stay silent and end the call as soon as voicemail cues are detected. - leave_message — wait for the beep, say voicemail_message verbatim, then hang up. ``` curl -X PATCH https://apifleet.dev/assistants/ \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "voicemail_action": "leave_message", "voicemail_message": "Hi, this is an automated reminder about your appointment tomorrow at 3 PM. Please call us back." }' ``` Detection is currently model-based (the model identifies voicemail cues from the greeting audio and a prompt block injected only on outbound calls). It's effective for most mainstream voicemail greetings, but not as deterministic as carrier AMD. If you need stricter handling at scale, we can wire Telnyx AMD later. ## Knowledge base Plain-text documents (FAQs, business info, policies) that get injected into the assistant's system prompt at the start of every call. No embeddings — the documents are sent verbatim, so the model has everything in context. Best for small, stable corpora (hours, prices, scripts). ### Limits - 50 KB per document. - 200 KB total injected per assistant per call (excess is truncated). - Token cost: the docs ride the cacheable prefix of the prompt, so repeated calls hit the cache (~98% discount on cached input tokens). ### Create ``` curl -X POST https://apifleet.dev/knowledge \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "business-hours", "content": "We are open Monday through Friday 9 AM to 6 PM Central, Saturday 10–4. Closed Sundays and federal holidays." }' ``` ### Attach to an assistant ``` curl -X PUT https://apifleet.dev/assistants//knowledge \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"knowledge_ids": ["", ""]}' ``` This replaces the attached set — pass an empty array to detach all. ### Manage ``` GET /knowledge GET /knowledge/:id PATCH /knowledge/:id # any subset of name/content DELETE /knowledge/:id ``` ## Simulations Test assistants before (and after) every prompt change. A persona is a mock caller — an LLM playing a character. A scenario gives that caller a goal and defines the checks that decide pass/fail. A simulation pairs an assistant with one persona and one scenario; a run executes it live and grades the transcript. Runs are asynchronous: creating one returns status: "queued" immediately, and each run also produces a call-log row (source: "simulation") with the full transcript, tool events, cost and — for voice runs — the recording. ### Modes - chat — the assistant's real pipeline driven as text (same instructions, tools, model; the cascading pipeline runs its actual LLM leg, the realtime pipeline runs a real Realtime session with text output). Fast and cheap; good for CI. - voice — full audio: the persona speaks TTS audio through the same media path a browser test call uses, with real turn-taking, and the run gets a WAV recording. ### Personas ``` curl -X POST https://apifleet.dev/simulations/personas \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Impatient Dublin caller", "system_prompt": "You are Dara, 34, calling from a noisy office. You are blunt, skip pleasantries, and give details only when asked twice.", "tts_provider": "deepgram", "tts_voice": "flux-jack-en" }' ``` llm_model overrides the caller model (default SIMULATION_CALLER_MODEL); tts_provider/tts_voice/tts_model/voice_speed shape the voice-mode voice and fall back to the server TTS defaults when null. ### Scenarios & evaluations ``` curl -X POST https://apifleet.dev/simulations/scenarios \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Book a table for four", "instructions": "Book a table for 4 people this Friday at 7pm under the name Aoife Byrne, callback 087 123 4567. Do not accept Saturday.", "max_turns": 10, "tool_mocks": { "book_table": { "ok": true, "confirmation_id": "BK-1042" } }, "evaluations": [ { "id": "party-size", "kind": "tool_call", "tool": "book_table", "status": "completed", "path": "arguments.party_size", "equals": 4 }, { "id": "booking-written", "kind": "tool_call", "tool": "book_table", "status": "completed", "path": "output.ok", "equals": true }, { "id": "phone-ok", "kind": "tool_call", "tool": "book_table", "path": "arguments.phone", "equals": "0871234567", "digits_only": true }, { "id": "no-ai-talk", "kind": "transcript", "role": "assistant", "excludes": "as an ai", "required": false }, { "id": "clean-end", "kind": "call", "path": "ended_reason", "equals": "assistant_ended_call" }, { "id": "date-agreed", "kind": "ai", "question": "Which day of the week did they finally agree on? Answer with one lowercase day name, or \"none\".", "expected": "friday", "comparator": "=" } ] }' ``` Four check kinds, all with optional id, name and required (default true): - tool_call — the assistant called a tool. tool (required), status (completed|error), occurrence (0 = first match), path (dot-path into the event, e.g. arguments.party_size), equals (scalar or array of accepted values). - transcript — the conversation text. role filters to one side; includes / excludes are substring checks. - call — the finished call row. path + equals (e.g. ended_reason). - ai — a judge model (SIMULATION_JUDGE_MODEL, default gpt-4o-mini) answers question from the transcript; the answer is compared against expected with comparator (= != > < >= <=). String comparisons are case-insensitive with collapsed whitespace by default; digits_only strips everything but digits first (phone numbers). Tool mocks map tool name → canned JSON: during a simulation the assistant's matching HTTP tools return the mock instead of calling your endpoint, and the tool event is flagged mocked: true. Built-ins (end_call etc.) are never mocked. ### Simulations & runs ``` # pair assistant x persona x scenario curl -X POST https://apifleet.dev/simulations \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"assistant_id": "", "persona_id": "", "scenario_id": "", "name": "Booking x impatient"}' # start one run (async — poll it) curl -X POST https://apifleet.dev/simulations//runs \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"mode": "chat"}' # or "voice" # run every simulation of one assistant under a single batch id curl -X POST https://apifleet.dev/simulations/runs/batch \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"assistant_id": "", "mode": "chat"}' GET /simulations # ?assistant_id= filter GET /simulations/runs # ?simulation_id=&assistant_id=&batch_id=&status=&page=&limit= GET /simulations/runs/:id # includes the linked call (transcript, recording_url, ...) DELETE /simulations/runs/:id GET/POST/PATCH/DELETE /simulations/personas[/:id], /simulations/scenarios[/:id], /simulations[/:id] ``` ### Run result ``` { "id": "…", "status": "completed", "passed": true, "mode": "chat", "batch_id": null, "call_id": "…", "results": { "checks": [ { "id": "tool-booked", "kind": "tool_call", "required": true, "passed": true, "expected": 4, "actual": 4, "reason": null }, { "id": "date-agreed", "kind": "ai", "comparator": "=", "passed": true, "expected": "friday", "actual": "friday", "reason": null } ], "required_checks": 4, "passed_checks": 4, "judge": { "model": "gpt-4o-mini", "skipped": false, "error": null }, "caller": { "model": "gpt-4.1-mini", "turns": 5, "hung_up": true, "timed_out": false }, "duration_ms": 14211 } } ``` passed is true when every check with required: true passed. Lifecycle: queued → running → completed | error (error means infrastructure failed — the caller LLM, a vendor socket — not that a check failed). A simulation.completed webhook fires for every finished run, carrying the run row above. CI can gate deploys on it, or on polling GET /simulations/runs?batch_id=…. ### Config ``` SIMULATIONS_ENABLED=1 # default on; 0 disables the run endpoints (503) SIMULATION_JUDGE_MODEL=gpt-4o-mini SIMULATION_CALLER_MODEL=gpt-4.1-mini SIMULATION_MAX_TURNS=12 # default caller-turn cap (per-scenario max_turns overrides) SIMULATION_MAX_CONCURRENT=2 SIMULATION_TIMEOUT_MS=180000 # whole run SIMULATION_TURN_TIMEOUT_MS=30000 # one assistant turn (chat mode) ``` ## Webhooks We POST signed JSON to your URL when calls start and end, when a simulation run finishes (simulation.completed), and—when subscribed—when an assistant is created, updated, or deleted. Create a webhook in the dashboard or via API: ``` curl -X POST https://apifleet.dev/webhooks \ -H "Authorization: Bearer af_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://your-app.com/hooks/apifleet", "events": ["call.started", "call.ended", "simulation.completed", "assistant.created", "assistant.updated", "assistant.deleted"]}' ``` The response includes the signing secret — shown once. Assistant lifecycle payloads use the same shape as GET /assistants/:id, including revision. A delete payload contains id, the last revision, and updated_at. Lifecycle events are opt-in so existing webhook registrations retain their previous event set. ### Event payload ``` POST https://your-app.com/hooks/apifleet Content-Type: application/json X-APIFleet-Event: call.ended X-APIFleet-Delivery: 9f8a-… X-APIFleet-Signature: sha256= { "event": "call.ended", "delivery": "9f8a-…", "created_at": "2026-05-24T12:03:02Z", "data": { /* same shape as the GET /calls row */ } } ``` Call-end payloads are captured before post-call analysis. Read the final summary, sentiment, outcome and action_items from GET /calls after analysis; see [post-call analytics](#analytics). ### Verifying signatures (Node.js) ``` const crypto = require('crypto'); app.post('/hooks/apifleet', express.raw({ type: '*/*' }), (req, res) => { const sig = req.header('X-APIFleet-Signature') || ''; const expected = 'sha256=' + crypto .createHmac('sha256', process.env.AF_WEBHOOK_SECRET) .update(req.body) // raw Buffer .digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) { return res.status(401).end(); } const event = JSON.parse(req.body.toString()); // handle call, simulation, or assistant lifecycle events res.status(204).end(); }); ``` ### Retries Call and simulation webhooks retry 5xx and 429 with exponential backoff (default up to 4 retries). Assistant lifecycle events first enter a durable SQLite outbox, survive process restarts and deploys, and retry with capped exponential backoff for 24 hours by default. Other 4xx responses are permanent and are not retried. Replies are expected within 5 seconds — return early and process asynchronously. ### Manage webhooks ``` GET /webhooks PATCH /webhooks/:id # body { enabled: false } to pause DELETE /webhooks/:id ``` ## Models & voices ### Models APIFleet offers current general-purpose, bidirectional OpenAI Realtime models and Gemini Live native audio. Translation-only and transcription-only models are not assistant replacements and are not shown. - gpt-live-1 — continuous voice with a separately configurable delegated model for business reasoning and tools. - gpt-realtime-2.1 — latest flagship reasoning voice model with tool use; current APIFleet default. - gpt-realtime-2.1-mini — latest faster, lower-cost reasoning voice model. - gpt-realtime-2 — previous flagship generation. - gpt-realtime-1.5 — flagship audio model for voice agents and customer support. - gpt-realtime - gpt-realtime-mini — cheapest, good for simple flows. - gemini-3.8-live — default Gemini model for native speech-to-speech with automatic reasoning and nonblocking function calls. - gemini-3.8-live-extended-thinking — background reasoning with low, medium, or high effort and nonblocking function calls. - gemini-3.1-flash-live-preview — legacy native audio preview with synchronous function calling and thinking levels. Existing assistants keep any previously stored model identifier, including older models that are no longer offered for new selections. Availability still depends on the models enabled for your OpenAI account. ### GPT-Live configuration Select pipeline_mode: "realtime", realtime_provider: "openai" and model: "gpt-live-1". GPT-Live speaks and listens; the delegated model uses your Business Instructions, knowledge and attached tools. The starting configuration is GPT-5.6 Terra, low reasoning and Standard processing. Tool calls run sequentially through the existing booking confirmation checks. Higher reasoning and Fast processing should be tested for task success, latency and cost on your workload. ``` { "model": "gpt-live-1", "voice": "willow", "live_settings": { "backend_model": "gpt-5.6-terra", "reasoning_effort": "low", "service_tier": "default", "max_output_tokens": 4096, "voice_instructions": "Speak naturally with an Irish accent; keep booking details clear." } } ``` Integrations with an accent picker can set live_settings.accent_instructions to the selected language/accent prompt while preserving the other settings. It goes directly to the speaking model and takes precedence over voice-style accent instructions. A Natural selection should specify the voice’s natural accent; an empty value restores the fallback Irish instruction for Willow and Stone. Use willow (Irish feminine) or stone (Irish masculine), or the default marin. Audition with Test in browser. Realtime speed, VAD, transcription-model and response-token controls do not apply to Live. Use audio/voice simulations; chat-only simulations are unsupported. Original timed transcript fragments are preserved, including overlapping speech. For booking flows that require a spoken confirmation, an unfinished confirmation stays pending even if the voice agent acknowledges the caller. After a quiet interval, AF can recover a missed delegation by forwarding the complete fresh caller reply to the reasoning backend once, including brief replies such as “thank you.” Routing the reply does not authorize a booking: the existing readback, consent and token checks still apply, and ambiguous replies require clarification. Successful booking-tool evidence is required before reporting completion. See [booking outcomes](#booking-outcomes) for the post-call result. Live voice costs $0.05/minute, billed per second, plus delegated-model usage. The call log records both costs and traces the delegated model. Shutdown waits for final usage before saving the record; an estimated flag in the usage trace identifies unconfirmed totals after connection loss. See [OpenAI delegation documentation](https://developers.openai.com/api/docs/guides/live-delegation). ### Input transcription models This setting controls the separate asynchronous caller transcript used in the dashboard and call logs. The Realtime assistant consumes the original audio directly, so its understanding can differ from the displayed transcript. - gpt-4o-transcribe — best accuracy; recommended when transcript quality matters most. - gpt-4o-mini-transcribe — lower-cost default. - whisper-1 — legacy compatibility. ### Gemini transcription models - gemini-3.5-transcribe-live — low-latency WebSocket transcription for cascading calls. - gemini-3.5-transcribe — unary/file transcription through POST /stt/transcribe. ``` POST /stt/transcribe Authorization: Bearer af_live_... Content-Type: application/json { "provider": "gemini", "model": "gemini-3.5-transcribe", "audio_base64": "...", "mime_type": "audio/wav", "language_codes": ["en-IE"], "custom_vocabulary": ["Aoife", "Rathmines"], "mode": "verbatim" } ``` For larger inputs, upload through the Gemini Files API and send its uri instead of audio_base64. Smart mode is also accepted; verbatim is the default. ### Voices #### OpenAI Realtime alloy, ash, ballad, cedar, coral, echo, marin, sage, shimmer, verse. OpenAI recommends marin and cedar for best quality. #### Gemini Live Zephyr, Puck, Charon, Kore, Fenrir, Leda, Orus, Aoede, Callirrhoe, Autonoe, Enceladus, Iapetus, Umbriel, Algieba, Despina, Erinome, Algenib, Rasalgethi, Laomedeia, Achernar, Alnilam, Schedar, Gacrux, Pulcherrima, Achird, Zubenelgenubi, Vindemiatrix, Sadachbia, Sadaltager, Sulafat. Voice selects timbre; accent is prompt-steered in instructions and is not guaranteed by a locale setting. Authenticated integrations can fetch GET /voice-presets for stable, curated voice choices. Each item includes an assistant_config that can represent either a Realtime voice or a tested cascading provider/voice combination; clients should persist the preset id. ## Errors All errors come back as JSON with the same shape: ``` { "error": { "message": "name is required" } } ``` | Status | Meaning | | --- | --- | | 400 | Invalid input (missing field, bad enum value, etc.) | | 401 | Missing or invalid API key / session. | | 404 | Resource doesn't exist for your tenant. | | 429 | IP temporarily blocked after repeated invalid credentials. | | 500 | Server error. | --- # Product Source: https://apifleet.dev/ APIFleet — Give your agent a voice. - - - - - - [Skip to content](#main) # Give youragent a voice. Build, test, and deploy voice agents. Connect real tools. See every conversation. [Start building](https://apifleet.dev/app/assistants) [Read the docs](https://apifleet.dev/docs) Example conversation [Caller:Can I book a demo?00:00](#example) [Agent:Let me check availability.00:05](#example) [HTTP tool:check_availability00:08](#example) [Result:Tuesday, 10:0000:10](#example) [View call log00:12](#example) Build conversations that do things Voice agents for a more open internet Speech tools actions real results Build test deploy repeat ## From first helloto deployment. 01 ### Configure your agent Give it instructions, choose a voice and model, and connect the knowledge and tools it needs to help.[Create an assistant](https://apifleet.dev/app/assistants) 02 ### Test the conversation Talk to your agent in the browser. Run simulations, inspect the conversation, and refine how it responds before connecting a number.[Explore simulations](https://apifleet.dev/app/simulations) 03 ### Connect your number Bind a phone number to your assistant, configure your telephony provider, and follow the conversations in your call logs.[Read the setup guide](https://apifleet.dev/docs) Same tools. A more human interface. ## A conversationyou can follow. The words are only half the story. Follow the tool calls and results behind the conversation, so you can understand what your agent did. Replay example Illustrative transcript and timing. This walkthrough doesn’t place a call. Example conversationBrowser test - 00:00 Caller Can I book a demo? - 00:05 Agent Let me check availability. - 00:08 HTTP tool check_availabilityYour endpoint returns available times. - 00:10 Tool result Tuesday, 10:00 - 00:12 Agent There’s a slot on Tuesday at 10:00. Would that work for you? [See your conversations in APIFleet](https://apifleet.dev/app/call-logs) ## Your voice.Your tools.Your way of building. Start in the dashboard or work directly with the API. The same assistants, configuration, and conversations are yours to build on. ### Choose how it speaks. Configure the voice, model, language, and instructions. Use a realtime model or choose the speech, language, and voice providers in a custom pipeline. ### Give it something to do. Connect HTTP tools to your own services. Look up an order, check a calendar, or bring the next step in your workflow into the conversation. ### Keep your app in the loop. Use API keys to manage assistants from your backend and webhooks to receive call events. Inspect recordings and transcripts in the dashboard. Create an assistantCopy ``` curl https://apifleet.dev/assistants \ -X POST \ -H "Authorization: Bearer $APIFLEET_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Demo concierge", "instructions": "Help callers explore our product.", "first_message": "Hi! What are you building?" }' ``` Create an API key in your workspace, then make it your own. [Explore the API](https://apifleet.dev/docs) ## Before yousay hello. What can I build with APIFleet? Voice agents that answer questions, use your business tools, and handle conversations over the phone or in a browser test. You define the instructions, knowledge, and actions available to each assistant. Can I test an agent before connecting a number? Yes. Use browser testing to talk to your agent, or run simulations to exercise a conversation. You can inspect the results and adjust its configuration before connecting phone traffic. Can it connect to my existing backend? Yes. Attach HTTP tools to call your services, manage assistants through the API, and subscribe to call events with webhooks. The API documentation covers authentication and configuration. Where do I create an account? Start building opens platform sign-in for existing accounts. New workspace access is currently limited. [Contact us about your project](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access). APIFleet is the platform powering VoiceFleet. ## Your next idea.Its first hello. Give it a voice. See where the conversation goes.[Start building](https://apifleet.dev/app/assistants) --- # APIFleet vs Vapi Source: https://apifleet.dev/compare/vapi APIFleet vs Vapi: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsVapi A close comparison for developers who want a hosted voice-agent platform with separate provider costs. Hosted platforms · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Vapi pricing](https://vapi.ai/pricing). | What matters | APIFleet | Vapi | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | $0.05 / min Hosting fee; providers extra | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Usage-based hosting. Optional paid success packages are available. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | The public hosting rate is $0.05 per minute; model and speech-provider costs are additional. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | A developer platform with API access, provider selection and simulation testing. | ## Compare the platform fee, then the same provider stack. Vapi is one of the closest alternatives to APIFleet’s approach. The useful starting point is the orchestration charge: $0.03 versus $0.05 per minute. That difference does not tell you the entire cost of a conversation. Match the model, voice, carrier, call duration and billing rules before comparing totals. ### When Vapi may fit Evaluate Vapi when its integrations, testing workflow or support packages are a better match for your team. A higher platform fee can still be worthwhile if it removes work you would otherwise own. ### When APIFleet may fit Evaluate APIFleet when you want configurable assistants, browser tests, simulations and call logs with a lower published platform fee and no monthly subscription. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Compare the platform portion This example holds AI provider and carrier costs outside both totals. Vapi’s published $0.05 hosting rate is compared with APIFleet’s $0.03 platform rate. It excludes optional packages and negotiated discounts. Monthly connected AI minutes Enter a whole number from 1 to 1,000,000. APIFleet platform $300.00 Vapi hosting $500.00 Platform difference $200.00 USD. The difference is for the platform component only, not the total cost of calls. JavaScript is off. The example above shows 10,000 minutes. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Vapi estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | 1,000 × $0.05 = $50.00 hosting; providers extra | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | 10,000 × $0.05 = $500.00 hosting; providers extra | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Vapi’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Vapi, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Replay your tool calls and verify their request and response formats. - Compare connected AI time, provider usage and telephone charges separately. - Test interruption handling, transfers and failed tools on the same scripts. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Vapi pricing](https://vapi.ai/pricing). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Vapi. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Retell AI](https://apifleet.dev/compare/retell-ai)[APIFleet vs Bland AI](https://apifleet.dev/compare/bland-ai)[APIFleet vs Bolna](https://apifleet.dev/compare/bolna) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs Retell AI Source: https://apifleet.dev/compare/retell-ai APIFleet vs Retell AI: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsRetell AI A managed voice-agent platform with a configurable, component-based call price. Hosted platforms · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Retell AI pricing](https://www.retellai.com/pricing). | What matters | APIFleet | Retell AI | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | $0.07–$0.31 / min Published AI voice range | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Usage-based pricing that varies with the selected voice, model and add-ons. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | Retell lists voice infrastructure at $0.055 per minute, alongside voice and model charges. Telephony and optional features affect the final bill. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | Hosted agents with simulation testing, call analytics, APIs and webhooks. | ## Put the configured quote beside a configured quote. Retell’s headline range and APIFleet’s platform fee describe different things. Build a sample agent on paper first: model, voice, phone route and optional analysis. Then compare the full configuration. A bare orchestration fee should never be presented as a complete alternative to a bundled call rate. ### When Retell AI may fit Evaluate Retell when its agent-building and analysis workflow fits the people who will maintain your calls. Include the features you actually need in the cost estimate. ### When APIFleet may fit Evaluate APIFleet when you want to manage assistants, tools, credentials and call logs in one developer workspace with an explicitly separate platform fee. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Retell AI estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Retell AI’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Retell AI, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Record each enabled add-on before comparing estimates. - Run the same successful, interrupted and transferred call scenarios. - Check where transcripts, webhooks and tool outcomes land in your application. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Retell AI pricing](https://www.retellai.com/pricing). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Retell AI. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Vapi](https://apifleet.dev/compare/vapi)[APIFleet vs Bland AI](https://apifleet.dev/compare/bland-ai)[APIFleet vs ElevenLabs Agents](https://apifleet.dev/compare/elevenlabs) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs Bland AI Source: https://apifleet.dev/compare/bland-ai APIFleet vs Bland AI: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsBland AI Bundled AI talk time and conversation pathways, with usage and subscription options. Hosted platforms · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Bland AI pricing](https://www.bland.ai/pricing). | What matters | APIFleet | Bland AI | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | $0.14 / min Start plan; AI components included | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Start has no monthly platform fee. Build is $299 per month plus $0.12 per minute. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | The talk-time rate includes the model, transcription and voice. Transfer time has separate published rates. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | Conversation Pathways and integrations support structured telephone workflows. | ## Decide how much pricing simplicity is worth to you. A bundled speech-and-model rate can make forecasting easier. A component-based stack gives you a different kind of control: changing a voice or model changes the bill. APIFleet’s $0.03 platform fee needs those component costs added before it belongs next to Bland’s talk-time price. ### When Bland AI may fit Evaluate Bland when its Pathways workflow and bundled AI pricing match your call design. Model both normal conversation and the human-transfer portion of your traffic. ### When APIFleet may fit Evaluate APIFleet when provider choice and visibility into individual call-cost components matter more than having one bundled AI rate. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Bland AI estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Bland AI’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Bland AI, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Separate AI talk time from human-transfer time in your sample traffic. - Ask which telephone charges are covered by the chosen quote. - Recreate pathway decisions as explicit prompts and tools, then test each branch. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Bland AI pricing](https://www.bland.ai/pricing). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Bland AI. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Retell AI](https://apifleet.dev/compare/retell-ai)[APIFleet vs Vapi](https://apifleet.dev/compare/vapi)[APIFleet vs Synthflow](https://apifleet.dev/compare/synthflow) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs Synthflow Source: https://apifleet.dev/compare/synthflow APIFleet vs Synthflow: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsSynthflow An enterprise deployment offering with implementation support and annual contracts. Enterprise platforms · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Synthflow pricing](https://synthflow.ai/pricing). | What matters | APIFleet | Synthflow | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | From $30,000 / year Published enterprise contract floor | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Enterprise contracts depend on volume, concurrency, integrations and support requirements. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | The current offer includes implementation, testing, training and launch support. Confirm the complete scope in a proposal. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | Enterprise telephony and business integrations form part of a managed rollout. | ## Compare the delivery model as well as the software. This is not a simple per-minute contest. A managed enterprise project can include work that your own engineers would need to do on a developer platform. Compare your internal implementation budget, rollout responsibilities and contract requirements alongside usage. ### When Synthflow may fit Evaluate Synthflow when you need an enterprise implementation engagement and its proposed scope fits your procurement and operations requirements. ### When APIFleet may fit Evaluate APIFleet when your team wants to configure and integrate agents itself, fund usage from $10 and avoid an annual platform commitment. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Synthflow estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Synthflow’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Synthflow, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Write down who owns integrations, testing and launch support. - Request a quote at your expected concurrency and call volume. - Confirm contractual requirements before assuming a self-serve platform can replace them. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Synthflow pricing](https://synthflow.ai/pricing). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Synthflow. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs PolyAI](https://apifleet.dev/compare/polyai)[APIFleet vs Voiceflow](https://apifleet.dev/compare/voiceflow)[APIFleet vs Bland AI](https://apifleet.dev/compare/bland-ai) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs ElevenLabs Agents Source: https://apifleet.dev/compare/elevenlabs APIFleet vs ElevenLabs Agents: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsElevenLabs Agents A voice-led agent platform with monthly minute allowances and usage overages. Hosted platforms · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [ElevenLabs Agents pricing](https://elevenlabs.io/pricing/agents). | What matters | APIFleet | ElevenLabs Agents | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | $99 / month Pro: 1,238 included agent minutes | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Subscription plans include minute allowances. Pro lists additional standard minutes at $0.08. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | LLM usage is additional. Connected telephone carriers bill separately. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | Agents, workflows, knowledge and a conversational widget sit alongside ElevenLabs voices. | ## A voice provider and a complete agent platform are different choices. Using an ElevenLabs voice inside APIFleet is different from building the whole agent in ElevenLabs Agents. Compare the complete workflow and how much of a monthly allowance you will use. Dividing a subscription by included minutes only makes sense when those minutes are actually consumed. ### When ElevenLabs Agents may fit Evaluate ElevenLabs Agents when its integrated voice and agent workflow is the best fit. Test your real languages, interruptions and tool use with the voices you intend to ship. ### When APIFleet may fit Evaluate APIFleet when you want to choose speech and model providers independently and use prepaid usage without a monthly platform subscription. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | ElevenLabs Agents estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer ElevenLabs Agents’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from ElevenLabs Agents, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Estimate unused allowance as well as overage minutes. - Add LLM and carrier charges to the subscription calculation. - Compare the same voice where possible so voice preference does not obscure platform behavior. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [ElevenLabs Agents pricing](https://elevenlabs.io/pricing/agents). This is APIFleet’s assessment, not an independent benchmark or an endorsement by ElevenLabs Agents. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Retell AI](https://apifleet.dev/compare/retell-ai)[APIFleet vs Deepgram Voice Agent API](https://apifleet.dev/compare/deepgram)[APIFleet vs Vapi](https://apifleet.dev/compare/vapi) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs Voiceflow Source: https://apifleet.dev/compare/voiceflow APIFleet vs Voiceflow: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsVoiceflow A team-oriented agent builder spanning voice, chat and agency workflows. Hosted platforms · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Voiceflow pricing](https://www.voiceflow.com/pricing). | What matters | APIFleet | Voiceflow | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | Request pricing Business and agency offerings | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | The public pricing page directs businesses to a quote and describes usage-based agency pricing. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | Pricing depends on the engagement. Ask for platform, usage and service charges separately. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | Voice and chat agents, business integrations and multi-client agency workflows. | ## Choose for the people maintaining the conversation. A team building both chat and voice experiences has different needs from a developer operating telephone agents. Compare authoring, review and handoff workflows before concentrating on a minute rate. Do not budget from an old plan price when the current site asks for a quote. ### When Voiceflow may fit Evaluate Voiceflow when your team needs to coordinate voice and chat experiences or maintain multiple client projects through its agency workflow. ### When APIFleet may fit Evaluate APIFleet when your main job is configuring, testing and operating voice agents with an API and a focused developer dashboard. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Voiceflow estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Voiceflow’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Voiceflow, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Have the person who maintains the agent make a real change in each tool. - List chat requirements separately from telephone requirements. - Ask for a quote that includes your workspace, client and usage assumptions. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Voiceflow pricing](https://www.voiceflow.com/pricing). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Voiceflow. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Synthflow](https://apifleet.dev/compare/synthflow)[APIFleet vs Vapi](https://apifleet.dev/compare/vapi)[APIFleet vs Retell AI](https://apifleet.dev/compare/retell-ai) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs Bolna Source: https://apifleet.dev/compare/bolna APIFleet vs Bolna: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsBolna Usage-based voice agents with BYOK options and a focus on Indian-language conversations. Hosted platforms · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Bolna pricing](https://www.bolna.ai/pricing). | What matters | APIFleet | Bolna | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | From $0.06 / min AI components; platform and telephony extra | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Prepaid usage and volume options. Billing increments vary by offering. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | The advertised starting rate covers speech and model components; Bolna says platform and telephony charges are added. BYOK is available. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | Voice agents with multilingual options including Indian languages. | ## Test the languages and billing increments your traffic needs. Two platforms offering provider choice can still produce different results for the same market. Use recordings and scenarios in your actual languages, accents and code-switching patterns. Check the billed duration of short calls; a minute rate alone misses the effect of billing increments. ### When Bolna may fit Evaluate Bolna when its language coverage and telephony arrangements suit your market. Validate those choices with real speakers and the intended call route. ### When APIFleet may fit Evaluate APIFleet when you want its assistant, simulation and call-log workflow with a platform charge calculated per connected AI second. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Bolna estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Bolna’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Bolna, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Confirm the complete quote, including the platform charge. - Test code-switching and local names with your chosen providers. - Compare short-call rounding and provider-key ownership. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Bolna pricing](https://www.bolna.ai/pricing). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Bolna. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Vapi](https://apifleet.dev/compare/vapi)[APIFleet vs Retell AI](https://apifleet.dev/compare/retell-ai)[APIFleet vs Telnyx AI Assistants](https://apifleet.dev/compare/telnyx) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs LiveKit Source: https://apifleet.dev/compare/livekit APIFleet vs LiveKit: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsLiveKit Realtime infrastructure and an agent framework for teams building their own application. APIs & frameworks · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [LiveKit pricing](https://livekit.com/pricing) · [LiveKit Agents documentation](https://docs.livekit.io/agents/). | What matters | APIFleet | LiveKit | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | Cloud plans + usage Ship starts at $50 / month | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Cloud plans meter agent sessions and other resources separately. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | Ship includes 5,000 agent-session minutes, then $0.01 per minute. Inference, transport and telephony can add separate charges. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | An agent framework and realtime infrastructure with cloud deployment options. | ## Decide which parts of the voice application you want to own. Agent-session compute is not the same product as a configured assistant workspace. For a framework-based build, budget for your application, deployment and operations as well as cloud usage. That engineering ownership can be exactly what a team wants when the experience needs deeper customization. ### When LiveKit may fit Evaluate LiveKit when you want to build the agent application and realtime experience yourself. Prototype the hardest interaction before estimating the rest of the project. ### When APIFleet may fit Evaluate APIFleet when you want to start from configurable assistants, tools, credentials, browser tests and call logs instead of assembling that management layer. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | LiveKit estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer LiveKit’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from LiveKit, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Separate agent compute, inference, media transport and telephone costs. - Estimate who will maintain deployment and operational tooling. - Prove any custom realtime interaction before committing to a migration. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [LiveKit pricing](https://livekit.com/pricing) · [LiveKit Agents documentation](https://docs.livekit.io/agents/). This is APIFleet’s assessment, not an independent benchmark or an endorsement by LiveKit. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Pipecat](https://apifleet.dev/compare/pipecat)[APIFleet vs Twilio ConversationRelay](https://apifleet.dev/compare/twilio)[APIFleet vs Deepgram Voice Agent API](https://apifleet.dev/compare/deepgram) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs Pipecat Source: https://apifleet.dev/compare/pipecat APIFleet vs Pipecat: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsPipecat An open-source Python framework for composable voice and multimodal pipelines. APIs & frameworks · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Pipecat Cloud pricing](https://www.daily.co/pricing/pipecat-cloud/) · [Pipecat framework](https://github.com/pipecat-ai/pipecat). | What matters | APIFleet | Pipecat | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | $0.01 / active min Pipecat Cloud agent-1x hosting only | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | The framework is open source. Cloud hosting charges for active and reserved capacity. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | Cloud agent-1x active compute is $0.01 per minute; reserved capacity is $0.0005 per minute. Transport and AI services are separate. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | Python pipelines connect AI services, audio processing and transports. | ## Compare a framework build with a managed workspace. Pipecat gives an engineering team control over the conversation pipeline. Its hosting price should be compared with hosting, not treated as a full call bill. Add provider usage, transport and the work of building configuration, logs, credentials and deployment around your agent. ### When Pipecat may fit Evaluate Pipecat when custom pipeline behavior is central to the product and your team wants to own the Python implementation and its operations. ### When APIFleet may fit Evaluate APIFleet when the immediate need is operating configurable agents through an existing dashboard and API with built-in tools, simulations and call logs. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Pipecat estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Pipecat’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Pipecat, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Measure reserved capacity even when no calls are active. - List the management and observability tools your application needs. - Prototype custom processors and compare ongoing maintenance work. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Pipecat Cloud pricing](https://www.daily.co/pricing/pipecat-cloud/) · [Pipecat framework](https://github.com/pipecat-ai/pipecat). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Pipecat. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs LiveKit](https://apifleet.dev/compare/livekit)[APIFleet vs Deepgram Voice Agent API](https://apifleet.dev/compare/deepgram)[APIFleet vs Twilio ConversationRelay](https://apifleet.dev/compare/twilio) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs Telnyx AI Assistants Source: https://apifleet.dev/compare/telnyx APIFleet vs Telnyx AI Assistants: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsTelnyx AI Assistants An integrated voice engine, assistant platform and telephony ecosystem. Hosted platforms · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Telnyx Voice AI pricing](https://telnyx.com/pricing/voice-ai-agents). | What matters | APIFleet | Telnyx AI Assistants | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | $0.05 / min Voice engine; LLM and telephony extra | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Voice-engine usage plus model tokens and telephone charges. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | The engine includes orchestration, hosted transcription and text-to-speech. Its published billing rounds each call to 60-second increments. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | AI assistants alongside Telnyx telephony and model services. | ## Using a carrier does not commit you to its agent platform. Telnyx can provide telephone connectivity while a different platform runs the assistant. APIFleet also supports Telnyx carrier credentials. Compare the integrated assistant offering on its own terms: its engine includes speech services that must be added to APIFleet’s platform charge. ### When Telnyx AI Assistants may fit Evaluate Telnyx AI Assistants when an integrated telephony and voice-engine setup suits your operational model. Include the selected LLM and call destinations in the estimate. ### When APIFleet may fit Evaluate APIFleet when you want a separate assistant-management layer and provider choice while keeping your carrier relationship. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Telnyx AI Assistants estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Telnyx AI Assistants’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Telnyx AI Assistants, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Check which costs belong to the carrier and which to the AI engine. - Model short calls using each service’s actual billing increments. - Validate number routing and transfers before changing a live configuration. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Telnyx Voice AI pricing](https://telnyx.com/pricing/voice-ai-agents). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Telnyx AI Assistants. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Twilio ConversationRelay](https://apifleet.dev/compare/twilio)[APIFleet vs Retell AI](https://apifleet.dev/compare/retell-ai)[APIFleet vs Bolna](https://apifleet.dev/compare/bolna) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs Twilio ConversationRelay Source: https://apifleet.dev/compare/twilio APIFleet vs Twilio ConversationRelay: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsTwilio ConversationRelay A speech interface for developers connecting their own conversational application to Twilio. APIs & frameworks · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Twilio conversational AI pricing](https://www.twilio.com/en-us/products/conversational-ai/pricing) · [ConversationRelay documentation](https://www.twilio.com/docs/voice/conversationrelay). | What matters | APIFleet | Twilio ConversationRelay | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | $0.07 / min ConversationRelay; Voice costs separate | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Per-minute ConversationRelay usage, with telephone usage billed separately. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | ConversationRelay handles the speech connection. Your application supplies the conversation logic and LLM integration. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | A WebSocket integration connects a developer-controlled application to speech and calls. | ## Choose between an application building block and an agent workspace. ConversationRelay is useful to evaluate when you already own the conversational backend. APIFleet instead supplies a configurable assistant runtime and management interface. Using Twilio as a carrier with APIFleet is a separate architecture from running ConversationRelay. ### When Twilio ConversationRelay may fit Evaluate ConversationRelay when your application should own the conversational logic and you want to connect it to Twilio’s speech and telephone services. ### When APIFleet may fit Evaluate APIFleet when you want to configure prompts, providers and HTTP tools, then test and inspect calls in an existing workspace. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Twilio ConversationRelay estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Twilio ConversationRelay’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Twilio ConversationRelay, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Include your model, application hosting and Twilio Voice charges. - Test streaming, interruption and reconnect behavior in your application. - Map existing telephone routing before changing the speech runtime. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Twilio conversational AI pricing](https://www.twilio.com/en-us/products/conversational-ai/pricing) · [ConversationRelay documentation](https://www.twilio.com/docs/voice/conversationrelay). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Twilio ConversationRelay. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Telnyx AI Assistants](https://apifleet.dev/compare/telnyx)[APIFleet vs LiveKit](https://apifleet.dev/compare/livekit)[APIFleet vs Deepgram Voice Agent API](https://apifleet.dev/compare/deepgram) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs Deepgram Voice Agent API Source: https://apifleet.dev/compare/deepgram APIFleet vs Deepgram Voice Agent API: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsDeepgram Voice Agent API A managed conversational voice API with bundled and bring-your-own-provider options. APIs & frameworks · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Deepgram pricing](https://deepgram.com/pricing). | What matters | APIFleet | Deepgram Voice Agent API | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | $0.075 / min Standard pay-as-you-go Voice Agent | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Voice Agent pricing changes with the selected tier and provider ownership. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | Standard is $0.075 per minute. Custom BYO LLM and TTS is listed at $0.05 per minute; those external providers have their own bills. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | A realtime conversation API for applications integrating speech and agent behavior. | ## Compare the whole agent API, not a transcription rate. Deepgram’s transcription service and Voice Agent API solve different parts of a voice stack. When evaluating the complete agent API, identify the components included in the chosen tier and the application code you will maintain around it. A BYO rate moves some charges to other providers. ### When Deepgram Voice Agent API may fit Evaluate Deepgram when you want a managed voice API inside an application you control. Test your intended configuration rather than assuming all pricing tiers behave identically. ### When APIFleet may fit Evaluate APIFleet when you also want a workspace for assistants, tools, knowledge, browser tests, simulations and call logs. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Deepgram Voice Agent API estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Deepgram Voice Agent API’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Deepgram Voice Agent API, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Identify whether you need transcription or the complete Voice Agent API. - Add direct provider costs when choosing a BYO configuration. - Budget for the application and management interface around the API. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Deepgram pricing](https://deepgram.com/pricing). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Deepgram Voice Agent API. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs ElevenLabs Agents](https://apifleet.dev/compare/elevenlabs)[APIFleet vs LiveKit](https://apifleet.dev/compare/livekit)[APIFleet vs Pipecat](https://apifleet.dev/compare/pipecat) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs Ultravox Source: https://apifleet.dev/compare/ultravox APIFleet vs Ultravox: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsUltravox A speech-native voice-agent service with usage-based pricing and SIP connectivity. APIs & frameworks · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [Ultravox pricing and product notice](https://www.ultravox.ai/pricing). | What matters | APIFleet | Ultravox | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | $0.05 / min Pay-as-you-go; SIP extra | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Usage-based pricing with additional plan options. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | The published pay-as-you-go rate is $0.05 per minute. SIP is listed at an additional $0.005 per minute. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | A speech-native agent approach. The site announces an acquisition by Inworld; confirm current onboarding and support terms. | ## Evaluate the conversation architecture, then its operating terms. A speech-native approach and a separately configured speech/model pipeline make different engineering choices. Test actual conversations instead of inferring quality from the architecture label. Also confirm which product and support terms apply when starting a new deployment. ### When Ultravox may fit Evaluate Ultravox when its speech-native behavior fits your use case and its current commercial and integration terms meet your requirements. ### When APIFleet may fit Evaluate APIFleet when you want a configurable provider stack and a workspace for testing, tools, knowledge and call inspection. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | Ultravox estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer Ultravox’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from Ultravox, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Validate interruptions, names, tool calls and recovery with recorded scenarios. - Include SIP and carrier charges in your telephone estimate. - Confirm current onboarding, support and migration terms directly. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [Ultravox pricing and product notice](https://www.ultravox.ai/pricing). This is APIFleet’s assessment, not an independent benchmark or an endorsement by Ultravox. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Deepgram Voice Agent API](https://apifleet.dev/compare/deepgram)[APIFleet vs ElevenLabs Agents](https://apifleet.dev/compare/elevenlabs)[APIFleet vs Vapi](https://apifleet.dev/compare/vapi) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # APIFleet vs PolyAI Source: https://apifleet.dev/compare/polyai APIFleet vs PolyAI: pricing & trade-offs | APIFleet - - - - - - [Skip to content](#main) # APIFleet vsPolyAI An enterprise conversational platform focused on customer-service operations. Enterprise platforms · Reviewed 19 October 2026 On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## At a glance Compare the scope of each rate before comparing the number. All amounts below are USD. Scroll across the table to see both platforms. Published pricing and product scope. Vendor sources: [PolyAI platform and enterprise contact](https://poly.ai/). | What matters | APIFleet | PolyAI | | --- | --- | --- | | Starting point | $0.03 per connected AI minute Platform fee, billed per second | Scope a quote Enterprise requirements and deployment | | Payment model | Prepaid usage. $10 minimum top-up. No monthly subscription or free credits. | Discuss enterprise scope with sales; the public site does not provide a comparable standard per-minute quote. | | Cost scope | AI providers and carrier charges are additional. Customer-owned keys are paid directly to providers. | Confirm implementation, usage, support and integration responsibilities in the proposal. | | Working style | Configurable assistants, tools, knowledge, browser tests, simulations and call logs. | Enterprise conversational agents and Dialog Studio tooling for customer interactions. | ## Compare operational requirements before procurement models. Contact-center projects can involve integration, procurement and operating requirements that go well beyond configuring an assistant. Put those requirements in writing. A lower usage price cannot substitute for a contractual or operational capability your organization needs. ### When PolyAI may fit Evaluate PolyAI when you are selecting an enterprise customer-service platform and need a scoped engagement around your operations. ### When APIFleet may fit Evaluate APIFleet when a developer-led rollout with configurable agents, direct API integration and prepaid usage matches your requirements. APIFleet currently limits new workspace access. Existing users can sign in; contact us about a new project. Carrier accounts, standalone previews, file transcription and simulation caller/judge models require customer-owned credentials. ## Two workloads to price explicitly These hypothetical examples assume exactly 1,000 or 10,000 connected AI minutes. They calculate APIFleet’s platform portion only; model, speech, carrier, numbers and any other service charges must be added.Illustrative monthly workloads, USD | Workload | APIFleet platform arithmetic | PolyAI estimate | | --- | --- | --- | | Pilot: 1,000 minutes | 1,000 × $0.03 = $30.00 | Apply the vendor’s published or quoted terms to the same provider stack and duration. | | Operation: 10,000 minutes | 10,000 × $0.03 = $300.00 | Include subscriptions, allowances, overages, rounding and implementation work when applicable. | A bundled vendor rate cannot be compared directly to the APIFleet platform portion. We do not infer PolyAI’s concurrency or seat limits from a minute rate; confirm them for your planned workload. ### Run a one-assistant switching pilot Before switching from PolyAI, recreate one assistant, replay its tool requests, test interruptions and transfers, then move one controlled route with a written rollback. Use the [voice-agent migration checklist](https://apifleet.dev/blog/migrate-voice-agents) and [conversation test plan](https://apifleet.dev/blog/test-voice-agents) with the vendor-specific checks below.Test outcomes and compare the same cost components before moving traffic. ## What to test before switching - Document required integrations and the team responsible for each one. - Ask for usage, implementation and support costs as distinct line items. - Validate procurement requirements directly; do not assume equivalent contracts. There is no universal one-click import. Map prompts, tools, credentials and routing explicitly, then run controlled calls. Our [gradual migration guide](https://apifleet.dev/blog/migrate-voice-agents) gives you a sequence with a rollback boundary. ## Sources & review Official vendor pages checked on 19 October 2026. [PolyAI platform and enterprise contact](https://poly.ai/). This is APIFleet’s assessment, not an independent benchmark or an endorsement by PolyAI. Prices and packaging can change. Confirm the current terms and test your intended configuration before committing. ## Keep comparing. [All platforms ](https://apifleet.dev/compare) [APIFleet vs Synthflow](https://apifleet.dev/compare/synthflow)[APIFleet vs Voiceflow](https://apifleet.dev/compare/voiceflow)[APIFleet vs Retell AI](https://apifleet.dev/compare/retell-ai) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # What does a voice agent actually cost? Source: https://apifleet.dev/blog/voice-agent-costs What does a voice agent actually cost? | APIFleet - - - - - - [Skip to content](#main) # What does a voice agent actually cost? A price per minute is only useful when you know what is inside that minute. Start with the components, then apply them to the calls you expect to handle. APIFleet team · 19 October 2026 · 3 min read On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## Start with three separate costs A voice call usually combines a platform, AI services and a telephone connection. Vendors package those pieces differently. One headline rate may cover orchestration alone; another may include transcription, a model and a voice. Put each quote into the same categories before comparing it. Platform Running and coordinating the assistant. APIFleet charges $0.03 per connected AI minute, billed per second. AI providers The model, transcription and generated speech. Usage may be measured in tokens, audio duration or characters rather than call minutes. Telephone carrier The connection to the telephone network. Account for the destination, direction, number rental and any separate call legs. A browser conversation has no telephone-network leg, but it still uses the platform and AI services. A call transferred to a person may continue accumulating carrier costs after the AI portion ends. ## Work through one call Assume an illustrative call has exactly 60 connected AI seconds, $0.0400 of AI provider usage and $0.0100 of carrier usage. These are example inputs, not a quote for a particular model, voice or destination. Illustrative 60-second call, USD | Component | Cost | | --- | --- | | APIFleet platform | $0.0300 | | AI providers | $0.0400 | | Carrier | $0.0100 | | Combined cost | $0.0800 | If APIFleet funds the AI providers, the platform and recorded provider usage at configured rates settle against your prepaid balance. Customer-owned provider keys are paid directly to those providers and are not billed a second time by APIFleet. Your carrier account is paid separately. The combined cost is therefore not necessarily one invoice. For 90 connected AI seconds, the platform portion is $0.0450. Do not assume the other components rise in exactly the same proportion: model context, speaking time and carrier rounding can differ. ## Turn calls into a monthly estimate Multiply expected connected AI minutes by the platform rate, then add provider and carrier estimates from representative calls. At 10,000 connected AI minutes, APIFleet’s platform portion is $300. That figure excludes AI providers and telephony. Use a mix of short questions, normal conversations, long calls and transfers. A single successful demo rarely represents production traffic. Keep separate assumptions for call volume, average duration, model context and how much the agent speaks. For subscription alternatives, include the monthly fee, unused included minutes and overage charges. For a framework you host yourself, add compute, idle capacity and the engineering work required to operate it. ## Ask the same questions of every quote - Which speech and model services are included, and which are added later? - Does billing round each call, each component or the total usage? - What happens during silence, transfers and unsuccessful calls? - Are analysis, recording, numbers or support separate charges? - Who pays each provider when customer-owned credentials are used? Our [comparison directory](https://apifleet.dev/compare) separates published platform rates from bundled and quote-based offerings. For a close orchestration-fee comparison, see [APIFleet vs Vapi](https://apifleet.dev/compare/vapi). ## Treat prepaid funding as a budget control APIFleet has no monthly subscription or free credits. The minimum top-up is $10. Calls reserve funds while they run; unused reserved funds return to the available balance when the call settles. A hold is not an extra fee. Keep enough available balance for concurrent calls and watch provider accounts that you fund directly. A prepaid platform balance does not cap a separate carrier or model account. Review actual call costs before increasing traffic, and keep estimates separate from provider invoices. ## Continue with a practical next step - [APIFleet API and configuration documentation](https://apifleet.dev/docs) - [Compare voice-agent platforms and their pricing](https://apifleet.dev/compare) - [BYOK: who pays for what?](https://apifleet.dev/blog/bring-your-own-keys) - [Test the conversation, not just the happy path](https://apifleet.dev/blog/test-voice-agents) - [Voice agent tools: a practical checklist](https://apifleet.dev/blog/voice-agent-tools) ## Sources and evidence - [APIFleet product and pricing](https://apifleet.dev/) · observed 2026-10-19 - [APIFleet API documentation](https://apifleet.dev/docs) · observed 2026-10-19 Prepared with AI assistance and checked against the linked evidence. Examples are illustrative unless explicitly documented as measured results. ## Next on your reading list. [BYOK: who pays for what?](https://apifleet.dev/blog/bring-your-own-keys)[Test the conversation, not just the happy path](https://apifleet.dev/blog/test-voice-agents)[Voice agent tools: a practical checklist](https://apifleet.dev/blog/voice-agent-tools) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # BYOK: who pays for what? Source: https://apifleet.dev/blog/bring-your-own-keys BYOK: who pays for what? | APIFleet - - - - - - [Skip to content](#main) # BYOK: who pays for what? Bring your own key changes who pays the provider. It does not remove the platform’s work, make calls free or make every credential interchangeable. APIFleet team · 19 October 2026 · 3 min read On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## Draw the payment boundary first BYOK means using credentials from a provider account you control. When your key pays for model or speech usage, that provider bills your account directly. APIFleet still charges its $0.03 per connected AI minute platform fee, billed per second. When APIFleet supplies a supported provider connection instead, recorded provider usage at configured rates is added to the platform charge in your prepaid balance. These rates are usage accounting, not a reconciliation of the provider’s final invoice. Payment ownership in APIFleet | Usage | Who collects payment? | | --- | --- | | Platform time | APIFleet prepaid balance | | APIFleet-funded AI | APIFleet prepaid balance | | Customer-owned AI key | Your AI provider | | Telephone connection | Your carrier | ## Use BYOK for a concrete reason A direct provider relationship can be useful when you already have an account, negotiated pricing, a model configuration or a usage-management process that you want to retain. It also gives you another account to operate. Before choosing BYOK, identify who owns payment methods, spend alerts, key rotation and provider support. If nobody owns those jobs, a working demo can become a production outage when a balance or quota is exhausted. Do not assume a provider offers the same features on every account or in every region. Check access to the exact model and voice your assistant uses before moving traffic. ## Configure one provider at a time - Choose the assistant’s model, transcription and voice configuration. - Add the corresponding provider credentials in the workspace’s Credentials section. Keep secrets out of prompts, knowledge files and public client code. - Run a short browser test using the intended configuration. - Inspect the call log and the provider’s usage dashboard. Confirm the connection succeeded and the usage appeared in the expected account. - Repeat for the telephone carrier, then test a controlled phone call. Phone carrier accounts, standalone voice previews, file transcription and simulation caller/judge models currently require customer-owned credentials in APIFleet. Do not assume every feature uses the same funding path as a live assistant call. ## Test the account failure, too A voice configuration is only as usable as its credentials. Test how your application handles an unavailable provider, an exhausted balance and a missing model permission. Make the user-facing fallback explicit: retry, collect a message, transfer, or end clearly. When rotating a key, first confirm the replacement can access the required services. Update the configured credential and run a controlled test before retiring the old key, taking in-flight calls into account. Keep a record of which assistant depends on which provider account. That small operational map is often more valuable during an incident than another dashboard chart. ## Read the two bills together APIFleet call logs help you inspect recorded usage; your provider dashboard shows the provider’s accounting. Compare the same time period and configuration. Differences in rounding, caching, discounts or billing timestamps can make a simple total-to-total comparison misleading. For an end-to-end estimate, add platform, provider and carrier costs even when they are collected separately. The [voice-agent cost guide](https://apifleet.dev/blog/voice-agent-costs) walks through that calculation. To compare alternatives, use the [platform directory](https://apifleet.dev/compare) and check each vendor’s BYOK terms directly. ## Continue with a practical next step - [APIFleet API and configuration documentation](https://apifleet.dev/docs) - [Compare voice-agent platforms and their pricing](https://apifleet.dev/compare) - [What does a voice agent actually cost?](https://apifleet.dev/blog/voice-agent-costs) - [Move your voice agents one route at a time](https://apifleet.dev/blog/migrate-voice-agents) - [Voice agent tools: a practical checklist](https://apifleet.dev/blog/voice-agent-tools) ## Sources and evidence - [APIFleet product and pricing](https://apifleet.dev/) · observed 2026-10-19 - [APIFleet API documentation](https://apifleet.dev/docs) · observed 2026-10-19 Prepared with AI assistance and checked against the linked evidence. Examples are illustrative unless explicitly documented as measured results. ## Next on your reading list. [What does a voice agent actually cost?](https://apifleet.dev/blog/voice-agent-costs)[Move your voice agents one route at a time](https://apifleet.dev/blog/migrate-voice-agents)[Voice agent tools: a practical checklist](https://apifleet.dev/blog/voice-agent-tools) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # Test the conversation, not just the happy path Source: https://apifleet.dev/blog/test-voice-agents Test the conversation, not just the happy path | APIFleet - - - - - - [Skip to content](#main) # Test the conversation, not just the happy path A pleasant demo proves that one conversation can work. A release decision needs evidence about the conversations that fail, drift or arrive at the wrong time. APIFleet team · 19 October 2026 · 3 min read On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## Define success as an observable outcome Start with the job, not the prompt. For a booking assistant, success might mean collecting the right date, checking availability, confirming the chosen time and receiving a successful booking response. A friendly goodbye is not evidence that a booking exists. Write a small set of acceptance conditions for each call type. Include conditions that must never happen, such as confirming an appointment after the booking tool failed. Give each test an expected tool outcome and a clear end state. Keep the assistant configuration, provider choices and test inputs with the result. Otherwise, a later change can make the old result impossible to interpret. ## Build a scenario set with deliberate friction A starting test matrix | Scenario | What to inspect | | --- | --- | | Normal request | Correct details and successful tool result | | Caller changes their mind | Old details are replaced before confirmation | | Interruption | The agent stops appropriately and hears the new request | | Silence or unclear speech | A useful recovery without invented information | | Tool timeout or failure | No false confirmation; a clear next step | | Human handoff | Correct routing and an understandable transition | Add local names, accents, background noise and code-switching when they reflect your callers. Do not use sensitive production recordings as convenient test fixtures without an appropriate basis and controls. ## Test in layers Begin with controlled tool responses so you can isolate conversational decisions from an unreliable integration. Then test against the real integration in a safe environment. Finally, test the actual audio path and telephone route. APIFleet provides browser tests, simulations and call logs. Use browser conversations for quick feedback and repeatable simulation scenarios for regression checks. Keep simulation results distinct from production evidence: a simulated caller does not reproduce every microphone, network or human behavior. Simulation caller and judge models require your own credentials. Test usage has a cost; APIFleet does not include free credits. Budget for evaluation as part of the deployment. ## Measure outcomes and listen to the failures Track task completion, incorrect actions, repeated questions, handoff outcomes and cost per completed task. A low cost per minute can be misleading if the agent takes longer or creates work for a person afterward. Listen to a sample of successful calls as well as failed ones. A transcript may hide awkward pauses, overlapping speech or a voice that is hard to understand. Look at tool requests and responses alongside the conversation. If you measure latency, define the interval. Time from a caller finishing speech to the first useful response is different from model token latency. Use the same measurement and test conditions when comparing stacks. ## Make the release decision before the test Set your acceptance criteria before looking at results. Decide which failures block release, who reviews ambiguous calls and what rollback looks like. Keep a small stable regression set and add a case whenever you find a meaningful new failure. Start with a controlled portion of traffic and observe the real outcomes. The [migration guide](https://apifleet.dev/blog/migrate-voice-agents) describes a staged rollout. If you are choosing a platform, apply this same test plan to the alternatives in [the comparison directory](https://apifleet.dev/compare). ## Continue with a practical next step - [APIFleet API and configuration documentation](https://apifleet.dev/docs) - [Compare voice-agent platforms and their pricing](https://apifleet.dev/compare) - [Move your voice agents one route at a time](https://apifleet.dev/blog/migrate-voice-agents) - [What does a voice agent actually cost?](https://apifleet.dev/blog/voice-agent-costs) - [Voice agent tools: a practical checklist](https://apifleet.dev/blog/voice-agent-tools) ## Sources and evidence - [APIFleet product and pricing](https://apifleet.dev/) · observed 2026-10-19 - [APIFleet API documentation](https://apifleet.dev/docs) · observed 2026-10-19 Prepared with AI assistance and checked against the linked evidence. Examples are illustrative unless explicitly documented as measured results. ## Next on your reading list. [Move your voice agents one route at a time](https://apifleet.dev/blog/migrate-voice-agents)[What does a voice agent actually cost?](https://apifleet.dev/blog/voice-agent-costs)[Voice agent tools: a practical checklist](https://apifleet.dev/blog/voice-agent-tools) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # Move your voice agents one route at a time Source: https://apifleet.dev/blog/migrate-voice-agents Move your voice agents one route at a time | APIFleet - - - - - - [Skip to content](#main) # Move your voice agents one route at a time Changing the agent platform does not have to mean changing every phone number, provider and integration on the same day. Make each change small enough to understand and reverse. APIFleet team · 19 October 2026 · 3 min read On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## Inventory the working system List the assistant prompts, models, voices, phone numbers, credentials, HTTP tools, knowledge sources and webhooks in use. Record who owns each external account and which systems depend on the call events. Capture the outcomes you rely on: a booking created, a lead delivered, a human transfer completed. Save representative test scenarios and configuration revisions. Migration success means preserving those outcomes, not just seeing the new dashboard load. Export only the data you are entitled to move and check the source platform’s export options. APIFleet does not provide an automatic import for every competitor; plan for explicit configuration and validation. ## Map behavior, not field names Recreate one assistant first. Prompts, tool schemas and webhook payloads may look similar across platforms while behaving differently. Check required fields, authentication, timeouts, error handling and the moment each event is delivered. Keep your existing backend integration behind a small adapter when that makes the boundary easier to test. For actions such as bookings and payments, use stable identifiers and duplicate protection so a retry does not create the action twice. Choose the same model and voice where supported for the initial comparison. Change the platform first; optimize providers after you have a useful baseline. ## Run controlled tests beside the old setup Create a test route or a separate test number. Validate the assistant in the browser, then on the intended telephone path. Use the [conversation test plan](https://apifleet.dev/blog/test-voice-agents) to cover interruptions, bad inputs, failed tools and handoffs. A parallel environment is not permission to duplicate live side effects. Keep test calls away from real bookings, outbound campaigns and production writes unless you deliberately authorize and observe them. Confirm billing ownership before testing. Fund the APIFleet prepaid balance, connect customer-owned carrier credentials and verify the provider accounts that should pay for AI usage. See [the BYOK guide](https://apifleet.dev/blog/bring-your-own-keys) for those boundaries. ## Move one route with a written rollback - Select a low-risk route and a time when someone can observe the result. - Record the old carrier routing configuration and the exact change required to restore it. - Complete or account for in-flight calls before changing the route. - Send a controlled call through the new path and verify the downstream outcome. - Watch errors, transfers, task completion and cost before increasing traffic. A public website domain and a carrier’s voice-routing configuration are separate concerns. Moving a landing page does not, by itself, move telephone calls. Likewise, preserving a phone number does not prove that callbacks and webhooks reach the correct application. ## Retire the old path after the evidence is clear Keep the old configuration available until you have enough representative traffic to evaluate the new setup. Decide the observation window from your call volume and risk, rather than choosing an arbitrary number of hours. Once the new path meets your criteria, remove unused credentials and routes, reconcile outstanding usage and keep the records your business needs. Check whether any integrations still point at the previous webhook or API host. Use the migration to simplify ownership: one person or team should know where routing lives, where failures appear and how to restore service. The best rollback procedure is short enough to follow during an incident. ## Continue with a practical next step - [APIFleet API and configuration documentation](https://apifleet.dev/docs) - [Compare voice-agent platforms and their pricing](https://apifleet.dev/compare) - [Test the conversation, not just the happy path](https://apifleet.dev/blog/test-voice-agents) - [BYOK: who pays for what?](https://apifleet.dev/blog/bring-your-own-keys) ## Sources and evidence - [APIFleet product and pricing](https://apifleet.dev/) · observed 2026-10-19 - [APIFleet API documentation](https://apifleet.dev/docs) · observed 2026-10-19 Prepared with AI assistance and checked against the linked evidence. Examples are illustrative unless explicitly documented as measured results. ## Next on your reading list. [Test the conversation, not just the happy path](https://apifleet.dev/blog/test-voice-agents)[BYOK: who pays for what?](https://apifleet.dev/blog/bring-your-own-keys) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access) --- # Voice agent tools: a practical checklist Source: https://apifleet.dev/blog/voice-agent-tools Voice agent tools: a practical checklist | APIFleet - - - - - - [Skip to content](#main) # Voice agent tools that preserve task outcomes Voice agent tools connect a conversation to actions such as checking availability or creating a booking. Define each tool’s success response, failure response and retry behavior before letting the assistant act on a caller’s behalf. APIFleet team · 19 October 2026 · 3 min read On this page Written by the APIFleet team.[Suggest a correction](mailto:mariano@apifleet.dev?subject=APIFleet%20content%20feedback) ## Define the action and its observable outcome Start with one business action and write down what proves it happened. For a booking, that proof might be a confirmed record with a booking identifier, date and time. A friendly assistant response or a successful network connection does not establish that the business action completed. Keep lookup tools separate from tools that change data when your integration permits it. A tool that only checks availability has a different retry risk from one that creates an appointment. Name the operation clearly and return the fields the assistant needs to explain the actual result. In APIFleet, configure the integration through Tools and attach the intended tools to the assistant. Keep provider credentials and integration secrets in their appropriate configuration, outside public client code and conversational instructions. Verify the endpoint and authentication against your own backend before testing a real caller. ## Treat a timeout as an unknown result A timeout tells you that a response did not arrive within the waiting period. It does not tell you whether the remote server completed the action. If an appointment was created just before the connection failed, blindly repeating the request can create a second appointment. HTTP defines some method semantics as idempotent, but a business action sent through POST does not become safe to repeat automatically. Your backend must deliberately support duplicate protection or provide a way to reconcile the original operation. Confirm those guarantees for the exact integration you use. For a hypothetical booking tool, generate a stable operation identifier before attempting the write and have the booking service enforce uniqueness. When the response is uncertain, retrieve the original operation’s status using that identifier. These are integration design steps, not a claim that APIFleet adds duplicate protection to every external booking system.Responses the assistant should distinguish | Tool result | Useful next behavior | | --- | --- | | Confirmed success | Explain the confirmed outcome and reference | | Validation failure | Ask for the specific missing or invalid detail | | Timeout or unknown result | Reconcile the original operation before repeating a write | | Confirmed rejection | Explain the failure and offer a supported next step | ## Test the complete path before moving traffic Write your expected result before making the test call. Include both the conversation outcome and the downstream record that should exist afterward. This makes it harder to mistake a reassuring sentence for a completed task. Begin with controlled test data and inspect the tool request, response and final conversation together. Check the result in your backend as well as the APIFleet call log. Then repeat the same scenario through the intended telephone route, because a browser conversation does not reproduce every carrier and audio condition. Release one integration change at a time and retain a route back to the previous configuration. Watch for duplicate records, misleading confirmations and unresolved operations before increasing traffic. If you later change a prompt, model or tool schema, replay the failure cases that originally justified the release. - Prepare a normal request, invalid input, a confirmed server error and a response that arrives after the configured timeout. - Run each case with test accounts and verify whether the downstream action happened zero times, once or more than once. - Interrupt the assistant before and after the write request and check that it does not invent a completed action. - Record the expected fallback and review ambiguous outcomes before enabling production traffic. ## Continue with a practical next step - [Configure assistants and tools through the APIFleet API](https://apifleet.dev/docs) - [Test interruptions, tools and task completion](https://apifleet.dev/blog/test-voice-agents) - [Move one voice-agent route with a rollback](https://apifleet.dev/blog/migrate-voice-agents) - [Compare voice-agent platform responsibilities](https://apifleet.dev/compare) ## Frequently asked questions ### Does a tool timeout mean the booking failed? No. The booking service may have completed the action before the response was lost. Reconcile the original operation before retrying a write. ### Does APIFleet make every external action idempotent? No universal duplicate-protection guarantee is implied. Your integration must implement and test the behavior supported by the external service. ## Sources and evidence - [APIFleet API documentation](https://apifleet.dev/docs) · observed 2026-10-19 - [RFC 9110: HTTP method semantics](https://www.rfc-editor.org/rfc/rfc9110.html) · observed 2026-10-19 Prepared with AI assistance and checked against the linked evidence. Examples are illustrative unless explicitly documented as measured results. ## Next on your reading list. [Test the conversation, not just the happy path](https://apifleet.dev/blog/test-voice-agents)[Move your voice agents one route at a time](https://apifleet.dev/blog/migrate-voice-agents) ## Bring your next conversation. Explore the API, or sign in to your existing workspace. New workspace access is currently limited; contact us to discuss your project. [Explore the docs ](https://apifleet.dev/docs)[Sign in](https://apifleet.dev/app/assistants)[Ask about access](mailto:mariano@apifleet.dev?subject=APIFleet%20workspace%20access)