# Get Activity Summary Source: https://docs.oneinbox.ai/api-reference/activity/get-activity-summary /openapi/openapi.yaml get /v1/activity/summary Aggregate activity report for your organization. Returns, in one call: API activity from the audit log grouped by action (`audit_actions`, bounded by the `since`/`until` window), lifetime resource totals (`resource_counts` — agents, calls, phone numbers, knowledge bases, tools, integrations, API keys, users), a call breakdown by status / outcome / end reason (`call_summary`), and error signals (`error_signals` — calls that ended in error, knowledge-base sources that failed ingestion, failed webhook deliveries). Use `GET /v1/audit-events` for the raw event feed behind these numbers, or with `?actor=me` to see only events made with the calling API key. # Create Agent Source: https://docs.oneinbox.ai/api-reference/agents/create-agent /openapi/openapi.yaml post /v1/agents # Delete Agent Source: https://docs.oneinbox.ai/api-reference/agents/delete-agent /openapi/openapi.yaml delete /v1/agents/{agent_id} # Get Agent Source: https://docs.oneinbox.ai/api-reference/agents/get-agent /openapi/openapi.yaml get /v1/agents/{agent_id} # List Agents Source: https://docs.oneinbox.ai/api-reference/agents/list-agents /openapi/openapi.yaml get /v1/agents # Update Agent Source: https://docs.oneinbox.ai/api-reference/agents/update-agent /openapi/openapi.yaml patch /v1/agents/{agent_id} # List Audit Events Source: https://docs.oneinbox.ai/api-reference/audit-events/list-audit-events /openapi/openapi.yaml get /v1/audit-events # Create Call Source: https://docs.oneinbox.ai/api-reference/calls/create-call /openapi/openapi.yaml post /v1/calls Create an outbound phone call. Matches the published spec. # Delete Call Source: https://docs.oneinbox.ai/api-reference/calls/delete-call /openapi/openapi.yaml delete /v1/calls/{call_id} # Get Call Source: https://docs.oneinbox.ai/api-reference/calls/get-call /openapi/openapi.yaml get /v1/calls/{call_id} # List Calls Source: https://docs.oneinbox.ai/api-reference/calls/list-calls /openapi/openapi.yaml get /v1/calls # List calls (cursor pagination) Source: https://docs.oneinbox.ai/api-reference/calls/list-calls-cursor-pagination /openapi/openapi.yaml get /v1/calls/cursor Cursor-paginated alternative to GET /v1/calls. Pass back the `next_cursor` value to fetch the next page. Recommended over offset pagination for large call lists (>10k rows) because it is O(log n) per page instead of O(offset+limit). # Patch Call Source: https://docs.oneinbox.ai/api-reference/calls/patch-call /openapi/openapi.yaml patch /v1/calls/{call_id} Set the call's outcome label. Outcome is the only mutable field — everything else (transcript, recording, duration, etc.) is worker-owned and only updatable via the internal endpoints. # Stop Call Source: https://docs.oneinbox.ai/api-reference/calls/stop-call /openapi/openapi.yaml post /v1/calls/{call_id}/stop # Health Source: https://docs.oneinbox.ai/api-reference/health/health /openapi/openapi.yaml get /v1/health # Create integration Source: https://docs.oneinbox.ai/api-reference/integrations/create-integration /openapi/openapi.yaml post /v1/integrations # Delete integration Source: https://docs.oneinbox.ai/api-reference/integrations/delete-integration /openapi/openapi.yaml delete /v1/integrations/{credential_id} # Get integration Source: https://docs.oneinbox.ai/api-reference/integrations/get-integration /openapi/openapi.yaml get /v1/integrations/{credential_id} # List integrations Source: https://docs.oneinbox.ai/api-reference/integrations/list-integrations /openapi/openapi.yaml get /v1/integrations # Update integration Source: https://docs.oneinbox.ai/api-reference/integrations/update-integration /openapi/openapi.yaml patch /v1/integrations/{credential_id} # Add a knowledge base source — file, URL, or inline text (auto-creates the KB) Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/add-a-knowledge-base-source-—-file-url-or-inline-text-auto-creates-the-kb /openapi/openapi.yaml post /v1/knowledge-bases/sources The single endpoint to add content to a knowledge base. You don't create a KB first — we auto-create one (named from `name`, the filename, or the URL) and attach your source. Returns a `job_id`; ingestion (parse → S3 → token count → vector index) runs in the background — poll `GET /v1/knowledge-bases/{kb_id}/jobs/{job_id}`. Three call shapes, one endpoint: - **File upload** (multipart/form-data): `file=@path/to/doc.pdf`. Allowed: pdf, docx, xlsx/xls, txt, md. - **URL** (multipart): `type=url&source=https://...` - **Inline text** (multipart): `type=text&source=...` The response's `source.knowledge_base_id` is the new KB id. To remove a source, use `DELETE /v1/knowledge-bases/{kb_id}/sources/{source_id}`. # Delete a knowledge base source (file / URL / inline text) Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/delete-a-knowledge-base-source-file-url-inline-text /openapi/openapi.yaml delete /v1/knowledge-bases/{kb_id}/sources/{source_id} Removes a single source from the KB along with its vector chunks and the stored file (S3). Get the `source_id` from `GET /v1/knowledge-bases/{kb_id}/sources`. Returns 404 if the source doesn't exist in this KB. # Delete Kb Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/delete-kb /openapi/openapi.yaml delete /v1/knowledge-bases/{kb_id} # Get Kb Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/get-kb /openapi/openapi.yaml get /v1/knowledge-bases/{kb_id} # Get Kb Job Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/get-kb-job /openapi/openapi.yaml get /v1/knowledge-bases/{kb_id}/jobs/{job_id} Poll the status of a background ingestion / indexing job. # List Kb Jobs Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/list-kb-jobs /openapi/openapi.yaml get /v1/knowledge-bases/{kb_id}/jobs Recent jobs for this KB (most-recent first, up to 20). # List Kb Sources Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/list-kb-sources /openapi/openapi.yaml get /v1/knowledge-bases/{kb_id}/sources # List Kbs Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/list-kbs /openapi/openapi.yaml get /v1/knowledge-bases # Update Kb Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/update-kb /openapi/openapi.yaml patch /v1/knowledge-bases/{kb_id} # Create Model Source: https://docs.oneinbox.ai/api-reference/llm-models/create-model /openapi/openapi.yaml post /v1/models # Delete Model Source: https://docs.oneinbox.ai/api-reference/llm-models/delete-model /openapi/openapi.yaml delete /v1/models/{model_id} # Get Model Source: https://docs.oneinbox.ai/api-reference/llm-models/get-model /openapi/openapi.yaml get /v1/models/{model_id} # Get Model Catalogue Source: https://docs.oneinbox.ai/api-reference/llm-models/get-model-catalogue /openapi/openapi.yaml get /v1/models/catalogue List the accepted `model` ids for a (kind, provider) so clients can pick a valid value — and power the model dropdown — without first POSTing a wrong one (#15). Declared BEFORE `/{model_id}` so 'catalogue' is never parsed as a model id. # List Models Source: https://docs.oneinbox.ai/api-reference/llm-models/list-models /openapi/openapi.yaml get /v1/models # Update Model Source: https://docs.oneinbox.ai/api-reference/llm-models/update-model /openapi/openapi.yaml patch /v1/models/{model_id} # Delete Phone Number Source: https://docs.oneinbox.ai/api-reference/phone-numbers/delete-phone-number /openapi/openapi.yaml delete /v1/phone-numbers/{phone_id} # Get Phone Number Source: https://docs.oneinbox.ai/api-reference/phone-numbers/get-phone-number /openapi/openapi.yaml get /v1/phone-numbers/{phone_id} # List Phone Numbers Source: https://docs.oneinbox.ai/api-reference/phone-numbers/list-phone-numbers /openapi/openapi.yaml get /v1/phone-numbers # Purchase Phone Number Source: https://docs.oneinbox.ai/api-reference/phone-numbers/purchase-phone-number /openapi/openapi.yaml post /v1/phone-numbers/purchase Buy a phone number through OneInbox and wire it to an agent in one step. OneInbox provisions the number on its own carrier account — the caller brings no external provider account or credentials. Pass a specific `phone_number` from GET /phone-numbers/search, or just filters to auto-pick one. # Register Phone Number Source: https://docs.oneinbox.ai/api-reference/phone-numbers/register-phone-number /openapi/openapi.yaml post /v1/phone-numbers # Search Available Numbers Source: https://docs.oneinbox.ai/api-reference/phone-numbers/search-available-numbers /openapi/openapi.yaml get /v1/phone-numbers/search Search phone numbers available to buy through OneInbox. Numbers come from OneInbox's own carrier inventory — no external provider account or credential is required to search. Buy one you like with POST /phone-numbers/purchase. # Update Phone Number Source: https://docs.oneinbox.ai/api-reference/phone-numbers/update-phone-number /openapi/openapi.yaml patch /v1/phone-numbers/{phone_id} # Create Tool Source: https://docs.oneinbox.ai/api-reference/tools/create-tool /openapi/openapi.yaml post /v1/tools # Delete Tool Source: https://docs.oneinbox.ai/api-reference/tools/delete-tool /openapi/openapi.yaml delete /v1/tools/{tool_id} # Get Tool Source: https://docs.oneinbox.ai/api-reference/tools/get-tool /openapi/openapi.yaml get /v1/tools/{tool_id} # List Tools Source: https://docs.oneinbox.ai/api-reference/tools/list-tools /openapi/openapi.yaml get /v1/tools # Update Tool Source: https://docs.oneinbox.ai/api-reference/tools/update-tool /openapi/openapi.yaml patch /v1/tools/{tool_id} # Get Usage Source: https://docs.oneinbox.ai/api-reference/usage/get-usage /openapi/openapi.yaml get /v1/usage # Get Voice Source: https://docs.oneinbox.ai/api-reference/voices/get-voice /openapi/openapi.yaml get /v1/voices/{voice_id} # Import Voice Source: https://docs.oneinbox.ai/api-reference/voices/import-voice /openapi/openapi.yaml post /v1/voices/import # List Voices Source: https://docs.oneinbox.ai/api-reference/voices/list-voices /openapi/openapi.yaml get /v1/voices # Create Webhook Source: https://docs.oneinbox.ai/api-reference/webhooks/create-webhook /openapi/openapi.yaml post /v1/webhooks # Delete Webhook Source: https://docs.oneinbox.ai/api-reference/webhooks/delete-webhook /openapi/openapi.yaml delete /v1/webhooks/{webhook_id} # Get Webhook Source: https://docs.oneinbox.ai/api-reference/webhooks/get-webhook /openapi/openapi.yaml get /v1/webhooks/{webhook_id} # List Webhook Deliveries Source: https://docs.oneinbox.ai/api-reference/webhooks/list-webhook-deliveries /openapi/openapi.yaml get /v1/webhooks/{webhook_id}/deliveries Delivery-attempt log for this webhook. Partners use this to verify we tried to deliver a specific event without filing a support ticket. Newest attempt first. Includes response_status / response_body / error fields from the most recent attempt on each row. # List Webhooks Source: https://docs.oneinbox.ai/api-reference/webhooks/list-webhooks /openapi/openapi.yaml get /v1/webhooks # Test Webhook Source: https://docs.oneinbox.ai/api-reference/webhooks/test-webhook /openapi/openapi.yaml post /v1/webhooks/{webhook_id}/test # Update Webhook Source: https://docs.oneinbox.ai/api-reference/webhooks/update-webhook /openapi/openapi.yaml patch /v1/webhooks/{webhook_id} # Create Call Outcome Source: https://docs.oneinbox.ai/api-reference/workspace/create-call-outcome /openapi/openapi.yaml post /v1/workspace/call-outcomes # List Call Outcomes Source: https://docs.oneinbox.ai/api-reference/workspace/list-call-outcomes /openapi/openapi.yaml get /v1/workspace/call-outcomes # Update Call Outcome Source: https://docs.oneinbox.ai/api-reference/workspace/update-call-outcome /openapi/openapi.yaml patch /v1/workspace/call-outcomes/{outcome_id} # Agents Source: https://docs.oneinbox.ai/concepts/agents An agent is the voice AI your callers talk to — it has a personality, a voice, and a set of actions it can take. ## What is an agent? An agent is a complete voice persona. When you create one with just a name, it is immediately usable — OneInbox automatically sets up a default LLM, a default voice, and a default system prompt. You only need to change these if you want to customise them. | Component | Default | Change it when... | | ------------------ | ----------------------------------------- | ---------------------------------------------------------------- | | **LLM** (AI brain) | Auto-created with a general system prompt | You want a specific persona, script, or temperature | | **Voice** | Default voice pre-configured | You want a specific voice from ElevenLabs or Cartesia | | **System prompt** | General-purpose assistant | You want the agent to follow specific instructions or scripts | | **Language** | `en` | You need the agent to transcribe a different language | | **Tools** | None | You want the agent to take actions (SMS, transfer, capture data) | A single agent handles browser calls (via the Web SDK) and direct phone calls — both outbound and inbound — you don't need a separate agent per call type. *** ## Create an agent You have two options — create with defaults and customise later, or provide your own config upfront. Both produce a fully working agent. ### Option A — Create with defaults Just a name. OneInbox automatically creates a default LLM, voice, and system prompt. Customise later using the `llm_id` and `agent_id` from the response. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/agents \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Support Agent" }' ``` ```json theme={null} { "id": "agt_abc123", "name": "Acme Support Agent", "llm_id": "llm_xyz789", "created_at": "2026-06-01T10:00:00Z" } ``` ### Option B — Create with your own config Pass any fields you want configured from the start. All fields except `name` are optional. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/agents \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Support Agent", "language": "en", "first_message": "Hi! Thanks for reaching out to Acme. How can I help you today?", "tts": { "provider": "elevenlabs", "voice_id": "" }, "silence_timeout_seconds": 10, "max_duration_seconds": 600, "interruption_sensitivity": 0.6, "enable_recording": true, "voicemail_detection": true, "voicemail_message": "Hi, please leave a message and we'll call you back." }' ``` The `llm_id` in the response is the auto-created AI model. Use it to set the system prompt, attach tools, or link knowledge bases — regardless of which option you used. Your agent is ready immediately. Test it with a quick browser call — no phone number needed, runs entirely over the internet (same mechanism the [Web SDK](/concepts/web-sdk) uses): ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/calls/web \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "agent_id": "agt_abc123" }' ``` *** ## Customise the defaults Out of the box the agent works with a general-purpose system prompt, a default voice, and a default LLM. To give your agent a specific personality or script, update the LLM model using the `llm_id` from the create response: ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "system_prompt": "You are a helpful sales rep for Acme Corp. Your goal is to qualify leads and book product demos. Keep all replies under two sentences. Be warm and direct.", "temperature": 0.7 }' ``` Changes apply to new calls immediately. One LLM model can power multiple agents — to share a brain across agents, PATCH the agent with `{ "llm_id": "llm_xyz789" }`. Update the model once and all agents using it pick up the change. To use a self-hosted or third-party LLM, set `provider` to `"custom"` and supply `custom_websocket_url`. The URL can be `wss://`, `ws://`, `https://`, or `http://` — the server must expose an OpenAI-compatible streaming chat completions interface. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/models \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "My self-hosted LLM", "provider": "custom", "custom_websocket_url": "wss://your-llm-server.example.com/v1/chat/completions", "system_prompt": "You are a helpful voice assistant.", "temperature": 0.7 }' ``` *** ## Browse available models The catalogue lists accepted model IDs for LLM, STT, and TTS providers — useful before setting a custom model on your agent or LLM. ```bash theme={null} # LLM providers — openai, anthropic, groq, shisa, openrouter curl "https://api-tokyo.oneinbox.ai/v1/models/catalogue?provider=openai" \ -H "Authorization: Bearer " # STT providers — deepgram, soniox, shisa, assembly_ai, whisper, azure curl "https://api-tokyo.oneinbox.ai/v1/models/catalogue?provider=deepgram" \ -H "Authorization: Bearer " # TTS providers — cartesia, elevenlabs, openai, deepgram, soniox, shisa, minimax curl "https://api-tokyo.oneinbox.ai/v1/models/catalogue?provider=cartesia" \ -H "Authorization: Bearer " ``` The `source` field on each item is `live` (fetched directly from the provider), `seed` (a static list shown without a credential), or `unverified`. *** ## Give your agent tools Tools (send SMS, capture caller data, transfer calls, book meetings, etc.) are attached to the **LLM model**, not the agent directly. **Why:** the LLM model is what decides what to do during a conversation. Tools are the actions it can take — so they live there. Any agent using that model inherits all its tools automatically. To add a tool, first create it, then attach it to the `llm_id` from your agent: ```bash theme={null} # 1. Create a tool (example: capture caller info) curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "capture_lead_info", "type": "extract_information", "description": "Extract the caller name, budget, and timeline from the conversation.", "extraction_schema": { "fields": [ { "name": "caller_name", "type": "string", "description": "Full name of the caller" }, { "name": "budget", "type": "string", "description": "Budget the caller mentioned" }, { "name": "timeline", "type": "string", "description": "Their decision timeline" } ] } }' # Save the returned tool "id" # 2. Attach it to the agent's LLM model curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "tool_ids": [""] }' ``` → [Tools guide](/guides/tools) — all 7 tool types with full examples *** ## Speech-to-text (STT) STT converts the caller's voice into text that the LLM can understand. Set the `transcriber` object on the agent to choose the provider and model. All STT providers below are platform-provided — no credential needed. | Provider | Models | Best for | | -------------- | ------------------------------------------- | ------------------------------------------------------------------- | | **Deepgram** | `nova-3` (default), `flux-en`, `flux-multi` | Low latency, high accuracy. `nova-3` recommended for most use cases | | **Soniox** | `stt-rt-v5`, `stt-rt-v4`, `stt-rt-v3` | High-accuracy real-time streaming | | **Shisa** | `shisa-asr-realtime` | Japanese language specialisation | | **Whisper** | `whisper-1` | Broad language coverage | | **AssemblyAI** | `best`, `nano`, `slam-1` | High accuracy for complex audio | | **Azure** | e.g. `en-US-JennyNeural` | Enterprise Azure deployments | ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/agents/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "transcriber": { "provider": "deepgram", "model": "nova-3", "language": "en" } }' ``` Set `language` to match the caller's language — e.g. `"hi"` for Hindi, `"ja"` for Japanese. Use `flux-multi` for multilingual calls where the language is unknown. *** ## Text-to-speech (TTS) TTS converts the agent's text replies into spoken audio. Set the `tts` object on the agent to choose the provider, voice, and speed. All TTS providers below are platform-provided — no credential needed. | Provider | Notable voices | Best for | | -------------- | --------------------------- | ------------------------------------- | | **Cartesia** | Sarah, Liam, Barbershop Man | Ultra-low latency, natural prosody | | **Deepgram** | Thalia, Asteria, Zeus | Fast, conversational | | **ElevenLabs** | Roger, Laura, Alice | High expressiveness, emotional range | | **OpenAI** | Alloy, Echo, Nova, Shimmer | Consistent quality, stable under load | | **Soniox** | — | Low-latency streaming TTS | | **Minimax** | Female Phone, Male Phone | Optimised for phone-quality audio | | **Shisa** | JA Female | Japanese language specialisation | ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/agents/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "tts": { "provider": "cartesia", "voice_id": "", "speed": 1.0, "stability": 0.5 } }' ``` `voice_id` must be the `vc_...` ID from the `/v1/voices` endpoint — not the raw provider voice ID. See [Voices](/guides/voices) for the full list of available voice IDs. | Field | Range | What it does | | ----------- | ------- | ------------------------------------------------------------------------- | | `voice_id` | — | The OneInbox voice ID (`vc_...`) from `/v1/voices` | | `speed` | 0.5–2.0 | Playback rate. `1.0` is normal speech speed | | `stability` | 0.0–1.0 | Voice consistency. Higher = more consistent tone, lower = more expressive | *** ## Key agent fields | Field | Default | What it controls | | -------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `first_message` | — | First thing the agent says when a call connects. Keep it under 2 sentences | | `language` | `en` | Transcription language. Set at the agent level — `{ "language": "ar" }` | | `silence_timeout_seconds` | `10` | Seconds of silence before the call ends | | `max_duration_seconds` | `600` | Hard cap on call length. Range: 30–7200 | | `interruption_sensitivity` | `0.5` | How easily the caller can interrupt (0.0 = hard, 1.0 = very easy) | | `responsiveness` | `0.5` | How quickly the agent responds after the caller stops speaking (0 = patient, 1 = snappy) | | `enable_recording` | `false` | Set `true` to get `recording_url` in the call record after the call ends | | `voicemail_detection` | `false` | Detect voicemail greetings on outbound calls | | `voicemail_message` | — | What the agent says if voicemail is detected | | `end_call_phrases` | `[]` | Phrases that trigger call end automatically — e.g. `["goodbye", "talk later"]` | | `job_description` | — | Prepended to the system prompt as a `# Role` block at call time. Use this to set the agent's role without editing the full system prompt on the LLM | | `speed` | `1.0` | Top-level speech rate multiplier (0.5–2.0). Overrides `tts.speed` when set | | `background_sound` | — | Ambient audio behind the agent's voice — e.g. `"office"`, `"cafe"` | | `emotions` | `false` | Enable emotion-aware voice expression (provider-dependent) | *** ## Dynamic variables Dynamic variables let you personalise an agent's `first_message`, `voicemail_message`, and `system_prompt` per call — without creating a separate agent per lead. Write placeholders with **single braces** (`{variable_name}`) in any of those fields, then pass the actual values when you start the call. ```bash theme={null} # 1. Agent with placeholders curl -X POST https://api-tokyo.oneinbox.ai/v1/agents \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Sales Bot", "first_message": "Hi {lead_name}, this is Aria calling about {product_name}.", "dynamic_variables": { "product_name": "Acme Outreach" } }' # 2. Call with per-call values curl -X POST https://api-tokyo.oneinbox.ai/v1/calls \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "agent_id": "", "to_number": "+919876543210", "from_number": "+15739693824", "variables": { "lead_name": "Priya" } }' ``` The agent opens with: **"Hi Priya, this is Aria calling about Acme Outreach."** **Two layers — how they combine:** | Layer | Where set | Priority | | -------------------------------- | ---------------------------------- | --------------------------------- | | `dynamic_variables` on the agent | Agent config — same for every call | Lower (default fallback) | | `variables` on the call | Call request — per-call | Higher (overrides agent defaults) | At call start, OneInbox builds the final variable map by merging both layers (call values win on collision), then substitutes every `{placeholder}` in the templates before the agent says a word. The LLM and TTS only ever see the resolved strings — never the raw placeholders. Use **single braces** — `{lead_name}`, not `{{lead_name}}`. Double braces are not interpolated and appear as literal text. *** ## Updating an agent Update any field on an agent at any time. Changes take effect on the next call — active calls in progress are not affected. ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/agents/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "first_message": "Hi! How can I help you today?", "silence_timeout_seconds": 15 }' ``` *** ## Manage agents ### List all agents Retrieve all agents in your account. Use this to find an `agent_id` or `llm_id` you need for other operations. ```bash theme={null} curl "https://api-tokyo.oneinbox.ai/v1/agents?limit=20" \ -H "Authorization: Bearer " ``` ### Get a specific agent Fetch a single agent's full config — including `llm_id`, language, voice settings, and all behaviour fields. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/agents/ \ -H "Authorization: Bearer " ``` The single-agent GET includes a read-only `effective_system_prompt` field — the exact system prompt the agent is given at call time: the LLM's `system_prompt` with `job_description` prepended as a `# Role` block. This is what the LLM actually receives, assembled the same way the worker does at runtime. ```json theme={null} { "id": "agt_abc123", "llm_id": "llm_xyz789", "job_description": "You are a friendly sales rep at Acme.", "effective_system_prompt": "# Role\nYou are a friendly sales rep at Acme.\n\nYou are a helpful voice assistant.", "..." } ``` `effective_system_prompt` is only populated on `GET /v1/agents/{id}`. It is `null` on the list endpoint to avoid an LLM lookup per row. Per-call variable interpolation and knowledge base chunks are resolved at runtime and are not reflected here. ### Delete an agent Permanently removes the agent. If the agent is assigned to a phone number, reassign the number to a different agent first, then delete. ```bash theme={null} # 1. Reassign the phone number first (if applicable) curl -X PATCH https://api-tokyo.oneinbox.ai/v1/phone-numbers/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "agent_id": "" }' # 2. Then delete the agent curl -X DELETE https://api-tokyo.oneinbox.ai/v1/agents/ \ -H "Authorization: Bearer " ``` ### List LLM models ```bash theme={null} curl "https://api-tokyo.oneinbox.ai/v1/models?limit=20" \ -H "Authorization: Bearer " ``` ### Get an LLM model Fetch the full config of a specific model — system prompt, tools, knowledge bases, and custom URL. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " ``` ### Delete an LLM model Permanently removes the model. Agents currently using this model will lose their LLM config — reassign them first with `{ "llm_id": "" }`. ```bash theme={null} curl -X DELETE https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " ``` *** ## Next steps Give your agent actions — SMS, email, data capture, transfer Make real outbound calls with a registered phone number How calls are classified and how to read results Browse available voices and configure TTS # Authentication Source: https://docs.oneinbox.ai/concepts/authentication How to authenticate API requests with your OneInbox API key. OneInbox has two kinds of keys. Which one you use depends on where your code runs — that distinction is the whole reason both exist. | Key | Starts with | Runs where | Can do | | ------------------- | ----------- | ---------------------- | ------------------------------------------------- | | **API key** | `oi_sk_` | Your server (backend) | Everything — create agents, make calls, read data | | **Publishable key** | `oi_pk_` | The browser (frontend) | Only start a call — nothing else | Use your **API key** for everything in this section. For the **publishable key**, see [Web SDK](/concepts/web-sdk) — it's created differently and used only to let website visitors start a call directly from your site. *** ## API key — full access, server only Your API key is the master credential for your OneInbox account. Anything this documentation shows you — creating agents, making calls, managing tools, reading call records, billing, everything — goes through this key. * **Format**: `oi_sk_...` * **Lives**: in your backend's environment variables / secrets manager — never in code you ship to a browser or app * **Scope**: unrestricted. Whoever holds it has the same access you do * **If it leaks**: revoke it immediately from the dashboard and issue a new one. A leaked API key is equivalent to a leaked account password — treat it that way Because it's this powerful, the API key is never meant to leave your server. That's the entire reason the publishable key exists — to give frontend code a way to trigger calls *without* ever having access to a credential this strong. *** ## Publishable key — limited access, safe for browsers A publishable key is designed to be safe for use in frontend code. It can be pasted directly into website code that anyone can view in their browser's dev tools. * **Format**: `oi_pk_...` * **Lives**: directly in your frontend code (e.g. with the [Web SDK](/concepts/web-sdk)) — this is the intended, safe place for it * **Scope**: can only do one thing — start a call. It cannot read your data, list your agents, see call history, or change any account settings * **Domain-locked**: when you create one in the dashboard, you register the origins (domains) it's allowed to be used from — e.g. `https://yoursite.com`. A request from any other origin is rejected with `403 ORIGIN_NOT_ALLOWED`, even with a valid key * **If it leaks**: low risk by design — it can only start calls on agents you've configured, and only from your registered domains. You can still revoke and rotate it from the dashboard if you want to be safe This is what makes the Web SDK possible: a website visitor's browser needs *some* credential to start a call, but it can never be trusted with your full API key. The publishable key solves that — full functionality for its one job, zero exposure for everything else. *** ## Why two keys instead of one A single backend you control can safely hold a powerful, unrestricted key — only your own server code ever touches it. A browser is different: anything you ship to it is visible to whoever opens dev tools, so any key embedded there is effectively public. Rather than force you to proxy every call request through your own server, OneInbox gives you a second key type that's *safe to be public* — scoped down to exactly the one capability a browser legitimately needs, and locked to the domains you control. | | API key | Publishable key | | ---------------- | -------------------------------------------- | --------------------------------------------------------------------- | | Trust model | Secret — protect like a password | Public — safe to expose | | Who/what uses it | Your server | Visitors' browsers | | Capabilities | Full account access | Start a call only | | Restricted by | Nothing (full scope) | Registered origins (domains) | | Where to create | Dashboard → **API Keys** | Dashboard → **Publishable Keys** | | If exposed | Revoke immediately — full account compromise | Low risk — already designed to be public, but you can still rotate it | *** ## Get your API key 1. [Sign up or log in](https://oneinbox-dashboard.vercel.app/signup) at the OneInbox dashboard 2. Open **API Keys** 3. Click **Create API key**, give it a name, and copy the key You can view and manage keys anytime from the dashboard — create new keys or revoke old ones as needed. Never put your API key in frontend code — anyone who finds it gets full access to your account. If you need to trigger calls from a browser, use a **publishable key** instead (see [Web SDK](/concepts/web-sdk)). *** ## How to send it Add this header to every request: ``` Authorization: Bearer ``` Example: ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/agents \ -H "Authorization: Bearer " ``` *** ## Check usage Retrieve usage summary for your account — credits consumed, call counts, and billing period. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/usage \ -H "Authorization: Bearer " ``` *** ## Quick reference | Action | Where | | ----------------------------------------- | -------------------------------------------------------------------------------- | | Create or revoke API keys | [Dashboard](https://oneinbox-dashboard.vercel.app/signup) → **API Keys** | | Create or revoke publishable keys | [Dashboard](https://oneinbox-dashboard.vercel.app/signup) → **Publishable Keys** | | Call agents, models, calls, etc. (server) | `Authorization: Bearer ` on every request | | Start a call from a website (browser) | Publishable key with the [Web SDK](/concepts/web-sdk) | Full walkthrough → **[Quickstart](/guides/quickstart)** # How it works Source: https://docs.oneinbox.ai/concepts/how-it-works What happens from the moment a call connects to the moment it ends — the full pipeline explained. ## The voice pipeline Every call runs the same real-time loop: the caller speaks, the audio is transcribed, the LLM generates a reply, and TTS speaks it back. This happens continuously for the duration of the call. ```mermaid theme={null} sequenceDiagram participant Caller participant STT as Speech-to-text (STT) participant LLM as Language model (LLM) participant TTS as Text-to-speech (TTS) participant Tool as Tool (optional) Caller->>STT: speaks STT->>LLM: transcript text LLM->>Tool: tool call (if triggered) Tool->>LLM: tool result LLM->>TTS: reply text (streamed) TTS->>Caller: spoken audio (streamed) ``` Each stage is configurable — you choose the provider and model. OneInbox handles streaming, connection management, and timing. *** ## Stage 1 — Speech-to-text (STT) When the caller speaks, audio streams in real time to the STT provider. OneInbox uses **end-of-speech detection** to know when the caller has finished a turn — based on a pause threshold, not a fixed timer. The resulting transcript is passed immediately to the LLM. **What you configure:** provider, model, language. **Platform providers (no credential needed):** Deepgram (`nova-3`, `flux-en`, `flux-multi`), Whisper, AssemblyAI, Azure. **Deepgram nova-3** is the default and recommended for most use cases — it offers the lowest transcription latency, which directly reduces overall response time. *** ## Stage 2 — Language model (LLM) The transcript arrives at the LLM along with the full conversation history, the system prompt, and any knowledge base context. The LLM generates a reply. **Streaming:** the LLM streams tokens as it generates them. OneInbox begins passing text to TTS as soon as the first sentence boundary is detected — it does not wait for the full reply. **Tool calls:** if the LLM decides to call a tool (transfer, SMS, booking, etc.), OneInbox executes the tool, returns the result to the LLM, and the LLM continues generating. The caller hears normal audio while this happens — the agent keeps speaking rather than going silent. **What you configure:** provider, model, system prompt, temperature, tools, knowledge bases. **Platform providers (no credential needed):** OpenAI, Shisa. Anthropic and Groq require a credential (BYOK). *** ## Stage 3 — Text-to-speech (TTS) As the LLM streams reply text, TTS converts it to audio in real time. Audio is streamed back to the caller as it is generated — the caller starts hearing the agent speak before the full reply is finished. **What you configure:** provider, voice, speed, stability. **Platform providers (no credential needed):** Cartesia, Deepgram, ElevenLabs, OpenAI, Minimax, Shisa. *** ## Interruption handling When a caller speaks while the agent is talking, OneInbox detects it and stops the agent's audio immediately — the caller's new speech goes straight into a new STT → LLM → TTS cycle. The `interruption_sensitivity` field (0.0–1.0) controls how easily the agent can be interrupted. *** ## Latency Response latency is the sum of three segments: | Segment | What it measures | | ---------------------------------- | --------------------------------------------------------------------- | | **STT latency** | Time from caller finishing speaking to transcript arriving at the LLM | | **LLM TTFT** (time to first token) | Time from transcript arriving to the LLM producing its first token | | **TTS TTFB** (time to first byte) | Time from first token arriving at TTS to first audio byte produced | Because all three stages stream in parallel, the caller typically starts hearing the agent's reply within 800–1500 ms of finishing their own sentence, depending on provider choices. *** ## Call types | Type | Transport | How it connects | | ----------------------- | ---------- | ------------------------------------------------------------------------------------------------- | | **Browser call** | WebRTC | Via the Web SDK or `POST /v1/calls/web`. No phone number needed — runs entirely over the internet | | **Outbound phone call** | PSTN / SIP | Agent dials `to_number` from `from_number` via `POST /v1/calls` | | **Inbound phone call** | PSTN / SIP | Caller dials your number — routed to the agent assigned to that number | The same agent config works for all three call types. *** ## What OneInbox manages for you * Real-time audio streaming between STT, LLM, and TTS * End-of-speech detection and turn management * Interruption detection and agent audio cutoff * Tool execution and result injection into the LLM context * Knowledge base retrieval and context injection * Silence timeout and end-call-phrase detection * Transcripts, call metadata, and AI summaries * Telephony routing (PSTN/SIP) for phone calls * WebRTC session tokens for browser calls *** ## Next steps * **[Quickstart](/guides/quickstart)** — make your first call in minutes * **[Agents](/concepts/agents)** — full agent configuration reference * **[LLMs](/guides/llms)** — configure the AI brain * **[Voices](/guides/voices)** — browse available voices and configure TTS # Integrations Source: https://docs.oneinbox.ai/concepts/integrations Optionally store third-party provider keys in OneInbox (BYOK). ## What is an integration? An **integration** is a third-party API key stored securely inside OneInbox. * OneInbox **encrypts** the key at rest * The raw key is **never** returned after creation * You reference integrations by `id` in other API calls *** ## When to use Integrations are **entirely optional**. OneInbox provides defaults for everything out of the box — LLM, STT, TTS, and phone numbers — so you can build and test without any integration at all. Add one only when you want to bring your own: * **LLM** — **openai**, **shisa**, and **custom** (via `custom_websocket_url`) are available out of the box, no key needed. **anthropic** and **groq** require you to bring your own API key and create an integration first. * **STT** — all providers (**deepgram**, **whisper**, **assembly\_ai**, **azure**) are available out of the box. Add an integration only if you want usage billed to your own provider account. * **TTS** — all providers (**cartesia**, **deepgram**, **elevenlabs**, **openai**, **shisa**, **minimax**) are available out of the box. Add an integration only if you want usage billed to your own provider account. * **Phone numbers** — use a number from your own Twilio or Telnyx account instead of the OneInbox default * **Email or calendar tools** — `send_email` and `schedule_calendar_event` need a `credential_id` pointing at your Resend/SendGrid or Cal.com account *** ## How to use ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "OpenAI Production", "provider": "openai", "api_key": "" }' ``` Email, telephony, and calendar providers also take a `metadata` object with provider-specific details: ```bash theme={null} # Email (Resend / SendGrid) — needs a verified "from" address curl -X POST https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Resend Email", "provider": "resend", "api_key": "", "metadata": { "from_email": "hello@yourdomain.com" } }' ``` ```bash theme={null} # Twilio — needs the phone number you bought with them + SIP trunk config curl -X POST https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "My Twilio Account", "provider": "twilio", "api_key": "", "metadata": { "account_sid": "", "phone_number": "+15739693824", "sip_trunk": "" } }' ``` ```bash theme={null} # Cal.com — API key only; event_type_id is set on the tool, not the integration curl -X POST https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Cal.com Bookings", "provider": "calcom", "api_key": "" }' ``` *** ## Resend setup To use the `send_email` tool with Resend, you need two things: a Resend API key and a verified sending domain. ### 1 — Get your Resend API key 1. Go to [resend.com](https://resend.com) and log in 2. Open **API Keys** in the left sidebar 3. Click **Create API Key** — give it a name like "OneInbox" 4. Copy the key (starts with `re_`) ### 2 — Verify your sending domain Resend blocks email from domains you haven't verified — sends fail with HTTP 403. 1. In Resend, go to **Domains** → **Add Domain** 2. Enter the domain you want to send from (e.g. `yourdomain.com`) 3. Resend shows you DNS records to add — typically three records: | Type | Purpose | | ------- | --------------------------------------------------------------------------- | | `TXT` | SPF — tells receiving servers that Resend is allowed to send on your behalf | | `CNAME` | DKIM — cryptographically signs outgoing messages to prove they're genuine | | `CNAME` | DMARC alignment (optional but recommended) | 4. Add these records in your DNS provider (GoDaddy, Cloudflare, Route 53, etc.) 5. Click **Verify** in Resend — propagation usually takes a few minutes You can only send from the **exact domain** (or a subdomain of it) that you verified. For example, verifying `yourdomain.com` lets you send from `hello@yourdomain.com` or `noreply@yourdomain.com`. It does **not** cover `mail.yourdomain.com` unless you verify that subdomain separately. ### 3 — Create the integration Pass your verified sending address as `metadata.from_email`. This is the address that appears in the "From" field of every email the agent sends: ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Resend Email", "provider": "resend", "api_key": "", "metadata": { "from_email": "hello@yourdomain.com" } }' ``` Save the returned `id` — use it as `credential_id` when creating a `send_email` tool. *** ## Cal.com setup To use the `schedule_calendar_event` tool, you need a Cal.com API key and the ID of the event type you want the agent to book against. ### What is an event type? An event type in Cal.com is a bookable meeting — it defines the duration, availability, booking form, and confirmation settings. Examples: | Event type | Duration | Use case | | -------------- | -------- | --------------------------------------- | | Product Demo | 30 min | Agent books a demo for interested leads | | Discovery Call | 20 min | First-touch qualification call | | Onboarding | 60 min | New customer setup session | Each event type has a numeric ID that you pass to OneInbox. ### 1 — Get your Cal.com API key 1. Log in to [cal.com](https://cal.com) 2. Go to **Settings** → **Developer** → **API Keys** 3. Click **Add** — give it a name and copy the key ### 2 — Find your event type ID **From the URL:** In your Cal.com dashboard, open **Event Types** and click Edit on the event you want. The URL contains the ID: ``` https://app.cal.com/event-types/123456 ^^^^^^ This is your event_type_id ``` **From the API:** ```bash theme={null} curl "https://api.cal.com/v2/event-types" \ -H "Authorization: Bearer " ``` The response lists all your event types with their `id` fields. Pick the one you want the agent to book. ### 3 — Configure availability The agent can only book slots that are available in Cal.com. Before going live: * Set your **working hours** on the event type (e.g. Mon–Fri, 9am–5pm) * Choose a **buffer time** between meetings if needed * Make sure the event type is set to **active** (not draft) If a caller asks for a time outside your availability, the booking fails with HTTP 400 and the agent will tell the caller that slot isn't available. The agent must collect the caller's **name and email** during the conversation — both are required by Cal.com to complete a booking. Make sure your agent's system prompt asks for these before attempting to schedule. ### 4 — Create the integration ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Cal.com Bookings", "provider": "calcom", "api_key": "" }' ``` Save the returned `id` — use it as `credential_id` when creating a `schedule_calendar_event` tool. The `event_type_id` is set on the tool itself, not the integration. If you run multiple event types (demo, discovery, onboarding), create a **separate integration for each** — each one points to a different `event_type_id`. Then create a separate `schedule_calendar_event` tool per integration, each with a clear description so the agent fires the right one based on what the caller asks for. *** ## How integrations connect ``` Integration (optional BYOK) │ ▼ LLM model with matching "provider" │ ▼ Agent (llm_id) → Calls ``` Telephony integrations power [Phone numbers](/guides/phone-calls) via `credential_id` on number search/register. *** ## Manage integrations ### List all integrations ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " ``` ### Get an integration ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/integrations/ \ -H "Authorization: Bearer " ``` The raw `api_key` is never returned — only the `masked_key` is shown. ### Update an integration Update the name, API key, metadata, or provider of an existing integration. ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/integrations/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "OpenAI Updated", "api_key": "" }' ``` ### Delete an integration Permanently removes the stored credential. Any models or tools using this `credential_id` will lose access to the provider until you attach a new integration. ```bash theme={null} curl -X DELETE https://api-tokyo.oneinbox.ai/v1/integrations/ \ -H "Authorization: Bearer " ``` *** ## Next steps * **[Phone numbers](/guides/phone-calls)** — telephony integration * **[Voices](/guides/voices)** — custom voice import * **[Create integration](/api-reference/integrations/create-integration)** — API reference # Web SDK Source: https://docs.oneinbox.ai/concepts/web-sdk Let visitors talk to your AI agent directly from your website — no phone number, no app download. ## What is the Web SDK? The Web SDK is a small piece of code you drop into your website. When a visitor clicks a "Talk to us" button, it opens a live voice conversation with your OneInbox agent — right in the browser, using their microphone. Think of it like a live chat widget, but for voice. **What it handles for you:** * Asking the browser for microphone permission * Streaming audio in real time (both directions) * Showing live transcripts as the conversation happens * Mute, unmute, and hang up **What your team sets up:** * An agent on OneInbox (the AI that answers) * A button or widget on your site that starts the call *** ## Quick steps — the simplest way to add it to your site This is the fastest path: a publishable key + the Web SDK, no backend required. Build the agent that will answer calls — see [Quickstart](/guides/quickstart) if you haven't made one yet. Save its `id` (`agt_…`). In the [OneInbox dashboard](https://oneinbox-dashboard.vercel.app), go to **Settings → Publishable Keys** → **Create key**. Enter the allowed origins for this key — one per line: | What to enter | When to use | | ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | | `https://yoursite.com` | Restrict the key to a specific domain — requests from any other origin are rejected with `403 ORIGIN_NOT_ALLOWED` | | `https://yoursite.com` + `https://staging.yoursite.com` | Multiple specific domains (e.g. production + staging) | | `*` or leave blank | Allow all origins — useful during development or for internal tools where locking to a domain isn't needed | Copy the key — it starts with `oi_pk_live_…`. Using `*` means any website can use your publishable key to start calls on your agent. This is fine for local testing but restrict to your actual domain before going to production. ```bash theme={null} npm install @oneinbox/web-sdk ``` Initialize the SDK with your publishable key, then point `start()` at your agent's `id`: ```ts theme={null} import { OneInbox } from "@oneinbox/web-sdk"; const oi = new OneInbox("oi_pk_live_…"); await oi.start("agt_…"); ``` Wire that `start()` call to any button — e.g. "Talk to us." When a visitor clicks it, the call begins right there in the browser, using their mic. That's it — no server, no separate "create a call" step. The full event/control API (mute, transcripts, hang up, etc.) is below under [Vanilla example](#vanilla-example) and [React example](#react-example). *** ## How it fits into your product When a visitor clicks "Call": 1. Your website asks your server: *"start a call for this visitor"* 2. Your server creates the call via the OneInbox API and gets back a short-lived access token 3. The Web SDK uses that token to connect the visitor's browser to the agent 4. The conversation starts — live, two-way voice Your server holds your secret API key. The browser only ever receives a one-time token that expires when the call ends — so nothing sensitive is exposed to visitors. *** ## Two packages | Package | Use it when | | ------------------------- | ---------------------------------------- | | `@oneinbox/web-sdk` | Plain JavaScript or any framework | | `@oneinbox/web-sdk-react` | React apps — gives you a ready-made hook | Both do the same thing. The React package just wraps the core one with React-friendly patterns. *** ## Install ```bash theme={null} # Vanilla JavaScript / any framework npm install @oneinbox/web-sdk # React npm install @oneinbox/web-sdk-react @oneinbox/web-sdk react ``` Each package is self-contained — the SDK bundles everything it needs to handle the audio connection, so there are no other companion packages to install. *** ## Vanilla example ```ts theme={null} import { OneInbox } from "@oneinbox/web-sdk"; const oi = new OneInbox("oi_pk_live_…"); // React to what happens during the call oi.on("call-start", () => showCallUI()); oi.on("call-end", () => showIdleUI()); oi.on("transcript", (t) => appendTranscript(t.role, t.text)); // live captions oi.on("error", (e) => showError(e.message)); // Start the call — pass the visitor's name so the agent greets them await oi.start("agt_…", { variables: { customer_name: "Sama" } }); // During the call oi.setMuted(true); // mute the visitor's mic oi.setMuted(false); // unmute await oi.stop(); // hang up ``` ### What you can listen to | Event | What it means | | ----------------------------- | --------------------------------------------------------------------- | | `call-start` | The call connected — show your active call UI | | `call-end` | The call ended — return to idle state | | `transcript` | A new line of speech was heard — update captions or a chat log | | `speech-start` / `speech-end` | Someone started or stopped speaking — animate a speaking indicator | | `volume-level` | How loud the visitor's mic is right now (0–1) — drive a mic level bar | | `error` | Something went wrong — show an error message | ### Controls | Method | What it does | | ---------------------------------- | ---------------------------------------------------------- | | `oi.start(agentId, { variables })` | Start the call | | `oi.stop()` | End the call | | `oi.setMuted(true / false)` | Mute or unmute the visitor's mic | | `oi.isMuted()` | Returns `true` if the mic is currently muted | | `oi.status` | Current state: `idle`, `connecting`, `active`, or `ending` | *** ## React example ```tsx theme={null} import { OneInboxProvider, useOneInbox } from "@oneinbox/web-sdk-react"; // Wrap your app once at the top level function App() { return ( ); } // Use the hook anywhere inside the provider function CallWidget({ agentId }) { const { start, stop, status, transcripts, isAgentSpeaking, isMuted, setMuted } = useOneInbox(); const active = status === "active"; return (
{active && ( )}

{isAgentSpeaking ? "Agent is speaking…" : status}

{transcripts.map((t, i) => (

{t.role}: {t.text}

))}
); } ``` `useOneInbox()` gives you everything you need to build a call UI: | Value | What it is | | ----------------------------- | ------------------------------------------------------------- | | `status` | Current call state (`idle`, `connecting`, `active`, `ending`) | | `transcripts` | Every line of the conversation so far | | `isAgentSpeaking` | `true` while the agent is talking | | `isMuted` | `true` if the visitor's mic is muted | | `volume` | Mic level in real time (0–1) | | `error` | The last error, if any | | `start` / `stop` / `setMuted` | Controls | # Calls Source: https://docs.oneinbox.ai/guides/call-outcomes Make outbound calls, receive inbound calls, read results, and manage call records. OneInbox automatically classifies outcomes after every call. ## Make an outbound call Pass the registered `from_number` and the destination `to_number`. Use `variables` to inject per-call context (e.g., the customer's name or order ID) into the agent's first message and system prompt. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/calls \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "agent_id": "", "to_number": "+919876543210", "from_number": "+15739693824", "variables": { "customer_name": "Sama", "order_id": "ORD-001" }, "webhook_url": "https://your-server.com/per-call-webhook", "out_sms": false }' ``` | Optional field | Default | What it does | | -------------- | ------- | -------------------------------------------------------------------------------------- | | `variables` | `{}` | Key-value pairs injected into the agent's system prompt and first message at call time | | `webhook_url` | — | Per-call webhook URL — overrides any global webhook for this call only | | `out_sms` | `false` | Send an SMS to `to_number` after the call ends | | `schedule_at` | — | ISO 8601 timestamp to schedule the call for a future time | ```json theme={null} { "id": "call_abc123", "status": "initiated", "to_number": "+919876543210", "from_number": "+15739693824" } ``` The call goes through these states: | Status | Meaning | | ------------- | ---------------------------------------------- | | `initiated` | Call created, connecting through your provider | | `in_progress` | Call connected, agent is talking | | `completed` | Call ended normally | | `failed` | Call failed to connect | *** ## Receive inbound calls When someone dials your registered number, OneInbox routes the call to your agent automatically — no extra API call needed. The call record appears in your account just like an outbound call, with the same `status`, `outcome`, `transcript`, and `recording_url` fields. To enable inbound on a number, set `inbound_routing` when you register or purchase it: ```json theme={null} "inbound_routing": { "agent_id": "", "fallback": { "agent_id": "" }, "voicemail_message": "Sorry we missed you, please leave a message." } ``` To add or update routing on an existing number: ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/phone-numbers/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "inbound_routing": { "agent_id": "", "voicemail_message": "Updated voicemail message." } }' ``` → [Phone numbers](/guides/phone-calls) — full setup for search, purchase, and bring-your-own-number paths *** ## Stop a call Send a stop request to end the session. If the agent already ended the call via the `end_call` tool, this is a no-op. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/calls//stop \ -H "Authorization: Bearer " ``` *** ## Read the results After the call ends, fetch the full record to get the transcript, outcome, and summary. Wait 2–3 seconds after stopping — the transcript and analysis are written asynchronously. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/calls/ \ -H "Authorization: Bearer " ``` ```json theme={null} { "id": "call_abc123", "status": "completed", "duration_seconds": 87, "messages": [ { "role": "agent", "content": "Hi Sama! This is Aria from Acme." }, { "role": "user", "content": "Oh hi, yes I've been expecting your call." } ], "outcome": "Appointment Booked", "ai_summary": "Caller agreed to a product demo on Thursday at 3pm.", "analysis": { "summary": "Caller agreed to a product demo on Thursday at 3pm." }, "recording_url": "https://storage.oneinbox.ai/recordings/call_abc123.mp3", "latency": { "llm_ttft": { "avg_ms": 857, "p50_ms": 820, "min_ms": 710, "max_ms": 1050, "samples": 4 }, "tts_ttfb": { "avg_ms": 312, "p50_ms": 290, "min_ms": 240, "max_ms": 410, "samples": 4 }, "eou_delay": { "avg_ms": 180, "p50_ms": 175, "min_ms": 140, "max_ms": 230, "samples": 4 } }, "credits_used": 1.45, "cost_cents": 8.7 } ``` `messages` and `analysis` are only populated after the call ends. Stop first, wait 2–3 seconds, then fetch. | Field | When it's available | What it means | | ------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------- | | `latency.llm_ttft` | After call ends | Time-to-first-token from the LLM — per turn, with avg/p50/min/max | | `latency.tts_ttfb` | After call ends | Time-to-first-byte from TTS — per turn | | `latency.eou_delay` | After call ends | End-of-utterance detection lag — how long before the agent started responding | | `credits_used` | After call ends | OneInbox billing units — `duration_seconds ÷ 60` (1 credit per active minute) | | `cost_cents` | Finalized async by carrier | Raw carrier cost (Twilio/Telnyx). May be `null` immediately after hangup — backfilled once the carrier finalizes | | `recording_url` | After call ends (if enabled) | Pre-signed S3 URL, valid 4 hours. Each GET returns a fresh URL so it never expires for active integrations | *** ## List calls Returns your most recent calls. Default order is newest first. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/calls \ -H "Authorization: Bearer " ``` *** ## List calls — cursor pagination For large result sets, use cursor-based pagination. Pass the `cursor` token from the previous response to get the next page. ```bash theme={null} # First page curl "https://api-tokyo.oneinbox.ai/v1/calls/cursor?limit=20" \ -H "Authorization: Bearer " # Next page — use the cursor from the previous response curl "https://api-tokyo.oneinbox.ai/v1/calls/cursor?cursor=&limit=20" \ -H "Authorization: Bearer " ``` The response includes a `cursor` token. When `cursor` is `null`, you have reached the last page. *** ## Delete a call Permanently deletes a call record. ```bash theme={null} curl -X DELETE https://api-tokyo.oneinbox.ai/v1/calls/ \ -H "Authorization: Bearer " ``` *** ## Manually set a call outcome After a call ends you can override the AI-assigned outcome — useful when your CRM or a human reviewer has classified the call differently. ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/calls/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "outcome": "interested" }' ``` The updated `outcome` value is immediately reflected in `GET /v1/calls/` and in webhook payloads for that call. *** ## What is an outcome? An outcome is a label assigned to a completed call that summarises its result. It's the top-level `outcome` field on the call record, set automatically after the call ends. `analysis` is a separate object holding the AI-generated `summary` — it does not contain `outcome`. You can also set or override `outcome` manually, and you can create your own custom outcome labels for your workspace. *** ## Built-in outcome labels OneInbox ships with a set of platform-level outcomes available to every account. `GET /v1/workspace/call-outcomes` returns their snake\_case identifiers; the `outcome` field on a call record stores the human-readable Title Case form: | Identifier (`call-outcomes` catalog) | Stored on `call.outcome` | What it means | | ------------------------------------ | ------------------------ | --------------------------------------------------- | | `appointment_booked` | `Appointment Booked` | A meeting or demo was scheduled | | `callback_requested` | `Callback Requested` | Caller asked to be called back later | | `completed` | `Completed` | Call finished with no other outcome matched | | `do_not_call` | `Do Not Call` | Caller asked not to be contacted again | | `failed` | `Failed` | Call failed to connect properly | | `interested` | `Interested` | Caller engaged but did not commit | | `no_answer` | `No Answer` | Call rang out with no pickup | | `not_connected` | `Not Connected` | No conversation happened (busy, immediate hang-up) | | `not_interested` | `Not Interested` | Caller explicitly declined | | `other` | `Other` | Doesn't match any other label | | `spam` | `Spam` | Identified as a spam/robocall situation | | `voicemail` | `Voicemail` | Voicemail greeting detected | | `wrong_number` | `Wrong Number` | Reached the wrong person/number | | — | `null` | No outcome classified — call too short or ambiguous | *** ## How auto-classification works After every call ends, OneInbox reads the transcript and assigns an outcome automatically. No configuration needed. A few things to know: * **Classification happens post-call.** `outcome` is `null` during an active call. Fetch the record after the call ends. * **`ai_summary` explains the reasoning.** If an outcome looks wrong, read the summary to understand what the model saw in the conversation. * **Custom outcomes are also used.** If you have created custom outcome labels (see below), the agent uses those in addition to the built-in set when classifying calls. *** ## Custom outcome labels You can create custom outcome labels specific to your workspace. The agent uses these alongside the built-in labels when classifying calls — so if you add "Hot Lead" as a custom outcome, the AI will start assigning it when a call matches that description. ### List call outcomes Returns both the built-in platform labels (always available) and any custom labels you have created for your workspace. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/workspace/call-outcomes \ -H "Authorization: Bearer " ``` ```json theme={null} { "builtin": [ "appointment_booked", "callback_requested", "completed", "do_not_call", "failed", "interested", "no_answer", "not_connected", "not_interested", "other", "spam", "voicemail", "wrong_number" ], "items": [ { "id": "co_abc123", "label": "Hot Lead", "description": "Expressed strong interest and asked specific product questions", "is_active": true } ], "total": 1 } ``` ### Create a custom outcome Add a new outcome label to your workspace. Any casing is accepted — e.g. `"Hot Lead"` or `"demo_scheduled"`. Once created, the agent starts using it automatically when classifying future calls. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/workspace/call-outcomes \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "label": "Hot Lead", "description": "Qualified lead with confirmed budget and decision timeline" }' ``` ```json theme={null} { "id": "co_abc123", "label": "Hot Lead", "description": "Qualified lead with confirmed budget and decision timeline", "is_active": true } ``` | Field | What it does | | ------------- | -------------------------------------------------------------------------------------------------- | | `label` | The outcome name. Any casing is accepted — stored and displayed as-is | | `description` | Optional. Explains to the AI when this outcome applies. More detail = more accurate classification | ### Update a custom outcome Rename a label or deactivate it. Deactivating (`is_active: false`) hides the outcome from future auto-classification but preserves it on historical call records — no data is lost. ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/workspace/call-outcomes/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "label": "Qualified Lead", "is_active": true }' ``` | Field | What it does | | ----------- | ----------------------------------------------------------------------------------------- | | `label` | New label name — updates how it appears on call records going forward | | `is_active` | `false` = hides this outcome from new classification while keeping historical data intact | *** ## Get notified automatically with webhooks Instead of polling, set up a webhook to receive the full call record as soon as a call ends: ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/webhooks \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Call completed", "url": "https://your-server.com/webhooks/oneinbox", "events": ["call.ended"] }' ``` → [Webhooks guide](/guides/webhooks) *** ## API reference [Create outbound call](/api-reference/calls/create-outbound-call) · [Stop call](/api-reference/calls/stop-call) · [Get call](/api-reference/calls/get-call) · [Update call](/api-reference/calls/update-call) · [List calls](/api-reference/calls/list-calls) · [Delete call](/api-reference/calls/delete-call) · [List call outcomes](/api-reference/workspace/list-call-outcomes) · [Create call outcome](/api-reference/workspace/create-call-outcome) · [Update call outcome](/api-reference/workspace/update-call-outcome) # Knowledge Bases Source: https://docs.oneinbox.ai/guides/knowledge-bases Upload your content — docs, FAQs, policies — so your agent can answer questions from it during calls. ## How it works You don't need to create a knowledge base manually. Adding content (a URL, file, or text) automatically creates one for you and returns its ID. Uploaded content is indexed and retrieved automatically during calls — no configuration needed. Supported file types: PDF, Excel, and Word documents. Maximum file size: 20 MB. *** ## Quick start — add content in one call You can skip creating a knowledge base ID manually. `POST /v1/knowledge-bases/sources` (without a `kb_id` in the path) auto-creates a new knowledge base named after your source and starts ingestion immediately. The response gives you the `knowledge_base_id` — save it for attaching to your agent. ### Add a URL Provide any public URL — a docs page, FAQ, blog post, or product page. OneInbox fetches the page and indexes its content automatically. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/knowledge-bases/sources \ -H "Authorization: Bearer " \ -F "type=url" \ -F "source=https://docs.yourproduct.com/faq" ``` ### Upload a file Upload a document directly. Supported formats: PDF, Excel, and Word documents. Use the `file` field only — do not include a `type` field when uploading a file. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/knowledge-bases/sources \ -H "Authorization: Bearer " \ -F "file=@/path/to/your-document.pdf" ``` ### Add inline text Paste content directly as plain text — useful for policies, scripts, FAQs, or any text you already have on hand. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/knowledge-bases/sources \ -H "Authorization: Bearer " \ -F "type=text" \ -F "source=Our refund policy is 30 days. Customers must provide proof of purchase to receive a refund." ``` All three endpoints return the same response structure: ```json theme={null} { "source": { "source_id": "kbs_xyz", "kb_id": "kb_abc123", "status": "processing" }, "job": { "job_id": "kbj_xyz", "kb_id": "kb_abc123", "status": "queued" }, "message": "Source accepted. Ingestion is running in the background." } ``` * **`source.kb_id`** — the ID of the auto-created knowledge base. Save this — you'll use it in Step 3 to attach the KB to your agent. * **`source.source_id`** — the individual content source that was added. * **`job.job_id`** — the processing job. Poll this to track indexing progress. The KB is named after the URL domain or file name. *** ## Step 2 — Check processing status Content is indexed asynchronously. Wait for the job to complete before attaching the KB to your agent — the agent can only use content that has finished processing. ```bash theme={null} # List all jobs for this KB curl https://api-tokyo.oneinbox.ai/v1/knowledge-bases//jobs \ -H "Authorization: Bearer " # Get a specific job curl https://api-tokyo.oneinbox.ai/v1/knowledge-bases//jobs/ \ -H "Authorization: Bearer " ``` Jobs follow this sequence: `queued` → `running` → `completed` or `failed` Wait for `"status": "completed"` before moving to Step 3. *** ## Step 3 — Attach to your LLM model This is the step that makes the knowledge base available to your agent. Attach it to the LLM model (not the agent directly). `llm_id` is returned when you create an agent — if you don't have it, fetch it with `GET /v1/agents/`. ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "knowledge_base_ids": [""] }' ``` Every agent using this LLM model now has access to the knowledge base. To attach multiple knowledge bases at once: ```bash theme={null} { "knowledge_base_ids": ["kb_abc123", "kb_def456"] } ``` ### Detach a knowledge base from a model To remove a KB from an LLM model without replacing the entire list, use `remove_knowledge_base_ids`: ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "remove_knowledge_base_ids": [""] }' ``` You can attach and detach KBs in the same request — `knowledge_base_ids` adds, `remove_knowledge_base_ids` detaches. *** ## Manage knowledge bases ### List all knowledge bases Retrieve all knowledge bases in your account. Useful for finding `kb_id` values or auditing what content your agents have access to. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/knowledge-bases \ -H "Authorization: Bearer " ``` ### List sources in a knowledge base See all the individual content sources (URLs, files, inline text) that have been added to a specific KB. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/knowledge-bases//sources \ -H "Authorization: Bearer " ``` ### Delete a source Remove a single source from the KB along with its vector chunks and stored file. Get the `source_id` from the list sources endpoint above. ```bash theme={null} curl -X DELETE "https://api-tokyo.oneinbox.ai/v1/knowledge-bases//sources/" \ -H "Authorization: Bearer " ``` ### Update a knowledge base Rename a KB, change its chunk size, or toggle multilingual mode. Chunk size changes take effect on the next source processed — existing content is not re-indexed automatically. ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/knowledge-bases/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Product Docs v2", "chunk_size": 1024, "multilingual": true }' ``` | Field | What it does | | -------------- | ----------------------------------------------------------------------------------------- | | `name` | Rename the KB | | `chunk_size` | Token size per chunk — smaller = more precise retrieval, larger = more context per result | | `multilingual` | `true` enables cross-language retrieval (content in one language, query in another) | ### Delete a knowledge base Permanently removes the KB and all its indexed content. If the KB is attached to an LLM model, it will no longer be available to those agents after deletion. ```bash theme={null} curl -X DELETE https://api-tokyo.oneinbox.ai/v1/knowledge-bases/ \ -H "Authorization: Bearer " ``` *** ## API reference [Add source (auto-create KB)](/api-reference/knowledge-bases/add-knowledge-base-source-auto-create) · [Add source](/api-reference/knowledge-bases/add-knowledge-base-source) · [List jobs](/api-reference/knowledge-bases/list-knowledge-base-jobs) # LLMs Source: https://docs.oneinbox.ai/guides/llms Configure the AI model that powers your agent's reasoning — set a system prompt, choose a provider, tune parameters, and attach tools. ## How LLMs work Every agent has an **LLM model** (`llm_id`) that controls what the agent says and does. The agent and the LLM model are separate resources so you can share one brain across multiple agents — update the system prompt once and every agent using that model picks up the change immediately. ``` Agent (voice, first message, call behaviour) └── LLM model (system prompt, provider, model, tools, knowledge bases) ``` When you create an agent, OneInbox automatically creates an LLM model with sensible defaults and returns its `id` as `llm_id`. *** ## Providers OneInbox supports several LLM providers. Platform providers work out of the box — no credentials needed. | Provider | Models | Credential required | | ---------------------- | --------------------------------------------- | -------------------------------------------------- | | **OpenAI** | `gpt-4o`, `gpt-4o-mini`, `gpt-5` | No — platform-provided | | **Shisa** | `shisa-ai/shisa-v2.1-llama3.3-70b` | No — platform-provided | | **Anthropic** | `claude-sonnet-4-5`, `claude-haiku-4-5` | Yes — [add an integration](/concepts/integrations) | | **Groq** | `llama-3.3-70b-versatile`, `gemma2-9b-it` | Yes — [add an integration](/concepts/integrations) | | **OpenRouter** | Curated subset — see model list in playground | No — platform-provided | | **Custom (WebSocket)** | Your own model server | Yes — WebSocket URL | *** ## Set a system prompt The system prompt defines the agent's persona, goals, and rules. Update it at any time without rebuilding the agent: ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "system_prompt": "You are Aria, a friendly sales rep for Acme Corp. Keep replies under two sentences. When the caller says goodbye, call end_call.", "temperature": 0.7 }' ``` | Field | Default | What it does | | --------------- | ----------------- | --------------------------------------------------------- | | `system_prompt` | General assistant | The agent's persona, goals, and rules | | `temperature` | `0.7` | Creativity. Lower = more consistent, higher = more varied | *** ## Switch provider or model To use a different provider or model, pass `provider` and `model` together: ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "provider": "openai", "model": "gpt-4o-mini" }' ``` For Anthropic or Groq, pass `credential_id` as well: ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "provider": "anthropic", "model": "claude-haiku-4-5", "credential_id": "" }' ``` See [Integrations](/concepts/integrations) for how to add a credential for Anthropic or Groq. *** ## OpenRouter — curated model list OpenRouter is platform-provided — no credential or integration needed. OneInbox exposes a curated subset of OpenRouter models, including small language models (SLMs) for low-latency use cases and select frontier models. Set `provider` to `openrouter` and pick a model ID from the supported list: ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "provider": "openrouter", "model": "mistralai/ministral-3b-2512" }' ``` Popular supported models include: | Model ID | Notes | | ------------------------------ | ---------------------------------------------- | | `mistralai/ministral-3b-2512` | Fastest SLM — ideal for high-concurrency calls | | `mistralai/ministral-8b-2512` | Balanced SLM | | `mistralai/ministral-14b-2512` | Higher quality SLM | | `mistralai/mistral-small-2603` | Mistral small | | `openai/gpt-4o-mini` | Cost-efficient OpenAI model | The full list of accepted model IDs is available in the model dropdown on the [API reference page](https://api-tokyo.oneinbox.ai). Use the exact model ID — for example `mistralai/ministral-3b-2512`, not `mistralai/ministral-3b`. A wrong ID causes the call to fail silently. *** ## Custom LLM — bring your own model server If you run your own model (self-hosted, fine-tuned, or on private infrastructure), point OneInbox at it using a `custom` provider and a WebSocket or HTTP URL. Your server must expose an **OpenAI-compatible streaming chat completions interface**. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/models \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "My self-hosted LLM", "provider": "custom", "custom_websocket_url": "wss://your-llm-server.example.com/v1/chat/completions", "system_prompt": "You are a helpful voice assistant.", "temperature": 0.7 }' ``` | Field | What it does | | ---------------------- | --------------------------------------------------------------------- | | `custom_websocket_url` | Your server URL — accepts `wss://`, `ws://`, `https://`, or `http://` | | `provider` | Must be `"custom"` | Your endpoint receives the same request shape as OpenAI's `/v1/chat/completions` and must return a streaming response in the same format. Tools, system prompts, and temperature are passed through unchanged. *** ## Attach tools Tools give the agent the ability to take actions during a call. They are attached to the LLM model — not to the agent directly: ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "tool_ids": ["", ""] }' ``` This replaces the full `tool_ids` list. Include all tool IDs you want active — any not listed are detached. See [Tools](/guides/tools) for how to create tools. *** ## Attach a knowledge base Knowledge bases let the agent answer questions from your documents or URLs. They are attached to the agent — not to the LLM model directly: ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/agents/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "kb_ids": ["", ""] }' ``` This replaces the full `kb_ids` list. Include all knowledge base IDs you want active — any not listed are detached. See [Knowledge bases](/guides/knowledge-bases) for how to create and manage them. *** ## Get an LLM model ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " ``` ```json theme={null} { "id": "llm_xyz789", "provider": "openai", "model": "gpt-4o-mini", "system_prompt": "You are Aria...", "temperature": 0.7, "tool_ids": ["tool_abc123"] } ``` *** ## API reference [List models](/api-reference/llm-models/list-llm-models) · [Get model](/api-reference/llm-models/get-llm-model) · [Update model](/api-reference/llm-models/update-llm-model) # Phone Numbers Source: https://docs.oneinbox.ai/guides/phone-calls Search for, purchase, and register phone numbers with your telephony provider. To make calls, see [Calls](/guides/call-outcomes). ## Overview Phone calls go through a telephony provider. You have **three ways** to get a number: | Path | When to use it | Integration required? | | ------------------------------------------------ | ---------------------------------------------------------------------- | --------------------- | | **A — Search & pick a number** | You want to choose a specific number from available inventory | No | | **B — Auto-assign a number** | Fastest setup — just pass your agent ID and OneInbox wires a number | No | | **C — Bring your own number (Twilio or Telnyx)** | You already own a number in Twilio or Telnyx and want to keep using it | Yes | Pick one path below to register your number, then head to [Calls](/guides/call-outcomes) to make your first call. *** ## Path A — Search and pick a number Search available numbers, then purchase the one you want. OneInbox buys and wires it to your agent in one step. **1. Search available numbers** ```bash theme={null} curl "https://api-tokyo.oneinbox.ai/v1/phone-numbers/search?country=US&area_code=415&limit=10" \ -H "Authorization: Bearer " ``` **2. Purchase a specific number** Copy a `phone_number` from the search results and pass it to the purchase endpoint: ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/phone-numbers/purchase \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "phone_number": "+14155551234", "friendly_name": "Sales Line", "agent_id": "", "inbound_routing": { "agent_id": "", "fallback": { "agent_id": "" }, "voicemail_message": "Sorry we missed you, please leave a message." } }' ``` Include `inbound_routing` if you want this number to receive inbound calls. Omit it if you only need to make outbound calls from this number. The number is now assigned to your agent. Head to [Calls](/guides/call-outcomes) to make your first call. *** ## Path B — Auto-assign a number (fastest) Don't want to search? Omit `phone_number` entirely. OneInbox auto-picks an available number and wires it to your agent in one call: ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/phone-numbers/purchase \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "country": "US", "area_code": "415", "friendly_name": "Sales Line", "agent_id": "", "inbound_routing": { "agent_id": "", "fallback": { "agent_id": "" }, "voicemail_message": "Sorry we missed you, please leave a message." } }' ``` Include `inbound_routing` if you want this number to receive inbound calls. Omit it if you only need outbound. The response includes the assigned `phone_number`. Head to [Calls](/guides/call-outcomes) to make your first call. *** ## Path C — Bring your own number (Twilio or Telnyx) Use a number you already own in Twilio or Telnyx. Both work the same way: set up a SIP trunk, create the integration in OneInbox, then register the number. **1. Buy the number in Twilio** Purchase a phone number from [Twilio Console](https://console.twilio.com) → Phone Numbers → Manage → Buy a number. **2. Set up an Elastic SIP Trunk** OneInbox connects to Twilio via Elastic SIP Trunking. **Step 1 — Create a trunk** In [Twilio Console](https://console.twilio.com), go to **Elastic SIP Trunking** in the left sidebar → click **Create new SIP Trunk** → give it a name (e.g. "OneInbox Trunk") → click **Create**. *** **Step 2 — Configure Termination (outbound calls)** The Termination SIP URI is how OneInbox sends outbound calls through your trunk. 1. Open your trunk → go to the **Termination** tab 2. Twilio auto-generates a **Termination SIP URI** — it looks like `yourtrunk.pstn.twilio.com` 3. Copy this — it's the `sip_trunk` value you'll pass to OneInbox *** **Step 3 — Configure Origination (inbound calls)** The Origination URI tells Twilio where to send inbound calls — in this case, to OneInbox. 1. Go to the **Origination** tab on your trunk 2. Click **Add new Origination URI** 3. Enter `sip:voice.oneinbox.ai:5060` 4. Set **Priority** to `10` and **Weight** to `10` → click **Add** *** **Step 4 — Attach your phone number** 1. Go to the **Numbers** tab on your trunk 2. Click **Add a number** → select the number you purchased in Step 1 3. Click **Add Selected** The number is now routed through this trunk. *** **Step 5 — Enable Geographic Permissions (for international calls)** If you need to call numbers outside your country (e.g. UAE, India), you must enable those regions: 1. In Twilio Console, go to **Voice** → **Settings** → **Geo Permissions** 2. Find the country or region you want to call → toggle it on 3. Click **Save** Without this, outbound calls to international numbers will fail with a `403 Forbidden` error. *** After completing these steps, copy the **Termination SIP URI** (e.g. `yourtrunk.pstn.twilio.com`) — you'll pass it as `sip_trunk` below. **3. Store your Twilio credentials in OneInbox** Your Account SID and Auth Token are in Twilio Console → Dashboard → Account Info. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "My Twilio Account", "provider": "twilio", "api_key": "", "metadata": { "account_sid": "", "phone_number": "+15739693824", "sip_trunk": "" } }' ``` ```json theme={null} { "id": "crd_abc123", "provider": "twilio" } ``` **4. Register the number with OneInbox** ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/phone-numbers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "phone_number": "+15739693824", "friendly_name": "Sales Line", "provider": "twilio", "agent_id": "", "provider_config": { "trunk_address": "yourtrunk.pstn.twilio.com", "auth_username": "oneinbox", "auth_password": "" }, "inbound_routing": { "agent_id": "", "fallback": { "agent_id": "" }, "voicemail_message": "Sorry, we missed you. Please leave a message." } }' ``` Include `inbound_routing` if you want this number to receive inbound calls. Omit it if you only need outbound. **1. Buy the number in Telnyx** Purchase a phone number from [Telnyx Portal](https://portal.telnyx.com) → Numbers → Buy Numbers. **2. Set up a SIP Connection** OneInbox connects to Telnyx via a SIP Connection (FQDN connection). **Step 1 — Create a connection** In [Telnyx Portal](https://portal.telnyx.com), go to **Voice** → **SIP Connections** → click **Add SIP Connection**. * **Connection name**: e.g. "OneInbox" * **Auth method**: Credential * Set a **username** and **password** — these go into `auth_username` and `auth_password` when you register the number in OneInbox *** **Step 2 — Get the SIP trunk domain** After creating the connection, Telnyx assigns a SIP domain — it looks like `.sip.telnyx.com`. Copy this — it's the `sip_trunk` value you'll pass to OneInbox. *** **Step 3 — Configure inbound (origination)** 1. Open your connection → go to **Inbound** 2. Under **SIP Trunking Settings**, set the origination destination to `sip:voice.oneinbox.ai:5060` *** **Step 4 — Attach your phone number** 1. Go to **Numbers** → select the number you purchased 2. Under **Connection/App**, select the SIP connection you just created 3. Click **Save** *** **Step 5 — Enable international calling (if needed)** If you need to call numbers outside your country: 1. Go to **Voice** → **Call Control** → **Outbound Voice Profile** 2. Enable the countries you need under **Destinations** **3. Store your Telnyx credentials in OneInbox** Your API key is in Telnyx Portal → Account → API Keys. Your account SID is in Account → Overview. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "My Telnyx Account", "provider": "telnyx", "api_key": "", "metadata": { "account_sid": "", "phone_number": "+15739693824", "sip_trunk": ".sip.telnyx.com" } }' ``` ```json theme={null} { "id": "crd_abc123", "provider": "telnyx" } ``` **4. Register the number with OneInbox** ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/phone-numbers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "phone_number": "+15739693824", "friendly_name": "Sales Line", "provider": "telnyx", "agent_id": "", "provider_config": { "trunk_address": ".sip.telnyx.com", "auth_username": "", "auth_password": "" }, "inbound_routing": { "agent_id": "", "fallback": { "agent_id": "" }, "voicemail_message": "Sorry, we missed you. Please leave a message." } }' ``` Include `inbound_routing` if you want this number to receive inbound calls. Omit it if you only need outbound. ```json theme={null} { "id": "phn_abc123", "phone_number": "+15739693824", "agent_id": "agt_abc123", "status": "active" } ``` To reassign the number to a different agent later, use [PATCH Update phone number](/api-reference/phone-numbers/update-phone-number) with `{ "agent_id": "..." }`. *** ## Inbound calls To make a number receive inbound calls, set `inbound_routing` when you register or purchase it (see paths A, B, and C above). Without `inbound_routing`, the number is outbound-only — calls to it will not be routed to your agent. To add or update inbound routing on an existing number, use [PATCH Update phone number](/api-reference/phone-numbers/update-phone-number): ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/phone-numbers/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "agent_id": "" }' ``` ### Inbound routing Use `inbound_routing` to control which agent handles inbound calls — you can use the same agent as outbound or a different one. Optionally add a fallback agent or a custom voicemail message. ```bash theme={null} # Set inbound_routing when registering the number curl -X POST https://api-tokyo.oneinbox.ai/v1/phone-numbers \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "phone_number": "+15551234567", "friendly_name": "Sales Line", "provider": "twilio", "agent_id": "", "provider_config": { ... }, "inbound_routing": { "agent_id": "", "fallback": { "agent_id": "" }, "voicemail_message": "Sorry, we missed you. Please leave a message." } }' # Or update routing on an existing number curl -X PATCH https://api-tokyo.oneinbox.ai/v1/phone-numbers/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "inbound_routing": { "agent_id": "", "voicemail_message": "Updated voicemail message." } }' ``` | Field | What it does | | ----------------------------------- | ------------------------------------------------------------------------------------------- | | `inbound_routing.agent_id` | Override which agent handles inbound calls — independent of the number's primary `agent_id` | | `inbound_routing.fallback.agent_id` | Agent to route to if the primary routing agent is unavailable | | `inbound_routing.voicemail_message` | Custom voicemail message for this number, overrides the agent's default | *** ## Manage phone numbers ### Get a phone number Retrieve a single number's current configuration — agent assignment, inbound routing, and provider details. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/phone-numbers/ \ -H "Authorization: Bearer " ``` ### Delete a phone number Releases the number from your account. For numbers purchased through OneInbox, this also cancels the number with the carrier. ```bash theme={null} curl -X DELETE https://api-tokyo.oneinbox.ai/v1/phone-numbers/ \ -H "Authorization: Bearer " ``` *** ## API reference [Register phone number](/api-reference/phone-numbers/register-phone-number) · [Update phone number](/api-reference/phone-numbers/update-phone-number) · [List phone numbers](/api-reference/phone-numbers/list-phone-numbers) · [Get phone number](/api-reference/phone-numbers/get-phone-number) · [Delete phone number](/api-reference/phone-numbers/delete-phone-number) # Quickstart Source: https://docs.oneinbox.ai/guides/quickstart Build your first voice agent, get a phone number, and make a real call — no third-party telephony account required. ## Overview In a few minutes you will have a working voice agent with its own phone number, and you'll have made a real outbound call with it. **You will:** 1. Create an **agent** 2. Purchase a **phone number** — directly through OneInbox, no Twilio account needed 3. **Make a call** 4. **Check the results** Every API request uses: ``` Authorization: Bearer ``` *** ## Prerequisites | Item | Where | | -------------------- | -------------------------------------------------------------------------------------- | | **OneInbox API key** | [Dashboard](https://oneinbox-dashboard.vercel.app) → **API Keys** → **Create API key** | | **Terminal** | `curl` (Mac Terminal, Windows PowerShell, or WSL) | *** ## Step 1 — Create an agent One API call. Give it a name — OneInbox automatically configures a default LLM, voice, and system prompt. The agent is ready to take calls immediately. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/agents \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "My First Agent" }' ``` ```json theme={null} { "id": "agt_abc123", "name": "My First Agent", "llm_id": "llm_xyz789", "created_at": "2026-06-01T10:00:00Z" } ``` Save both IDs from the response: * **`id`** — the agent (voice, language, call behavior) * **`llm_id`** — the AI brain (what it knows and can do). They're separate so multiple agents can share one brain. *** ## Step 2 — Purchase a phone number Buy a number directly through OneInbox — no Twilio or telephony account needed. **Option A — Search and pick a specific number:** ```bash theme={null} # 1. Search available numbers curl "https://api-tokyo.oneinbox.ai/v1/phone-numbers/search?country=US&area_code=415&limit=10" \ -H "Authorization: Bearer " # 2. Purchase the one you want curl -X POST https://api-tokyo.oneinbox.ai/v1/phone-numbers/purchase \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "phone_number": "+14155551234", "friendly_name": "My First Number", "agent_id": "" }' ``` **Option B — Auto-assign (skip the search):** ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/phone-numbers/purchase \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "country": "US", "area_code": "415", "friendly_name": "My First Number", "agent_id": "" }' ``` ```json theme={null} { "id": "phn_abc123", "phone_number": "+14155551234", "agent_id": "agt_abc123", "status": "active" } ``` Your number is now live both ways: it can call out, and anyone who dials it reaches your agent automatically. Already have a number in Twilio you'd rather use? See [Phone numbers](/guides/phone-calls) for the bring-your-own-number path. *** ## Step 3 — Make a call Call any number you want, using your new number as the caller ID: ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/calls \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "agent_id": "", "to_number": "+919876543210", "from_number": "+14155551234" }' ``` ```json theme={null} { "id": "call_abc123", "status": "initiated", "to_number": "+919876543210", "from_number": "+14155551234" } ``` Your phone rings — answer it to talk to your agent live. *** ## Step 4 — Check call results After the call ends, fetch the record: ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/calls/ \ -H "Authorization: Bearer " ``` ```json theme={null} { "id": "call_abc123", "status": "completed", "duration_seconds": 45, "messages": [ { "role": "agent", "content": "Hi! How can I help?" }, { "role": "user", "content": "I have a question about my order" } ], "outcome": "Interested", "ai_summary": "Caller asked about order status. Agent provided tracking info." } ``` `messages`, `outcome`, and `ai_summary` are only available after the call ends. *** ## Customize your agent Your agent works out of the box with defaults. When you're ready to tailor it to your use case, update it without rebuilding anything. ### Give it a personality Set a system prompt to define the agent's role and behaviour, and a first message to control how it opens every call: ```bash theme={null} # Set a system prompt on the LLM curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "system_prompt": "You are a helpful support agent for Acme Corp. Keep replies under two sentences. When the caller says goodbye, call end_call.", "temperature": 0.7 }' # Set a first message and call behaviour on the agent curl -X PATCH https://api-tokyo.oneinbox.ai/v1/agents/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "first_message": "Hi! Thanks for reaching out to Acme. How can I help?", "silence_timeout_seconds": 10, "enable_recording": true }' ``` ### Add tools Tools let your agent take actions during a call — transfer to a human, end the call, send an SMS, book a meeting, and more. Create each tool, then attach them to the LLM: ```bash theme={null} # Transfer to a human agent curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "transfer_to_human", "type": "transfer_call", "description": "Transfer to a human when the caller asks to speak to a person.", "transfer_to": "+15105550100" }' # End the call cleanly curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "end_call", "type": "end_call", "description": "End the call after the task is done or the caller says goodbye." }' # Attach both tools to the LLM curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "tool_ids": ["", ""] }' ``` See [Tools](/guides/tools) for the full list — SMS, email, calendar booking, data extraction, and more. ### Add a knowledge base Give your agent a document or URL to answer questions from: ```bash theme={null} # Create a knowledge base source curl -X POST https://api-tokyo.oneinbox.ai/v1/knowledge-bases \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Product FAQ", "source_type": "url", "url": "https://acme.com/faq" }' # Attach the knowledge base to the agent curl -X PATCH https://api-tokyo.oneinbox.ai/v1/agents/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "kb_ids": [""] }' ``` See [Knowledge bases](/guides/knowledge-bases) for uploading files, syncing URLs, and managing sources. *** ## Next steps Voice, language, recording, and behaviour settings Give your agent actions — SMS, email, data capture, transfer Upload docs or sync URLs for your agent to answer from Bring your own Twilio number, or learn more about outbound/inbound # Tools Source: https://docs.oneinbox.ai/guides/tools Give your agent the ability to take action during a call — send messages, capture data, transfer callers, book meetings, or call your own API. ## How tools work When a caller says something that matches a tool's trigger (defined in its `description` field), the agent fires that tool automatically mid-conversation. **The key thing to understand:** tools are attached to **LLM models**, not to agents directly. ``` Agent → LLM Model → Tools ``` One LLM model can have multiple tools. Every agent that uses that model inherits all its tools automatically. To give an agent a new tool, update the LLM model it is linked to — not the agent itself. If you haven't built an agent yet, start with the [Quickstart](/guides/quickstart) first. *** ## Tool types | Type | What the agent does | Best for | | ------------------------- | ------------------------------------------- | ------------------------------------------------------ | | `api_call` | Calls your HTTP endpoint | Custom logic, lookups, CRM updates — **your own code** | | `transfer_call` | Transfers to a phone number | Routing to humans | | `extract_information` | Saves structured data from the conversation | Capturing name, email, budget | | `end_call` | Hangs up the call | Completing a flow cleanly | | `send_sms` | Sends a text message | Follow-ups, confirmations | | `send_email` | Sends an email | Lead handoffs, summaries | | `schedule_calendar_event` | Books a calendar event | Demo scheduling, appointments | Whenever a tool talks to a third-party provider — `send_sms`, `send_email`, or `schedule_calendar_event` — you'll need a `credential_id` pointing at an [integration](/concepts/integrations) for that provider. `api_call`, `transfer_call`, `extract_information`, and `end_call` don't need one. *** ## Step 1 — Create a tool ### `api_call` OneInbox supports fully custom tools — define any action your agent should take by pointing it at an HTTP endpoint you control. The `api_call` tool type lets your agent call your own API mid-conversation to look up data, push to a CRM, trigger business logic, or take any other action your backend supports. There is no limit to what you can do: the agent extracts the right parameters from the conversation, calls your endpoint, and can use the response to decide what to say next. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "check_inventory", "type": "api_call", "description": "Look up inventory by SKU when the caller asks about stock or availability.", "url": "https://api.example.com/inventory", "method": "POST", "headers": { "Authorization": "Bearer " }, "parameters": [ { "name": "sku", "type": "string", "required": true, "description": "Product SKU the caller mentioned" } ], "run_in_background": true, "speak_during_execution": true }' ``` | Field | What it does | | ------------------------ | ------------------------------------------------------------------------------------------------------------------- | | `url` | Your endpoint URL — must be publicly reachable | | `method` | HTTP method (`GET`, `POST`, `PUT`, `PATCH`) | | `headers` | Any auth headers your endpoint requires | | `parameters` | Fields the agent extracts from the conversation and passes to your API as the request body | | `run_in_background` | `true` = agent keeps talking while the API call runs in parallel. `false` = agent pauses and waits for the response | | `speak_during_execution` | `true` = agent says something like "Let me check that for you…" while the API call is in progress | #### Nested parameters (full JSON Schema) `parameters` only supports a flat list of fields. If your endpoint needs nested objects, arrays, or enums, use `parameters_schema` instead — a raw JSON Schema object, validated server-side before save. Use one or the other, not both: ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "create_ticket", "type": "api_call", "description": "Open a support ticket when the caller reports an issue.", "url": "https://api.example.com/tickets", "method": "POST", "parameters_schema": { "type": "object", "properties": { "subject": { "type": "string", "description": "Ticket subject" }, "priority": { "type": "string", "enum": ["low", "high"] }, "items": { "type": "array", "items": { "type": "object", "properties": { "sku": { "type": "string" } }, "required": ["sku"] } } }, "required": ["subject"] } }' ``` *** ### `send_sms` Sends a text message when triggered. No `credential_id` needed — the SMS is sent from the same number used to make the call (your purchased OneInbox number or your Twilio/Telnyx number registered with OneInbox). ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "notify_team_sms", "type": "send_sms", "description": "SMS the team when a lead is captured. Trigger when the caller shares their contact details.", "messaging_config": { "to": "caller", "body_template": "New lead: {name} ({phone})" } }' ``` | Field | What it does | | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | `description` | How the agent decides when to fire this tool — write it as a trigger condition | | `messaging_config.to` | `"caller"` to text whoever is on the call, or an explicit E.164 number to notify your team | | `messaging_config.body_template` | Message text. Use `{variable_name}` (single braces) for dynamic values. Use `{{caller}}` to auto-insert the caller's phone number | The SMS sends from the same number used for the call — make sure that number has SMS capability enabled. When purchasing a number via OneInbox or registering your own Twilio/Telnyx number, verify that it supports SMS before using this tool. `{{caller}}` is a built-in variable that auto-resolves to the caller's phone number at call time — the system fills it in automatically. Never ask the caller for their number just to include it in the message body. *** ### `send_email` Sends an email when triggered. Use this to deliver lead summaries to your sales team, send follow-up emails to callers, or notify someone when a key moment happens in a call. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "notify_team_email", "type": "send_email", "description": "Email the sales team when a lead is captured. Trigger when the caller expresses interest.", "credential_id": "", "messaging_config": { "to": "sales@example.com", "subject_template": "New lead: {name}", "body_template": "{summary}" } }' ``` | Field | What it does | | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `description` | How the agent decides when to fire this tool — write it as a trigger condition | | `credential_id` | UUID of a `resend` or `sendgrid` integration. The email sends from that integration's `from_email` — which **must be on a domain you've verified with the provider**, or the send fails with HTTP 403 | | `messaging_config.to` | Recipient email address. Use `{{email}}` to send to the caller's email address | | `messaging_config.subject_template` | Email subject line. Use `{variable_name}` (single braces) for dynamic values | | `messaging_config.body_template` | Email body text. Use `{variable_name}` (single braces) for dynamic values pulled from the conversation | Want every call to auto-send a summary SMS/email without a tool call? Set `post_call_sms` / `post_call_email` directly on the **agent** instead — see [Agents](/concepts/agents). Tools fire mid-call based on a trigger; post-call config fires once, automatically, after every call ends. `{{email}}` resolves from the `dynamic_variables` object passed when the call is initiated — for example `"dynamic_variables": {"email": "caller@example.com"}` in the outbound call request. Pass the caller's email at dial time and use `{{email}}` anywhere in `to`, `subject_template`, or `body_template` to insert it automatically. *** ### `schedule_calendar_event` Books a calendar event when triggered. Use this when you want the agent to schedule a demo or follow-up meeting directly during the call. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "book_demo", "type": "schedule_calendar_event", "description": "Book a product demo when the caller asks to schedule a meeting or demo. Trigger phrases: schedule, book a demo, set up a call.", "credential_id": "", "calendar_config": { "event_type_id": 123456, "duration_minutes": 30, "timezone": "America/New_York" } }' ``` | Field | What it does | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `description` | Trigger condition — tell the agent exactly when to fire this (e.g. "when the caller agrees to a meeting") | | `credential_id` | UUID of a `calcom` integration. Required — the tool checks availability and books against this Cal.com account | | `calendar_config.event_type_id` | The Cal.com event type ID to book against. Find it in your Cal.com dashboard URL or via `GET https://api.cal.com/v2/event-types` | | `calendar_config.duration_minutes` | Length of the event in minutes | | `calendar_config.timezone` | IANA timezone string for the booking (e.g. `"Asia/Kolkata"`, `"Asia/Tokyo"`, `"Europe/London"`, `"America/New_York"`). Defaults to UTC if omitted — set this to the caller's timezone so the booked slot appears at the correct local time | The agent must collect the attendee's **name and email** during the call — both are required by Cal.com to complete the booking. If the requested slot has no availability (e.g. outside your Cal.com working hours), the booking fails with HTTP 400. *** ### `transfer_call` Transfers the caller to a real phone number. Use this when the caller asks to speak with a human or needs to reach a specific team. OneInbox supports two transfer modes — cold (default) and warm. | Mode | What happens | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Cold** (default) | Blind SIP REFER — caller is immediately handed off. The human picks up with no prior context. | | **Warm** | Agent calls the human first, briefs them with the caller's context, then connects the caller once the human is ready. Caller hears hold music during the briefing. | #### Cold transfer The default. The caller is transferred instantly — no briefing, no hold music. Use this when speed matters more than context handoff (e.g. routing to a general support queue). ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "transfer_to_support", "type": "transfer_call", "description": "Transfer to a human agent when the caller asks to speak to a person or escalate. Trigger phrases: talk to someone, speak to a human, I want a real person.", "transfer_to": "+15105550100" }' ``` Omitting `transfer_config` entirely is equivalent to `transfer_config.mode: "cold"`. #### Warm transfer The agent calls the human first, gives them a briefing (caller's name, reason for calling, any relevant context), then bridges the caller in once the human is ready. The caller hears hold music during the consult. Use this when the human needs context before picking up — e.g. transferring to a sales manager for a high-value lead. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "warm_transfer_to_supervisor", "type": "transfer_call", "description": "Warm transfer to a supervisor when the caller needs escalation.", "transfer_to": "+15105550100", "transfer_config": { "mode": "warm", "extra_instructions": "Greet the supervisor, give them the caller'\''s name and issue, and ask if they'\''re ready before connecting." } }' ``` | Field | What it does | | ------------------------------------ | ---------------------------------------------------------------------------------- | | `transfer_to` | E.164 phone number to transfer the caller to | | `description` | Trigger condition — be specific so the agent knows exactly when to fire this tool | | `transfer_config.mode` | `"cold"` (default) — blind handoff; `"warm"` — agent briefs human first | | `transfer_config.extra_instructions` | Warm mode only — guides what the agent should say to the human during the briefing | *** ### `extract_information` Silently captures structured data from the conversation as it happens — the agent doesn't announce it to the caller. Use this to save lead qualification data, capture names and emails, or record key facts from the call. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "lead_capture", "type": "extract_information", "description": "Extract lead info from the conversation. Run this once the caller has shared their name and contact details.", "extraction_schema": { "fields": [ { "name": "full_name", "type": "string", "required": true, "description": "Caller full name" }, { "name": "email", "type": "string", "description": "Caller email address" }, { "name": "interested", "type": "boolean", "description": "Whether the caller expressed interest" } ] } }' ``` | Field | What it does | | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `description` | Tells the agent *when* to run the extraction — not a phrase trigger, but a condition (e.g. "once the caller has answered the qualifying questions") | | `extraction_schema.fields` | List of fields to extract. Each field has a `name`, `type` (`string`, `boolean`, `number`), optional `required`, and a `description` that guides the extraction | The captured data is available in the call record after the call ends. *** ### `end_call` Hangs up the call cleanly. Use this at the end of a flow — after a booking, after the caller says goodbye, or when the agent has completed its task. Without this tool, the call continues until the silence timeout is reached. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "hangup", "type": "end_call", "description": "End the call cleanly after the agent has completed its task or the caller says goodbye." }' ``` *** ## Step 2 — Attach tools to your LLM model Creating a tool makes it available in your account, but the agent can't use it yet. You need to attach it to the LLM model linked to your agent. Use the `llm_id` from your agent's create response — this is the AI brain that decides what to do during a call. ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "tool_ids": ["", ""] }' ``` Every agent linked to this `llm_id` picks up the change immediately — no restart required. ### Detach tools from a model To remove tools from an LLM model without replacing the entire list, use `remove_tool_ids`: ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/models/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "remove_tool_ids": [""] }' ``` You can add and remove tools in the same request — `tool_ids` adds, `remove_tool_ids` detaches. *** ## Step 3 — Reference tools in your system prompt The `description` on each tool is the **trigger signal** — the LLM reads it to decide when to fire the tool automatically. The system prompt gives the agent context and ordering for *how* to use tools in the flow. **Reference tools by their `name` field** (the `name` you set when creating the tool), not by tool ID. The LLM matches the name to the tool it has available and fires it at the right moment. ``` You are a helpful sales assistant for Acme Corp. When the caller shares their name and email, use the lead_capture tool immediately. After capturing their info, ask if they'd like to receive a follow-up SMS. If they say yes, use notify_team_sms. If at any point the caller asks to speak to a human, use transfer_to_human. After the task is complete or the caller says goodbye, use end_call. Keep all replies under two sentences. Be warm and direct. ``` Write the `description` as a trigger condition ("Fire when the caller says X" or "Run once the caller has answered the qualifying questions"). The system prompt then reinforces the order and flow. Both are read by the LLM — the `description` drives *when*, the system prompt drives *how*. *** ## Reading tool results after a call After the call ends, the extracted data and tool activity appear in the call record. Stop the call first, wait a few seconds, then fetch: ```bash theme={null} # 1. Stop the call curl -X POST https://api-tokyo.oneinbox.ai/v1/calls//stop \ -H "Authorization: Bearer " # 2. Wait 2–3 seconds, then fetch curl https://api-tokyo.oneinbox.ai/v1/calls/ \ -H "Authorization: Bearer " ``` ```json theme={null} { "id": "call_abc123", "status": "completed", "messages": [ { "role": "agent", "content": "Hi! How can I help?" }, { "role": "user", "content": "My name is Sama, my email is sama@acme.com" } ], "outcome": "Interested", "analysis": { "summary": "Caller expressed interest and shared contact details." } } ``` `messages` and `analysis` are only available after the call ends — both are empty while the call is active. *** ## Manage tools ### List all tools Retrieve every tool in your account. Useful for finding tool IDs when you need to attach or update them. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/tools \ -H "Authorization: Bearer " ``` ### Update a tool Change a tool's name, description, or config. For example, update the trigger description to make the agent more (or less) sensitive to firing it. ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/tools/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "description": "Updated trigger description" }' ``` ### Delete a tool Remove a tool permanently. If the tool is attached to an LLM model, detach it first using `remove_tool_ids` (see Step 2 above), then delete it. ```bash theme={null} curl -X DELETE https://api-tokyo.oneinbox.ai/v1/tools/ \ -H "Authorization: Bearer " ``` *** ## API reference [Create tool](/api-reference/tools/create-tool) · [List tools](/api-reference/tools/list-tools) · [Update tool](/api-reference/tools/update-tool) · [Delete tool](/api-reference/tools/delete-tool) # Voices Source: https://docs.oneinbox.ai/guides/voices OneInbox ships 299 ready-to-use voices across Cartesia, Deepgram, ElevenLabs, OpenAI, Minimax, Soniox, and Shisa. Follow this guide if you want to use a specific custom voice from a third-party provider instead. ## Default voices OneInbox ships **299 voices out of the box** across Cartesia, Deepgram, ElevenLabs, OpenAI, Minimax, Soniox, and Shisa — no setup needed. You can use any of them immediately by setting `tts.voice_id` on your agent. | Provider | Voice count | Languages | | --------------------- | ----------- | -------------------------- | | **Deepgram** (aura-2) | 160 | en, es, de, fr, it, nl, ja | | **Shisa** | 77 | ja, en | | **Cartesia** | 40 | en, ja | | **ElevenLabs** | 6 | en | | **OpenAI** | 6 | en | | **Soniox** | 6 | en | | **Minimax** | 4 | en, zh | Browse the full list (with voice IDs) at any time: ```bash theme={null} curl "https://api-tokyo.oneinbox.ai/v1/voices" \ -H "Authorization: Bearer " # Filter to one provider curl "https://api-tokyo.oneinbox.ai/v1/voices?provider=cartesia" \ -H "Authorization: Bearer " ``` Always use the `id` field (`vc_...`) from the voice object as `tts.voice_id` — **not** the `provider_voice_id`. Passing the raw provider ID (e.g. a Cartesia UUID or a Deepgram model name) returns a `VOICE_NOT_FOUND` error. *** ## How voices work Every agent has a TTS (text-to-speech) configuration that controls how it sounds. A default voice is automatically assigned when you create an agent — you can hear it immediately with [a quick browser call](/concepts/agents#create-an-agent) (no phone number needed) or a real phone call. Follow this guide when you want to use a custom voice from ElevenLabs, Cartesia, or another provider. To switch, set the `provider` and `voice_id` on the agent. The `voice_id` is the OneInbox `id` (`vc_abc123`) returned when you import a voice (see below). ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/agents/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "tts": { "provider": "elevenlabs", "voice_id": "" } }' ``` *** ## Step 1 — Add an integration for your provider If you want to import voices beyond the 28 platform voices, you need to add an integration for your third-party provider first. An integration stores your provider API key securely so OneInbox can authenticate on your behalf. ### ElevenLabs ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "ElevenLabs", "provider": "elevenlabs", "api_key": "" }' ``` ### Cartesia ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/integrations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Cartesia", "provider": "cartesia", "api_key": "" }' ``` Both return an integration `id` — save it for Step 2. *** ## Step 2 — Import a voice Import a specific voice from your provider into OneInbox using its provider voice ID. The provider voice ID is the native ID from your provider's voice library (not the OneInbox ID). ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/voices/import \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "provider": "elevenlabs", "provider_voice_id": "21m00Tcm4TlvDq8ikWAM", "name": "Rachel", "credential_id": "", "gender": "female", "language": "en", "accent": "American" }' ``` ```json theme={null} { "id": "vc_abc123", "name": "Rachel", "provider": "elevenlabs", "provider_voice_id": "21m00Tcm4TlvDq8ikWAM" } ``` The `id` field (`vc_abc123`) is the OneInbox voice ID — this is what you use in the next step when assigning the voice to your agent. *** ## Step 3 — Assign the voice to your agent Use the OneInbox `id` from the import response (`vc_abc123`) to assign the voice to your agent. This tells the agent to use that specific voice for all calls. ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/agents/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "tts": { "provider": "elevenlabs", "voice_id": "vc_abc123", "speed": 1.0 } }' ``` | Field | Range | What it does | | ----------- | ------- | ------------------------------------------------------------------------- | | `voice_id` | — | The OneInbox `id` from the import response (format: `vc_abc123`) | | `speed` | 0.5–2.0 | Playback rate. `1.0` is normal speech speed | | `stability` | 0.0–1.0 | Voice consistency. Higher = more consistent tone, lower = more expressive | *** ## Get a voice Retrieve a single voice by its OneInbox ID. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/voices/ \ -H "Authorization: Bearer " ``` *** ## List imported voices Retrieve all voices in your account, or filter by provider: ```bash theme={null} # All voices in your account curl https://api-tokyo.oneinbox.ai/v1/voices \ -H "Authorization: Bearer " # Filter by provider curl "https://api-tokyo.oneinbox.ai/v1/voices?provider=elevenlabs" \ -H "Authorization: Bearer " ``` Each voice object: ```json theme={null} { "id": "vc_abc123", "name": "Rachel", "provider": "elevenlabs", "provider_voice_id": "21m00Tcm4TlvDq8ikWAM", "gender": "female", "language": "en", "accent": "American" } ``` *** ## API reference [List voices](/api-reference/voices/list-voices) · [Get voice](/api-reference/voices/get-voice) · [Import voice](/api-reference/voices/import-voice) # Webhooks Source: https://docs.oneinbox.ai/guides/webhooks Receive real-time events from OneInbox on your server — no polling required. ## How webhooks work When a call event occurs, OneInbox sends an HTTP POST to your server with the event payload. Your server must respond with `2xx` within a few seconds — if it doesn't, OneInbox retries delivery. Setting up a webhook means you don't need to poll `GET /v1/calls/` repeatedly. OneInbox pushes the data to you the moment the event fires. *** ## Create a webhook Set up a webhook by providing a URL on your server and the events you want to receive. OneInbox will send a POST request to that URL every time one of those events fires. ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/webhooks \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "name": "Call events", "url": "https://your-server.com/webhooks/oneinbox", "events": ["call.started", "call.ended", "call.analyzed", "call.failed", "call.recording.available", "transcript.partial", "transcript.final"] }' ``` ```json theme={null} { "id": "wh_abc123", "name": "Call events", "url": "https://your-server.com/webhooks/oneinbox", "events": ["call.started", "call.ended", "transcript.final"] } ``` Save the `id` — you'll need it to update or delete the webhook. *** ## Supported events | Event | When it fires | | -------------------------- | ------------------------------------------------------ | | `call.started` | Call connects and the agent begins the session | | `call.ended` | Call ends — agent or caller hung up | | `call.analyzed` | AI analysis (summary, outcome) is ready after the call | | `call.failed` | Call failed to connect | | `call.recording.available` | Call recording is ready and accessible | | `transcript.partial` | Partial transcript update during an active call | | `transcript.final` | Full transcript is ready (fires after `call.ended`) | *** ## Event payloads ### `call.started` Fires when a call connects and the agent starts the session. Use this to log call start times or trigger "call in progress" updates in your CRM. ```json theme={null} { "event": "call.started", "call_id": "call_abc123", "agent_id": "agt_abc123", "to_number": "+919876543210", "from_number": "+15739693824", "created_at": "2026-06-01T10:00:00Z" } ``` ### `call.ended` Fires when a call ends. This payload includes the AI-generated outcome and summary — the most commonly used event for CRM updates, lead routing, and reporting. ```json theme={null} { "event": "call.ended", "call_id": "call_abc123", "agent_id": "agt_abc123", "status": "completed", "duration_seconds": 87, "to_number": "+919876543210", "from_number": "+15739693824", "outcome": "Appointment Booked", "ai_summary": "Caller agreed to a product demo on Thursday at 3pm.", "analysis": { "summary": "Caller agreed to a product demo on Thursday at 3pm." } } ``` ### `call.analyzed` Fires after the call ends once the AI has finished generating the summary and outcome. Use this to trigger CRM updates or lead routing based on the call result. ```json theme={null} { "event": "call.analyzed", "call_id": "call_abc123", "agent_id": "agt_abc123", "outcome": "Appointment Booked", "ai_summary": "Caller agreed to a product demo on Thursday at 3pm." } ``` ### `call.failed` Fires when a call fails to connect. Use this to log failures, trigger retries, or alert your team. ```json theme={null} { "event": "call.failed", "call_id": "call_abc123", "agent_id": "agt_abc123", "to_number": "+919876543210", "from_number": "+15739693824", "reason": "no-answer" } ``` ### `call.recording.available` Fires when the call recording has been processed and is ready to access. Use this to store or share recordings after a call. ```json theme={null} { "event": "call.recording.available", "call_id": "call_abc123", "recording_url": "https://storage.oneinbox.ai/recordings/call_abc123.mp3" } ``` ### `transcript.partial` Fires during an active call with a partial transcript update. Use this for real-time monitoring or live agent assist — note that partial transcripts may change as the call continues. ```json theme={null} { "event": "transcript.partial", "call_id": "call_abc123", "messages": [ { "role": "agent", "content": "Hi! How can I help you today?" }, { "role": "user", "content": "I'd like to book a demo." } ] } ``` ### `transcript.final` Fires after `call.ended` once the full transcript is ready. Use this when you need the complete message-by-message conversation log — for example, to log it in your database or send it to a CRM. ```json theme={null} { "event": "transcript.final", "call_id": "call_abc123", "messages": [ { "role": "agent", "content": "Hi! How can I help you today?" }, { "role": "user", "content": "I'd like to book a demo." }, { "role": "agent", "content": "Of course! Let me get that booked for you." } ] } ``` *** ## Test a webhook Send a test delivery to confirm your server is receiving events correctly before going live: ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/webhooks//test \ -H "Authorization: Bearer " ``` Your server should receive a test POST with a sample payload. Check your server logs to confirm it arrives and that your endpoint returns `2xx`. *** ## Per-call webhook override You can send events for a specific call to a different URL without changing your global webhook config. This is useful when you're routing different campaigns or batches to separate downstream systems — for example, one URL for inbound calls and another for outbound. Pass `webhook_url` when creating the call: ```bash theme={null} curl -X POST https://api-tokyo.oneinbox.ai/v1/calls \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "agent_id": "", "to_number": "+919876543210", "from_number": "+15739693824", "webhook_url": "https://your-server.com/this-campaign-only" }' ``` The events for this call go to `webhook_url` instead of (or in addition to) any global webhooks you have configured. *** ## Manage webhooks ### List all webhooks Retrieve all webhooks in your account. Use this to find a webhook's `id` when you need to update or delete it. ```bash theme={null} curl https://api-tokyo.oneinbox.ai/v1/webhooks \ -H "Authorization: Bearer " ``` ### Update a webhook Change the URL, name, events, or status of a webhook. ```bash theme={null} curl -X PATCH https://api-tokyo.oneinbox.ai/v1/webhooks/ \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "events": ["call.started", "call.ended", "transcript.final"] }' ``` | Field | What it does | | -------- | ------------------------------------------------------------------------ | | `name` | Rename the webhook | | `url` | Change the delivery endpoint | | `events` | Replace the full list of subscribed events | | `status` | `"active"` or `"inactive"` — pause delivery without deleting the webhook | ### Delete a webhook Remove a webhook permanently. OneInbox will stop sending events to that URL immediately. ```bash theme={null} curl -X DELETE https://api-tokyo.oneinbox.ai/v1/webhooks/ \ -H "Authorization: Bearer " ``` ### View delivery history Retrieve the delivery-attempt log for a webhook — useful for verifying that a specific event reached your server or diagnosing failures. Returns most-recent attempt first; each row includes `response_status`, `response_body`, and `error`. ```bash theme={null} curl "https://api-tokyo.oneinbox.ai/v1/webhooks//deliveries?limit=50" \ -H "Authorization: Bearer " ``` *** ## API reference [Create webhook](/api-reference/webhooks/create-webhook) · [List webhooks](/api-reference/webhooks/list-webhooks) · [Update webhook](/api-reference/webhooks/update-webhook) · [Test delivery](/api-reference/webhooks/test-webhook-delivery) # Introduction Source: https://docs.oneinbox.ai/introduction OneInbox is a voice orchestration platform for building AI agents that handle live phone and web conversations. ## What is OneInbox? OneInbox is a **voice orchestration platform** for building AI agents that handle live voice conversations — over the phone and in the browser. You configure agents, voices, and call behavior through the REST API. OneInbox handles real-time audio, speech recognition, telephony routing, and scaling. *** ## Keys OneInbox has two kinds of keys. Which one you use depends on where your code runs — that distinction is the whole reason both exist. | Key | Starts with | Runs where | Can do | | ------------------- | ----------- | ---------------------- | ------------------------------------------------- | | **API key** | `oi_sk_` | Your server (backend) | Everything — create agents, make calls, read data | | **Publishable key** | `oi_pk_` | The browser (frontend) | Only start a call — nothing else | Use your **API key** for everything in this section. For the **publishable key**, see [Web SDK](/concepts/web-sdk) — it's created differently and used only to let website visitors start a call directly from your site. **Before you make your first API call**, get your API key: 1. [Create a free account →](https://oneinbox-dashboard.vercel.app/signup) 2. Go to **API Keys** and click **Create API key** 3. Copy the key — it starts with `oi_sk_` 4. Use it as `Authorization: Bearer ` on every request Already have an account? [Log in to your dashboard →](https://oneinbox-dashboard.vercel.app/login) Once logged in, you can view all your call logs — transcripts, outcomes, and latency breakdowns — directly in the dashboard using your API key. *** ## What you can build | Use case | How | | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | | **Outbound calling bot** | Agent dials leads, qualifies them, books demos | | **Inbound support line** | Assign a phone number — callers reach your agent 24/7 | | **Website voice widget** | Add the [Web SDK](/concepts/web-sdk) to your site with a publishable key — visitors talk to your agent right in the browser, no phone number needed | *** ## How a call works Caller speaks → transcribed to text → LLM decides reply → spoken back to caller. OneInbox runs this loop in real time. → [How it works](/concepts/how-it-works) *** ## Get started Agent + phone number + your first real call Full outbound calling bot — agent, tools, phone number, call, results Every endpoint with interactive Try It examples Get your API key and start making requests # Get Activity Summary Source: https://docs.oneinbox.ai/api-reference/activity/get-activity-summary /openapi/openapi.yaml get /v1/activity/summary Aggregate activity report for your organization. Returns, in one call: API activity from the audit log grouped by action (`audit_actions`, bounded by the `since`/`until` window), lifetime resource totals (`resource_counts` — agents, calls, phone numbers, knowledge bases, tools, integrations, API keys, users), a call breakdown by status / outcome / end reason (`call_summary`), and error signals (`error_signals` — calls that ended in error, knowledge-base sources that failed ingestion, failed webhook deliveries). Use `GET /v1/audit-events` for the raw event feed behind these numbers, or with `?actor=me` to see only events made with the calling API key. # Create Agent Source: https://docs.oneinbox.ai/api-reference/agents/create-agent /openapi/openapi.yaml post /v1/agents # Delete Agent Source: https://docs.oneinbox.ai/api-reference/agents/delete-agent /openapi/openapi.yaml delete /v1/agents/{agent_id} # Get Agent Source: https://docs.oneinbox.ai/api-reference/agents/get-agent /openapi/openapi.yaml get /v1/agents/{agent_id} # List Agents Source: https://docs.oneinbox.ai/api-reference/agents/list-agents /openapi/openapi.yaml get /v1/agents # Update Agent Source: https://docs.oneinbox.ai/api-reference/agents/update-agent /openapi/openapi.yaml patch /v1/agents/{agent_id} # List Audit Events Source: https://docs.oneinbox.ai/api-reference/audit-events/list-audit-events /openapi/openapi.yaml get /v1/audit-events # Create Call Source: https://docs.oneinbox.ai/api-reference/calls/create-call /openapi/openapi.yaml post /v1/calls Create an outbound phone call. Matches the published spec. # Delete Call Source: https://docs.oneinbox.ai/api-reference/calls/delete-call /openapi/openapi.yaml delete /v1/calls/{call_id} # Get Call Source: https://docs.oneinbox.ai/api-reference/calls/get-call /openapi/openapi.yaml get /v1/calls/{call_id} # List Calls Source: https://docs.oneinbox.ai/api-reference/calls/list-calls /openapi/openapi.yaml get /v1/calls # List calls (cursor pagination) Source: https://docs.oneinbox.ai/api-reference/calls/list-calls-cursor-pagination /openapi/openapi.yaml get /v1/calls/cursor Cursor-paginated alternative to GET /v1/calls. Pass back the `next_cursor` value to fetch the next page. Recommended over offset pagination for large call lists (>10k rows) because it is O(log n) per page instead of O(offset+limit). # Patch Call Source: https://docs.oneinbox.ai/api-reference/calls/patch-call /openapi/openapi.yaml patch /v1/calls/{call_id} Set the call's outcome label. Outcome is the only mutable field — everything else (transcript, recording, duration, etc.) is worker-owned and only updatable via the internal endpoints. # Stop Call Source: https://docs.oneinbox.ai/api-reference/calls/stop-call /openapi/openapi.yaml post /v1/calls/{call_id}/stop # Add a knowledge base source — file, URL, or inline text (auto-creates the KB) Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/add-a-knowledge-base-source-—-file-url-or-inline-text-auto-creates-the-kb /openapi/openapi.yaml post /v1/knowledge-bases/sources The single endpoint to add content to a knowledge base. You don't create a KB first — we auto-create one (named from `name`, the filename, or the URL) and attach your source. Returns a `job_id`; ingestion (parse → S3 → token count → vector index) runs in the background — poll `GET /v1/knowledge-bases/{kb_id}/jobs/{job_id}`. Three call shapes, one endpoint: - **File upload** (multipart/form-data): `file=@path/to/doc.pdf`. Allowed: pdf, docx, xlsx/xls, txt, md. - **URL** (multipart): `type=url&source=https://...` - **Inline text** (multipart): `type=text&source=...` The response's `source.knowledge_base_id` is the new KB id. To remove a source, use `DELETE /v1/knowledge-bases/{kb_id}/sources/{source_id}`. # Delete a knowledge base source (file / URL / inline text) Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/delete-a-knowledge-base-source-file-url-inline-text /openapi/openapi.yaml delete /v1/knowledge-bases/{kb_id}/sources/{source_id} Removes a single source from the KB along with its vector chunks and the stored file (S3). Get the `source_id` from `GET /v1/knowledge-bases/{kb_id}/sources`. Returns 404 if the source doesn't exist in this KB. # Delete Kb Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/delete-kb /openapi/openapi.yaml delete /v1/knowledge-bases/{kb_id} # Get Kb Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/get-kb /openapi/openapi.yaml get /v1/knowledge-bases/{kb_id} # Get Kb Job Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/get-kb-job /openapi/openapi.yaml get /v1/knowledge-bases/{kb_id}/jobs/{job_id} Poll the status of a background ingestion / indexing job. # List Kb Jobs Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/list-kb-jobs /openapi/openapi.yaml get /v1/knowledge-bases/{kb_id}/jobs Recent jobs for this KB (most-recent first, up to 20). # List Kb Sources Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/list-kb-sources /openapi/openapi.yaml get /v1/knowledge-bases/{kb_id}/sources # List Kbs Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/list-kbs /openapi/openapi.yaml get /v1/knowledge-bases # Update Kb Source: https://docs.oneinbox.ai/api-reference/knowledge-bases/update-kb /openapi/openapi.yaml patch /v1/knowledge-bases/{kb_id} # Update Model Source: https://docs.oneinbox.ai/api-reference/llm-models/update-model /openapi/openapi.yaml patch /v1/models/{model_id} # Delete Phone Number Source: https://docs.oneinbox.ai/api-reference/phone-numbers/delete-phone-number /openapi/openapi.yaml delete /v1/phone-numbers/{phone_id} # Get Phone Number Source: https://docs.oneinbox.ai/api-reference/phone-numbers/get-phone-number /openapi/openapi.yaml get /v1/phone-numbers/{phone_id} # List Phone Numbers Source: https://docs.oneinbox.ai/api-reference/phone-numbers/list-phone-numbers /openapi/openapi.yaml get /v1/phone-numbers # Purchase Phone Number Source: https://docs.oneinbox.ai/api-reference/phone-numbers/purchase-phone-number /openapi/openapi.yaml post /v1/phone-numbers/purchase Buy a phone number through OneInbox and wire it to an agent in one step. OneInbox provisions the number on its own carrier account — the caller brings no external provider account or credentials. Pass a specific `phone_number` from GET /phone-numbers/search, or just filters to auto-pick one. # Register Phone Number Source: https://docs.oneinbox.ai/api-reference/phone-numbers/register-phone-number /openapi/openapi.yaml post /v1/phone-numbers # Search Available Numbers Source: https://docs.oneinbox.ai/api-reference/phone-numbers/search-available-numbers /openapi/openapi.yaml get /v1/phone-numbers/search Search phone numbers available to buy through OneInbox. Numbers come from OneInbox's own carrier inventory — no external provider account or credential is required to search. Buy one you like with POST /phone-numbers/purchase. # Update Phone Number Source: https://docs.oneinbox.ai/api-reference/phone-numbers/update-phone-number /openapi/openapi.yaml patch /v1/phone-numbers/{phone_id} # Create Tool Source: https://docs.oneinbox.ai/api-reference/tools/create-tool /openapi/openapi.yaml post /v1/tools # Delete Tool Source: https://docs.oneinbox.ai/api-reference/tools/delete-tool /openapi/openapi.yaml delete /v1/tools/{tool_id} # Get Tool Source: https://docs.oneinbox.ai/api-reference/tools/get-tool /openapi/openapi.yaml get /v1/tools/{tool_id} # List Tools Source: https://docs.oneinbox.ai/api-reference/tools/list-tools /openapi/openapi.yaml get /v1/tools # Update Tool Source: https://docs.oneinbox.ai/api-reference/tools/update-tool /openapi/openapi.yaml patch /v1/tools/{tool_id} # Get Usage Source: https://docs.oneinbox.ai/api-reference/usage/get-usage /openapi/openapi.yaml get /v1/usage # Get Voice Source: https://docs.oneinbox.ai/api-reference/voices/get-voice /openapi/openapi.yaml get /v1/voices/{voice_id} # Import Voice Source: https://docs.oneinbox.ai/api-reference/voices/import-voice /openapi/openapi.yaml post /v1/voices/import # List Voices Source: https://docs.oneinbox.ai/api-reference/voices/list-voices /openapi/openapi.yaml get /v1/voices # Create Webhook Source: https://docs.oneinbox.ai/api-reference/webhooks/create-webhook /openapi/openapi.yaml post /v1/webhooks # Delete Webhook Source: https://docs.oneinbox.ai/api-reference/webhooks/delete-webhook /openapi/openapi.yaml delete /v1/webhooks/{webhook_id} # Get Webhook Source: https://docs.oneinbox.ai/api-reference/webhooks/get-webhook /openapi/openapi.yaml get /v1/webhooks/{webhook_id} # List Webhook Deliveries Source: https://docs.oneinbox.ai/api-reference/webhooks/list-webhook-deliveries /openapi/openapi.yaml get /v1/webhooks/{webhook_id}/deliveries Delivery-attempt log for this webhook. Partners use this to verify we tried to deliver a specific event without filing a support ticket. Newest attempt first. Includes response_status / response_body / error fields from the most recent attempt on each row. # List Webhooks Source: https://docs.oneinbox.ai/api-reference/webhooks/list-webhooks /openapi/openapi.yaml get /v1/webhooks # Test Webhook Source: https://docs.oneinbox.ai/api-reference/webhooks/test-webhook /openapi/openapi.yaml post /v1/webhooks/{webhook_id}/test # Update Webhook Source: https://docs.oneinbox.ai/api-reference/webhooks/update-webhook /openapi/openapi.yaml patch /v1/webhooks/{webhook_id} # Create Call Outcome Source: https://docs.oneinbox.ai/api-reference/workspace/create-call-outcome /openapi/openapi.yaml post /v1/workspace/call-outcomes # List Call Outcomes Source: https://docs.oneinbox.ai/api-reference/workspace/list-call-outcomes /openapi/openapi.yaml get /v1/workspace/call-outcomes # Update Call Outcome Source: https://docs.oneinbox.ai/api-reference/workspace/update-call-outcome /openapi/openapi.yaml patch /v1/workspace/call-outcomes/{outcome_id}