KrosAI Documentation ## Sections • [Overview](https://docs.krosai.com/overview.md): The KrosAI Bridge API enables seamless management of AI-driven telephone calls throughout their entire lifecycle, including call routing, recording, transcription, billing, and real-time event synchronization. Users can leverage this API to integrate and control intelligent voice interactions within their applications efficiently. Authentication Two credential forms are accepted: kros_ API key (service-to-service): Plain text Authorization: Bearer kros_<random> The header X-API-Key is not accepted. Base URL Title Description Environment Base URL Production https://api.krosai.com All public endpoints are prefixed /api/v1/ . Rate Limiting 600 requests per minute per IP (≈ 10 req/s sustained). Health, OpenAPI, and docs routes are exempt. Responses include a Retry-After header when the limit is exceeded (HTTP 429). Idempotency POST / PUT / PATCH endpoints honour the Idempotency-Key request header. Duplicate requests with the same key within the replay window are served from cache without re-executing the handler. Response Headers Title Description Header Description x-routed-via: bridge Confirms the request reached Bridge x-request-id Echoed from caller or fresh UUID v4 — use for distributed tracing Organisation Scoping All data endpoints require an organization_id query parameter (UUID). The Bridge service key bypasses Supabase RLS, so the explicit org filter is the sole access control boundary — never omit it. AI Provider Support Title Description Title Description Provider Outbound Inbound Notes ElevenLabs ✅ ✅ SIP + Batch Calling API Vapi ✅ ✅ API-based dispatch Retell ✅ ✅ API-based dispatch Vogent ✅ ✅ SIP URI routing Custom SIP ✅ ✅ Any SIP URI • [Calls](https://docs.krosai.com/calls.md): Manage the full lifecycle of voice calls, including initiating outbound calls, retrieving call details, accessing transcripts and lifecycle events, and controlling recordings. Additionally, simulate inbound calls for testing and soft-delete call records to maintain data integrity. • [Simulate inbound call](https://docs.krosai.com/calls/simulate-inbound-call.md): Simulate inbound calls to test and validate call handling within your organization’s telephony setup. This functionality enables authenticated users to generate realistic call scenarios, with organization context automatically applied for customer callers or explicitly specified for internal users, facilitating robust integration and workflow testing. • [Initiate outbound call](https://docs.krosai.com/calls/initiate-outbound-call.md): Initiate outbound calls with flexible configuration options, including caller ID, destination number, and agent routing. This section enables users to create and manage outbound voice sessions while automatically associating calls with the correct organization based on authentication context. • [Terminate call](https://docs.krosai.com/calls/terminate-call.md): This section allows users to terminate an active call by specifying its unique identifier. Customer callers can only end calls within their own organization, while internal users have permission to hang up any call. Optional parameters let users customize the hangup cause for the termination. • [Get Call Status](https://docs.krosai.com/calls/get-call-status.md): Retrieve the current status of a specific call by providing its unique identifier, enabling users to monitor call activity in real time. Access is securely scoped to the caller’s organization for customer principals, ensuring call data privacy, while internal users have broader query capabilities. This functionality supports accurate and lightweight call status probing within the KrosAI platform. • [Get Transcript](https://docs.krosai.com/calls/get-transcript.md): Retrieve the stored transcript of a completed call, delivered either as a structured chat format with role-based messages or as plain text when JSON formatting is unavailable. Access is securely scoped to the caller’s organization, ensuring transcript privacy across tenants while allowing internal users broader retrieval capabilities. • [List calls](https://docs.krosai.com/calls/list-calls.md): Retrieve a paginated list of calls within an organization, optionally filtered by status, direction, and other criteria. By default, the results exclude calls that never connected, but these can be included to analyze all call activity. This allows users to efficiently navigate and review call records sorted by creation time. • [Get call detail](https://docs.krosai.com/calls/get-call-detail.md): Retrieve the complete call record associated with a specific call UUID, scoped to the caller’s organization to ensure secure access. This allows users to obtain detailed information about individual calls for auditing, troubleshooting, or reporting purposes. • [Soft-delete a call record](https://docs.krosai.com/calls/soft-delete-a-call-record.md): Mark a call record as deleted to exclude it from standard retrievals while preserving the data for billing and audit purposes. This action ensures the record remains in the system but is hidden from active call listings, maintaining data integrity without permanent removal. • [List call lifecycle events](https://docs.krosai.com/calls/list-call-lifecycle-events.md): Retrieve a detailed chronological log of all lifecycle events associated with a specific call, enabling you to track its progression from initiation through to hangup. This includes key state changes like ringing, answering, recording start and stop, as well as other relevant events, providing comprehensive insight into the call’s history. • [Get call recording metadata](https://docs.krosai.com/calls/get-call-recording-metadata.md): Retrieve detailed metadata for a completed call, including the recording URL and its transcript when available. This allows users to access and review call recordings and their contents for analysis, compliance, or archival purposes. • [Control call recording](https://docs.krosai.com/calls/control-call-recording.md): Control call recording by initiating or terminating the recording for an active call within your organization. This section enables you to start or stop call recordings dynamically, with optional customization of the recording storage location. Use this functionality to manage call recordings seamlessly during live calls. • [Endpoints](https://docs.krosai.com/endpoints.md): Manage and configure AI endpoints that connect to various AI providers or custom SIP URIs, enabling seamless routing of inbound calls and outbound requests. This section allows you to create, update, retrieve, and delete endpoint configurations, as well as verify connectivity to ensure reliable integration with your chosen AI services. • [List endpoints](https://docs.krosai.com/endpoints/list-endpoints.md): Retrieve a comprehensive list of AI endpoints associated with your organization, optionally filtered by endpoint type. This section enables users to efficiently access and manage available endpoints, organized by their creation date for easy reference. • [Create endpoint](https://docs.krosai.com/endpoints/create-endpoint.md): Create and configure a new AI endpoint by specifying essential details such as its name, provider type, and connection settings. This enables users to integrate and manage various AI service providers within their organization, tailoring endpoint behavior through customizable parameters like URLs, secrets, and status. • [Get endpoint](https://docs.krosai.com/endpoints/get-endpoint.md): Retrieve detailed information about a specific endpoint within your organization by providing its unique identifier. This allows you to access the endpoint’s configuration and metadata, enabling effective management and integration within your KrosAI environment. • [Update endpoint](https://docs.krosai.com/endpoints/update-endpoint.md): Modify the configuration of an existing endpoint by updating one or more of its attributes. This operation supports partial updates, allowing users to change only the specified fields such as the display name, URL, provider settings, secret, or status, while leaving other properties unchanged. • [Delete endpoint](https://docs.krosai.com/endpoints/delete-endpoint.md): Remove a specific endpoint configuration from your account to permanently disable its associated functionalities. This operation ensures that only endpoints within your organization’s scope can be deleted, maintaining secure and precise management of your API integrations. • [Partial update endpoint](https://docs.krosai.com/endpoints/partial-update-endpoint.md): Use this endpoint to apply partial updates to an existing endpoint’s configuration by modifying only the provided fields, leaving all other settings unchanged. It enables flexible and precise adjustments to an endpoint’s properties such as its name, URL, provider configuration, secret, or status without requiring a full replacement. • [Test endpoint connectivity](https://docs.krosai.com/endpoints/test-endpoint-connectivity.md): This section allows you to verify the reachability and responsiveness of a configured endpoint by testing its connectivity. It supports both HTTP/HTTPS URLs, returning the HTTP response status and latency, and SIP-based hosts, performing a DNS resolution check to ensure proper configuration. Use this to quickly validate endpoint availability and diagnose connection issues. • [Phone Numbers](https://docs.krosai.com/phone-numbers.md): Manage your phone number inventory by claiming, registering, and releasing numbers, as well as searching available inventory based on criteria like country or area code. Configure routing settings, perform port diagnostics, and connect or disconnect AI endpoints to optimize call handling and integration within your organization. • [List phone numbers](https://docs.krosai.com/phone-numbers/list-phone-numbers.md): Retrieve a comprehensive list of phone numbers associated with a specific organization, optionally filtered by status. This allows users to view and manage their phone inventory efficiently, excluding sensitive SIP credentials which are available through detailed queries for individual numbers. • [Claim or register a phone number](https://docs.krosai.com/phone-numbers/claim-or-register-a-phone-number.md): Claim or register a phone number to your organization’s account, ensuring it is activated and ready for use. Configure inbound and outbound call permissions along with custom routing options to control how calls are handled. The process verifies your organization’s balance before associating the number, enabling seamless management of your telephony resources. This section enables organizations to claim or register a new phone number to their account, ensuring the number is activated upon creation. It verifies that the organization has sufficient balance before associating the number, allowing users to configure inbound and outbound call permissions and routing options as needed. • [Browse available phone number inventory](https://docs.krosai.com/phone-numbers/browse-available-phone-number-inventory.md): Retrieve a list of unassigned phone numbers available for provisioning, filtered by criteria such as country, area code, digit patterns, and toll-free status. This allows users to efficiently discover inventory that matches their specific requirements, enabling seamless number selection and allocation. • [Search available phone number inventory with filters](https://docs.krosai.com/phone-numbers/search-available-phone-number-inventory-with-filters.md): Retrieve a tailored list of available phone numbers by applying flexible search filters such as country code, area code, toll-free status, and number patterns. This enables users to efficiently identify and select phone numbers that meet specific criteria from the inventory. • [Get phone number](https://docs.krosai.com/phone-numbers/get-phone-number.md): Retrieve detailed information about a specific phone number using its unique identifier within your organization’s scope. This section provides the complete phone number record, including associated SIP credentials, enabling you to manage or integrate telephony data securely and efficiently. • [Partial update phone number](https://docs.krosai.com/phone-numbers/partial-update-phone-number.md): Update specific attributes of an existing phone number record without affecting unspecified fields. Users can modify details such as endpoint association, routing preferences, and status, including detaching the endpoint by setting its value to null. This enables precise, partial updates to phone number configurations within an organization. • [Release or delete phone number](https://docs.krosai.com/phone-numbers/release-or-delete-phone-number.md): This section allows you to either release a phone number, marking it as available while retaining its record for audit purposes, or permanently delete it from the system. Users can manage the lifecycle of phone numbers by choosing to soft-release them or fully remove them based on their operational needs. • [Attach or detach endpoint](https://docs.krosai.com/phone-numbers/attach-or-detach-endpoint.md): Use this section to link an AI endpoint to a specific phone number within your organization or to remove an existing association by detaching the endpoint. This enables dynamic control over which AI endpoint processes calls for each phone number, streamlining endpoint management and configuration. • [Detach endpoint from phone number](https://docs.krosai.com/phone-numbers/detach-endpoint-from-phone-number.md): Use this endpoint to remove the association between a phone number and its assigned endpoint, effectively clearing the endpoint assignment. Once detached, inbound calls to the number will default to the fallback handler, ensuring uninterrupted call routing without an explicit endpoint. • [Phone number diagnostic check](https://docs.krosai.com/phone-numbers/phone-number-diagnostic-check.md): Use this section to perform a routing diagnostic on a specific phone number by verifying its assigned endpoint’s existence, enabled status, and correct configuration. This check inspects the phone number’s database state without initiating any live network probes, helping you quickly identify misconfigurations or missing assignments. • [API Keys](https://docs.krosai.com/api-keys.md): Manage and control your organization’s API keys by creating, updating, rotating, and revoking them as needed. Monitor individual key usage with detailed statistics to maintain security and track access, while ensuring raw keys are only exposed during creation and rotation for enhanced protection. • [List API keys](https://docs.krosai.com/api-keys/list-api-keys.md): Retrieve a comprehensive list of API keys associated with an organization, including the ability to optionally include revoked keys. The response provides metadata such as key prefixes and masked identifiers, ensuring sensitive key material remains secure while enabling effective key management and auditing. • [Create API key](https://docs.krosai.com/api-keys/create-api-key.md): Generate a new API key to authenticate and authorize access within your organization. The response includes the raw key only once, so be sure to store it securely as it cannot be retrieved again. Customize the key’s permissions by specifying optional scopes to control access levels. • [Update API key](https://docs.krosai.com/api-keys/update-api-key.md): Modify an existing API key’s metadata by updating its name and access scopes to better align with your security and organizational needs. This section allows you to adjust permissions without changing the key itself, enabling precise control over API access. • [Revoke API key](https://docs.krosai.com/api-keys/revoke-api-key.md): Use this section to immediately deactivate an existing API key by marking it as revoked, ensuring it can no longer be used for authentication. This action helps maintain security by preventing further access with the revoked key across your organization. • [Rotate API key](https://docs.krosai.com/api-keys/rotate-api-key.md): Rotate an API key to immediately replace an existing key with a new one, enhancing security by invalidating the old key without delay. The newly generated key is returned only once during this operation, allowing users to seamlessly update their credentials. • [API key usage](https://docs.krosai.com/api-keys/api-key-usage.md): Retrieve detailed usage statistics aggregated by API key to monitor and analyze access patterns within your organization. This section enables you to gain insights into API consumption, helping you track activity and manage key-based usage effectively. • [Per-key usage summary](https://docs.krosai.com/api-keys/per-key-usage-summary.md): Retrieve detailed usage statistics for each API key within your organization to monitor and analyze consumption patterns. This section enables you to gain insights into how individual API keys are utilized, helping optimize access management and track usage effectively. • [Create SDK session token](https://docs.krosai.com/api-keys/create-sdk-session-token.md): Generate a short-lived SDK session token that securely embeds your organization ID, granted scopes, and expiration time. This token enables client SDKs to authenticate real-time features such as WebRTC and LiveKit events without exposing the raw Bridge API key, ensuring seamless and secure client-side interactions. • [Webhooks](https://docs.krosai.com/webhooks.md): Configure and manage webhook endpoints to receive real-time notifications about call lifecycle events. This section allows you to register new webhooks, verify their functionality, track delivery status, and retry failed notifications to maintain reliable event processing. Manage and configure webhook endpoints to receive real-time notifications about call lifecycle events. This section enables you to register new webhooks, verify their connectivity, monitor delivery history, and retry failed notifications to ensure reliable event processing. • [List webhooks](https://docs.krosai.com/webhooks/list-webhooks.md) • [Create webhook](https://docs.krosai.com/webhooks/create-webhook.md): Use this section to configure a new outbound webhook by specifying its target URL, the events it should listen to, and optional security settings like a signing secret. This enables your application to receive real-time notifications for selected events, with the ability to enable or disable the webhook as needed. • [Update webhook](https://docs.krosai.com/webhooks/update-webhook.md): Update webhook configurations to modify settings such as the target URL, subscribed events, signing secret, or activation status. This allows users to tailor how outbound webhook notifications are delivered and secured for their organization. • [Delete webhook](https://docs.krosai.com/webhooks/delete-webhook.md): Remove an existing outbound webhook associated with your organization to stop it from receiving future event notifications. This operation ensures that only authorized users can delete webhooks within their access scope, helping maintain secure and organized webhook management. • [Update webhook](https://docs.krosai.com/webhooks/update-webhook-1.md): Update webhook configurations to modify any combination of the webhook’s URL, subscribed events, signing secret, or activation status. This allows you to tailor outbound webhook behavior dynamically, ensuring notifications remain accurate and secure. • [Send a test event to a webhook](https://docs.krosai.com/webhooks/send-a-test-event-to-a-webhook.md): Simulate sending a synthetic test event to a specified webhook URL to confirm its availability and proper configuration. This allows you to verify that your webhook endpoint is reachable and correctly processes signed test payloads, ensuring reliable event delivery. • [Retry a failed webhook delivery](https://docs.krosai.com/webhooks/retry-a-failed-webhook-delivery.md): This section enables you to retry a previously failed or undelivered webhook delivery by fetching the original payload and securely resending it to the configured webhook URL. It helps ensure reliable event delivery by updating the delivery status based on the retry attempt outcome. • [Webhook delivery history](https://docs.krosai.com/webhooks/webhook-delivery-history.md): Retrieve a chronological record of all delivery attempts for a specific webhook, enabling users to monitor and troubleshoot webhook performance and reliability. This section provides detailed insight into each delivery attempt, sorted from most recent to oldest, helping ensure webhook events are successfully received and processed. • [Health](https://docs.krosai.com/health.md): Service health. Returns ESL connectivity, Supabase reachability, recording pipeline status, and component-level sub-checks. • [Platform health snapshot](https://docs.krosai.com/health/platform-health-snapshot.md): Retrieve a comprehensive snapshot of the platform’s overall health, including the status of critical components like ESL connectivity and Supabase integration. This enables users to monitor system integrity and diagnose potential issues programmatically within the same API environment used for other operations. • [Health Check](https://docs.krosai.com/health/health-check.md): Public health check endpoint. No authentication required. Returns basic service identification for monitoring, uptime checks, and Cloudflare health probes. Returns: JSON dict with service , version , docs , and health keys confirming the service is reachable. • [Root](https://docs.krosai.com/health/root.md): Root endpoint returning service identification info. Returns: JSON dict with service , version , docs , and health keys for quick service discovery. • [Provider Integrations](https://docs.krosai.com/provider-integrations.md): Manage and securely store your third-party provider credentials, including integrations with services like ElevenLabs, Vapi, Retell, and OpenAI. This section enables you to create, update, retrieve, and remove provider integrations while ensuring API keys remain protected by only exposing masked hints after creation. Additionally, you can verify the validity of your credentials before saving them. • [List provider integrations](https://docs.krosai.com/provider-integrations/list-provider-integrations.md): List all provider integrations for an organisation. Raw credentials are never returned — only safe metadata fields are included: id , provider , display_name , is_connected , last_tested_at , organization_id , created_at , updated_at . Args: organization_id: UUID of the organisation. provider: Optional provider name filter (e.g. "elevenlabs" , "vapi" ). Returns: List of integration dicts ordered by created_at descending. Raises: HTTPException: 503 when DB unavailable; 500 on query error. • [Create or upsert a provider integration](https://docs.krosai.com/provider-integrations/create-or-upsert-a-provider-integration.md): Create or upsert a provider integration credential set. If an integration for this ``(organization_id, provider)`` pair already exists, it is updated in-place (upsert on the unique constraint). The raw ``api_key`` is stored in ``api_key_encrypted`` and is never returned; the response includes only an ``api_key_hint`` with ``last4`` and ``prefix`` fields. Args: body: Integration creation payload. Must include ``organization_id``, ``provider``, and at least one of ``api_key`` or ``credentials`` (alias for ``extra_config``). Returns: Integration row with ``api_key_encrypted`` replaced by ``api_key_hint``. Raises: HTTPException: 400 when neither ``api_key`` nor ``credentials`` is supplied, or when the provider value violates the DB check constraint; 503 when DB unavailable; 500 on DB write error. • [Get a provider integration](https://docs.krosai.com/provider-integrations/get-a-provider-integration.md): Retrieve detailed information about a specific provider integration using its unique identifier. This allows users to access all safe, non-sensitive metadata related to the integration while ensuring that confidential credentials remain protected. • [Update a provider integration](https://docs.krosai.com/provider-integrations/update-a-provider-integration.md): Update the display name, connection status, or configuration details of an existing provider integration to keep its metadata current. This operation allows you to modify non-sensitive information without affecting the integration’s API credentials. Use it to manage integration settings and ensure accurate representation within your organization. • [Delete a provider integration](https://docs.krosai.com/provider-integrations/delete-a-provider-integration.md): Remove an existing provider integration along with all associated stored credentials from your account. This action permanently deletes the integration, ensuring it is no longer available for authentication or data exchange within your organization. • [Test provider integration credentials](https://docs.krosai.com/provider-integrations/test-provider-integration-credentials.md): Use this feature to validate a provider’s integration credentials by performing a live verification call. You can test credentials either by referencing an existing integration or by providing an API key directly, enabling you to confirm access before saving or updating provider details. Supported providers include ElevenLabs, VAPI, and Retell, each verified against their respective endpoints. • [ℹ️ Introduction](https://docs.krosai.com/getting-started/introduction.md): AI-Native Phone Infrastructure for Emerging Markets KrosAI is the developer platform for connecting AI voice agents to real phone numbers. We handle the complex telephony infrastructure so you can focus on building great voice experiences. What is KrosAI? KrosAI bridges the gap between AI voice agents and traditional phone networks. Whether you're building customer support bots, sales automation, or appointment scheduling systems, KrosAI provides the infrastructure to make and receive real phone calls. With KrosAI, you can: Connect any AI agent to phone numbers - ElevenLabs, Vapi, Retell, LiveKit, or your custom voice agent Provision local numbers in emerging markets - Africa (Nigeria, Kenya, Ghana, South Africa) and MENA (UAE, Egypt) Simple API & SDK - Get your first call working in under 5 minutes Full observability - Call logs, recordings, transcripts, and analytics How it works 1 Your AI agent Produces audio output (speech synthesis). 2 KrosAI Bridge Handles WebRTC/SIP conversion and routes audio to/from phone networks. 3 Phone Network Connects to real phones via local numbers in your target markets. Key capabilities Feature Description Sub-second latency Optimized audio routing for natural conversations Emerging market coverage Local numbers in Nigeria, Kenya, UAE, Ghana, and more Simple SDK Connect your agent in 10 lines of code Real-time events Webhooks for call.started, call.ended, transcription, etc. Per-second billing Pay only for the time you use Call recordings Automatic recording with transcript generation Choose your path Phone Calls (5-minute quickstart) Build your first voice agent in 5 minutes Create an AI-powered phone line that can make and receive calls. Perfect for customer support, sales automation, and appointment booking. → Get started with phone calls 💻 Web Integration (Voice SDK) Embed voice in your app Use our React SDK to add phone calling capabilities directly to your web application. → Get Started with Voice SDK Supported AI providers Provider Integration Type Best For Provider Integration Type Best For ElevenLabs WebRTC/SIP Natural conversation, voice cloning, multilingual Vapi SIP Structured workflows, tool calling, function execution Retell SIP Low-latency, custom LLMs, enterprise deployments LiveKit WebRTC Real-time collaboration, multi-party calls Custom/Webhook HTTP Your own voice infrastructure Quick links API Reference - Full REST API documentation Voice SDK Reference - JavaScript/TypeScript SDK Webhooks - Real-time event notifications Error Codes - Troubleshooting guide Rate Limits - API limits and best practices • [🚀Quickstart](https://docs.krosai.com/getting-started/quickstart.md): In this quickstart, you'll create an AI-powered phone line that can make and receive calls. By the end, you'll have a working phone number connected to your AI agent. What you'll learn: Create your KrosAI account and API key Purchase a phone number Connect an AI endpoint (ElevenLabs, Vapi, or custom) Make your first inbound and outbound calls Prerequisites Before you begin, you'll need: A KrosAI account ( sign up free ) An AI voice provider account (ElevenLabs, Vapi, or Retell) A phone to test calls 1 Create your account Go to cockpit.krosai.com Sign up with email or Google Complete KYC verification (required for phone numbers) - takes ~2 minutes KYC verification is required by telecom regulations before purchasing phone numbers. We use Sumsub for secure identity verification. 2 Create an API key Using the Dashboard Navigate to Developers → API Keys Click Create API Key Name it (e.g., "My First Key") Select scopes: numbers:read - View phone numbers numbers:write - Purchase/configure numbers calls:read - View call logs calls:write - Make outbound calls Click Create Copy and save your key - it's only shown once! Your API key will look like: kros_live_abc123... 3 Purchase a phone number TypeScript const response = await fetch('https://api.krosai.com/v1/phone-numbers', { method: 'POST', headers: { 'x-api-key': 'kros_live_your_key_here', 'Content-Type': 'application/json', }, body: JSON.stringify({ inventory_id: 'inv_ng_12345', // From GET /phone-numbers/available }), }); const { number, id } = await response.json(); console.log('Purchased:', number); // +2348012345678 Python import requests response = requests.post( 'https://api.krosai.com/v1/phone-numbers', headers={ 'x-api-key': 'kros_live_your_key_here', 'Content-Type': 'application/json', }, json={ 'inventory_id': 'inv_ng_12345', } ) data = response.json() print(f"Purchased: {data['number']}") CURL curl -X POST "https://api.krosai.com/v1/phone-numbers" \ -H "x-api-key: kros_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"inventory_id": "inv_ng_12345"}' Navigate to Phone Numbers → Buy Number Select your country (e.g., Nigeria, Kenya, UAE) Choose a number from the available inventory Click Purchase 4 Connect AI Agent Providers 5 Create an Endpoint TypeScript // Create a Vapi endpoint: const response = await fetch('https://api.krosai.com/v1/endpoints', { method: 'POST', headers: { 'x-api-key': 'kros_live_your_key_here', 'Content-Type': 'application/json', }, body: JSON.stringify({ name: 'My Support Agent', type: 'agent', url: 'sip:assistant@sip.vapi.ai', // Or your provider's SIP URI provider_config: { provider: 'vapi', assistant_id: 'asst_abc123', }, }), }); const { id: endpointId } = await response.json(); TypeScript // Create an ElevenLabs endpoint: const response = await fetch('https://api.krosai.com/v1/endpoints', { method: 'POST', headers: { 'x-api-key': 'kros_live_your_key_here', 'Content-Type': 'application/json', }, body: JSON.stringify({ name: 'ElevenLabs Agent', type: 'agent', url: 'sip:agent@sip.rtc.elevenlabs.io', provider_config: { provider: 'elevenlabs', agent_id: 'your-agent-id', }, }), }); Navigate to Endpoints → Create Endpoint Select your provider: ElevenLabs - Enter Agent ID Vapi - Enter Assistant ID Retell - Enter Agent ID Webhook - Enter your server URL Click Create 6 Attach endpoint to phone number TypeScript await fetch(`https://api.krosai.com/v1/phone-numbers/${phoneNumberId}`, { method: 'PATCH', headers: { 'x-api-key': 'kros_live_your_key_here', 'Content-Type': 'application/json', }, body: JSON.stringify({ endpoint_id: endpointId, allow_inbound: true, allow_outbound: true, }), }); 7 Make your first call Test inbound call Call your new phone number from any phone. Your AI agent will answer: Call: +234 801 234 5678 → Your AI agent answers and starts the conversation Make an outbound call TypeScript const response = await fetch('https://api.krosai.com/v1/outbound-calls', { method: 'POST', headers: { 'x-api-key': 'kros_live_your_key_here', 'Content-Type': 'application/json', }, body: JSON.stringify({ from_number: '+2348012345678', // Your KrosAI number to_number: '+14155551234', // Destination phone endpoint_id: endpointId, // Your AI agent }), }); const { call_id, status } = await response.json(); console.log('Call initiated:', call_id); Python response = requests.post( 'https://api.krosai.com/v1/outbound-calls', headers={ 'x-api-key': 'kros_live_your_key_here', 'Content-Type': 'application/json', }, json={ 'from_number': '+2348012345678', 'to_number': '+14155551234', 'endpoint_id': endpoint_id, } ) data = response.json() print(f"Call initiated: {data['call_id']}") Using the Playground The KrosAI Dashboard includes a Playground for testing calls without code: Go to Playground in the dashboard Select your phone number Enter a destination number Click Call Watch real-time call events and transcription Congratulations! You've successfully: Created a KrosAI account Purchased a phone number Connected an AI agent Made your first call Next steps Deep dive into integrations ElevenLabs Integration Voice cloning and natural conversations Vapi Integration Structured workflows and tool calling Retell Integration Low-latency enterprise deployments • [🔑Authentication](https://docs.krosai.com/getting-started/authentication.md): KrosAI uses API keys to authenticate requests. You can create and manage API keys in the Dashboard . API Key Authentication Include your API key in the x-api-key header of every request: TypeScript const response = await fetch('https://api.krosai.com/v1/phone-numbers', { headers: { 'x-api-key': 'kros_live_your_api_key_here', }, }); Python response = requests.get( 'https://api.krosai.com/v1/phone-numbers', headers={'x-api-key': 'kros_live_your_api_key_here'} ) CURL curl -X GET "https://api.krosai.com/v1/phone-numbers" \ -H "x-api-key: kros_live_your_api_key_here" API Key Format KrosAI API keys follow this format: Format kros_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx │ └── Environment: "live" for production kros_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx │ └── Environment: "live" for production All API keys are prefixed with kros_ for easy identification. Creating API Keys Via Dashboard 1 Create API key Go to Developers → API Keys 2 Click Create Click Create API Key 3 Name the key Enter a descriptive name 4 Select scopes Select the required scopes 5 Optional: IP restrictions (Optional) Add IP restrictions 6 Optional: expiration (Optional) Set expiration date 7 Finish Click Create Important: Copy your API key immediately after creation. For security, we only show the full key once. ' API Key Properties Property Description Name Descriptive name for identification Scopes Permissions granted to the key Allowed IPs Optional IP allowlist for extra security Expires At Optional expiration date Created At When the key was created Last Used Last time the key was used Scopes Scopes control what actions an API key can perform. Use the principle of least privilege—only grant scopes that are needed. Available Scopes Scope Description numbers:read View phone numbers numbers:write Purchase, configure, and release phone numbers endpoints:read View endpoints endpoints:write Create, update, and delete endpoints calls:read View call logs and recordings calls:write Initiate outbound calls, hangup calls webhooks:read View webhooks webhooks:write Create, update, and delete webhooks billing:read View balance and transactions billing:write Add credits, manage subscriptions api-keys:read View API keys api-keys:write Create, update, and revoke API keys voice:connect Use the Voice SDK to connect calls Scope Examples Read-only access for analytics — read-only.json Read-only.json { "scopes": ["calls:read", "numbers:read", "billing:read"] } Full access for server-side integrations — full-access.json Full-access.json { "scopes": [ "numbers:read", "numbers:write", "endpoints:read", "endpoints:write", "calls:read", "calls:write", "webhooks:read", "webhooks:write" ] } Voice SDK access only — voice-sdk.json Voice-sdk.json { "scopes": ["voice:connect", "calls:read"] } IP Restrictions For additional security, you can restrict API key usage to specific IP addresses: Allowed_ips.json { "allowed_ips": ["203.0.113.50", "198.51.100.0/24"] } Requests from non-allowed IPs will receive a 403 Forbidden response. Key Rotation We recommend rotating API keys regularly. To rotate a key: 1 Create new key Create a new API key with the same scopes 2 Update application Update your application to use the new key 3 Verify Verify the new key works correctly 4 Revoke old key Revoke the old key Bearer Token Authentication For browser-based applications using the KrosAI Dashboard, we also support Bearer token authentication using JWTs: CURL curl -X GET "https://api.krosai.com/v1/phone-numbers" \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." Bearer tokens are typically used for dashboard access. For server-side integrations, use API keys. Error Responses Invalid API Key JSON { "error": "Invalid API key", "code": "INVALID_API_KEY" } Missing API Key JSON { "error": "Missing API key", "code": "MISSING_API_KEY" } Insufficient Scope 403 Forbidden { "error": "API key lacks required scope: calls:write", "code": "INSUFFICIENT_SCOPE" } IP Not Allowed Plain text { "error": "Request from IP 192.168.1.1 not allowed", "code": "IP_NOT_ALLOWED" } { "error": "Request from IP 192.168.1.1 not allowed", "code": "IP_NOT_ALLOWED" } Key Expired JSON { "error": "API key has expired", "code": "KEY_EXPIRED" } • [📞Buy Numbers](https://docs.krosai.com/numbers/buy-numbers.md): The Phone Numbers API allows you to purchase, configure, and manage local phone numbers for your AI voice agents. List Phone Numbers Retrieve all phone numbers owned by your organization. Bash GET /phone-numbers Query Parameters Parameter Type Description status string Filter by status: active , suspended , pending country string Filter by country code (e.g., NG , KE ) limit integer Number of results (default: 50, max: 100) offset integer Pagination offset Request Bash curl -X GET "https://api.krosai.com/v1/phone-numbers?country=NG&limit=10" \ -H "x-api-key: kros_live_your_key" Response JSON { "phone_numbers": [ { "id": "pn_abc123", "number": "+2348012345678", "country": "NG", "type": "local", "status": "active", "endpoint_id": "ep_xyz789", "allow_inbound": true, "allow_outbound": true, "created_at": "2025-01-10T10:00:00Z", "updated_at": "2025-01-10T10:00:00Z" } ], "total": 1, "limit": 10, "offset": 0 } Get Phone Number Retrieve details for a specific phone number. Bash GET /phone-numbers/{id} Request Bash curl -X GET "https://api.krosai.com/v1/phone-numbers/pn_abc123" \ -H "x-api-key: kros_live_your_key" Response JSON { "id": "pn_abc123", "number": "+2348012345678", "country": "NG", "type": "local", "status": "active", "endpoint_id": "ep_xyz789", "endpoint": { "id": "ep_xyz789", "name": "Support Agent", "type": "agent", "provider": "elevenlabs" }, "allow_inbound": true, "allow_outbound": true, "monthly_cost_cents": 500, "created_at": "2025-01-10T10:00:00Z", "updated_at": "2025-01-10T10:00:00Z" } List Available Numbers Search for phone numbers available for purchase. Bash GET /phone-numbers/available Query Parameters Parameter Type Required Description country string Yes ISO country code (e.g., NG , KE , AE ) type string No Number type: local , mobile , toll_free area_code string No Specific area code limit integer No Number of results (default: 20) Request Bash curl -X GET "https://api.krosai.com/v1/phone-numbers/available?country=NG&type=local" \ -H "x-api-key: kros_live_your_key" Response JSON { "available_numbers": [ { "inventory_id": "inv_ng_001", "number": "+2348012345678", "country": "NG", "type": "local", "monthly_cost_cents": 500, "setup_cost_cents": 0, "capabilities": { "voice": true, "sms": false } }, { "inventory_id": "inv_ng_002", "number": "+2348012345679", "country": "NG", "type": "local", "monthly_cost_cents": 500, "setup_cost_cents": 0, "capabilities": { "voice": true, "sms": false } } ], "total": 2 } Purchase Phone Number Purchase an available phone number. Bash POST /phone-numbers Request Body Field Type Required Description inventory_id string Yes ID from available numbers list endpoint_id string No Endpoint to attach immediately allow_inbound boolean No Enable inbound calls (default: true) allow_outbound boolean No Enable outbound calls (default: true) Request Bash curl -X POST "https://api.krosai.com/v1/phone-numbers" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "inventory_id": "inv_ng_001", "endpoint_id": "ep_xyz789", "allow_inbound": true, "allow_outbound": true }' Response JSON { "id": "pn_abc123", "number": "+2348012345678", "country": "NG", "type": "local", "status": "active", "endpoint_id": "ep_xyz789", "allow_inbound": true, "allow_outbound": true, "monthly_cost_cents": 500, "created_at": "2025-01-10T10:00:00Z" } Error Responses Status Code Description 400 KYC_REQUIRED KYC verification not completed 400 KYC_PENDING KYC verification still pending 400 INSUFFICIENT_BALANCE Not enough credits 404 NUMBER_NOT_AVAILABLE Number no longer available Update Phone Number Update phone number configuration. Bash PATCH /phone-numbers/{id} Request Body Field Type Description endpoint_id string Endpoint ID to route calls to allow_inbound boolean Enable/disable inbound calls allow_outbound boolean Enable/disable outbound calls Request Bash curl -X PATCH "https://api.krosai.com/v1/phone-numbers/pn_abc123" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "endpoint_id": "ep_new456", "allow_inbound": true, "allow_outbound": false }' Response JSON { "id": "pn_abc123", "number": "+2348012345678", "endpoint_id": "ep_new456", "allow_inbound": true, "allow_outbound": false, "updated_at": "2025-01-10T11:00:00Z" } Release Phone Number Release a phone number. The number returns to the available pool. Bash DELETE /phone-numbers/{id} Request Bash curl -X DELETE "https://api.krosai.com/v1/phone-numbers/pn_abc123" \ -H "x-api-key: kros_live_your_key" Response JSON { "success": true, "message": "Phone number released successfully" } ⚠️ Warning: Releasing a number is immediate and cannot be undone. The number may be purchased by another customer. Phone Number Status Values Status Description active Number is operational suspended Number is temporarily suspended pending Number is being provisioned porting Number is being ported Code Examples TypeScript // List all phone numbers async function listPhoneNumbers() { const response = await fetch('https://api.krosai.com/v1/phone-numbers', { headers: { 'x-api-key': process.env.KROSAI_API_KEY }, }); return response.json(); } // Purchase a number async function purchaseNumber(inventoryId: string, endpointId?: string) { const response = await fetch('https://api.krosai.com/v1/phone-numbers', { method: 'POST', headers: { 'x-api-key': process.env.KROSAI_API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ inventory_id: inventoryId, endpoint_id: endpointId, }), }); if (!response.ok) { const error = await response.json(); throw new Error(error.error); } return response.json(); } // Update number configuration async function updateNumber(numberId: string, config: { endpoint_id?: string; allow_inbound?: boolean; allow_outbound?: boolean; }) { const response = await fetch( `https://api.krosai.com/v1/phone-numbers/${numberId}`, { method: 'PATCH', headers: { 'x-api-key': process.env.KROSAI_API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify(config), } ); return response.json(); } Python import requests import os API_KEY = os.environ.get('KROSAI_API_KEY') BASE_URL = 'https://api.krosai.com/v1' def list_phone_numbers(country=None): params = {} if country: params['country'] = country response = requests.get( f'{BASE_URL}/phone-numbers', headers={'x-api-key': API_KEY}, params=params ) return response.json() def purchase_number(inventory_id, endpoint_id=None): payload = {'inventory_id': inventory_id} if endpoint_id: payload['endpoint_id'] = endpoint_id response = requests.post( f'{BASE_URL}/phone-numbers', headers={ 'x-api-key': API_KEY, 'Content-Type': 'application/json' }, json=payload ) if not response.ok: raise Exception(response.json().get('error')) return response.json() def update_number(number_id, **config): response = requests.patch( f'{BASE_URL}/phone-numbers/{number_id}', headers={ 'x-api-key': API_KEY, 'Content-Type': 'application/json' }, json=config ) return response.json() Next Steps Create an Endpoint to route calls Make Outbound Calls View Call Logs • [🏴󠁧󠁢󠁳󠁣󠁴󠁿Countries](https://docs.krosai.com/numbers/countries.md): KrosAI provides local phone numbers in markets underserved by traditional providers like Twilio and Vonage. We focus on Africa and the Middle East, where we have direct carrier relationships. Coverage Map Region Countries Status West Africa Nigeria, Ghana ✅ Available East Africa Kenya, Rwanda ✅ Available Southern Africa South Africa ✅ Available North Africa Egypt ✅ Available Middle East UAE ✅ Available Africa Nigeria 🇳🇬 Property Details Number Types Local, Mobile Monthly Cost $5.00 Per-Minute Rate $0.04 (inbound), $0.06 (outbound) Area Codes Lagos (01), Abuja (09), Port Harcourt (084) KYC Required Yes - Government ID + Proof of Address Approval Time 24-48 hours Porting Available Yes Ghana 🇬🇭 Property Details Number Types Local, Mobile Monthly Cost $5.00 Per-Minute Rate $0.05 (inbound), $0.07 (outbound) Area Codes Accra (030), Kumasi (032) KYC Required Yes - Government ID Approval Time 24 hours Porting Available Yes Kenya 🇰🇪 Property Details Number Types Local, Mobile Monthly Cost $6.00 Per-Minute Rate $0.04 (inbound), $0.06 (outbound) Area Codes Nairobi (020), Mombasa (041) KYC Required Yes - Government ID Approval Time 24 hours Porting Available Yes South Africa 🇿🇦 Property Details Number Types Local, Mobile, Toll-Free Monthly Cost $4.00 Per-Minute Rate $0.03 (inbound), $0.05 (outbound) Area Codes Johannesburg (011), Cape Town (021), Durban (031) KYC Required Yes - RICA compliance Approval Time 48 hours Porting Available Yes Rwanda 🇷🇼 Property Details Number Types Local Monthly Cost $7.00 Per-Minute Rate $0.06 (inbound), $0.08 (outbound) Area Codes Kigali (250) KYC Required Yes - Government ID Approval Time 24 hours Porting Available Limited Egypt 🇪🇬 Property Details Number Types Local Monthly Cost $6.00 Per-Minute Rate $0.05 (inbound), $0.07 (outbound) Area Codes Cairo (02), Alexandria (03) KYC Required Yes - Government ID Approval Time 48-72 hours Porting Available Yes Middle East United Arab Emirates 🇦🇪 Property Details Number Types Local, Toll-Free Monthly Cost $10.00 Per-Minute Rate $0.08 (inbound), $0.12 (outbound) Area Codes Dubai (04), Abu Dhabi (02) KYC Required Yes - Business License required Approval Time 3-5 business days Porting Available Yes Coming Soon We're actively expanding coverage. These markets are in development: Country Flag Expected Availability Morocco 🇲🇦 Q1 2025 Tunisia 🇹🇳 Q1 2025 Senegal 🇸🇳 Q2 2025 Ivory Coast 🇨🇮 Q2 2025 Tanzania 🇹🇿 Q2 2025 Uganda 🇺🇬 Q2 2025 Saudi Arabia 🇸🇦 Q2 2025 Qatar 🇶🇦 Q3 202 Info: Need a country not listed? Contact us - we're actively expanding and can prioritize based on demand. Number Types Local Numbers Standard geographic numbers tied to a specific city or region. Best for building local presence. Mobile Numbers Mobile-format numbers that work across the country. Often preferred for SMS-capable services. Toll-Free Numbers Free for callers. Available in select markets (South Africa, UAE). Higher monthly cost. Compliance Requirements Each country has specific regulatory requirements for phone number ownership: Country Requirements Documents Needed Nigeria Personal or Business Government ID + Utility Bill Ghana Personal or Business Government ID Kenya Personal or Business Government ID South Africa RICA Registration Government ID + Proof of Address Rwanda Personal or Business Government ID Egypt Personal or Business Government ID UAE Business Only Trade License + Emirates ID KYC Process 1 Initiate KYC Start verification in the Dashboard. 2 Submit Documents Upload required identity documents. 3 Verification Our team reviews (powered by Sumsub). 4 Approval Once approved, you can purchase numbers. Info: Note: KYC approval is account-wide. Once verified, you can purchase numbers in any supported country. Pricing Summary Country Monthly Inbound/min Outbound/min Nigeria $5.00 $0.04 $0.06 Ghana $5.00 $0.05 $0.07 Kenya $6.00 $0.04 $0.06 South Africa $4.00 $0.03 $0.05 Rwanda $7.00 $0.06 $0.08 Egypt $6.00 $0.05 $0.07 UAE $10.00 $0.08 $0.12 • [☎️Vapi](https://docs.krosai.com/integration-1/vapi.md): Connect your Vapi AI assistants to KrosAI phone numbers for emerging market coverage. Overview Vapi is an AI voice assistant platform. With KrosAI, you can route calls from your African and Middle Eastern phone numbers to Vapi assistants. Prerequisites KrosAI account with verified KYC At least one KrosAI phone number Vapi account with an assistant created Setup Steps ' 1 Configure SIP Trunk in Vapi On your Vapi Dashboard, navigate to Integrations Search for SIP Trunk and click on it Click Configure New SIP Trunk On KrosAI Dashboard, open and copy the SIP credentials of your phone number Fill the New SIP Trunk form in Vapi with your KrosAI phone number SIP credentials Note: Use the SIP credential SIP IP Address instead of the SIP Domain Save the SIP Trunk 2 BYO KrosAI Phone Number to Vapi Open Phone Number on Vapi Dashboard Click Create Phone Number Select BYO SIP Trunk Number Enter your KrosAI number with country code in the Phone Number field On the SIP Trunk Credential dropdown, select the SIP Trunk you just created Click Import SIP Phone Number 3 Get Your Vapi Assistant ID On your Vapi Dashboard, navigate to Assistants Select your assistant Copy the Assistant ID 4 Connect Vapi in KrosAI Go to Settings → Integrations in your KrosAI Dashboard Click Connect next to Vapi Enter your Vapi API Key Click Save & Test 5 Create Endpoint and Attach Phone Number On your KrosAI Dashboard, click Endpoints Click Add Endpoint Enter a Name Select Vapi as your AI agent provider Enter the Vapi Assistant ID Enter your Vapi SIP Trunk Credential ID Select the phone number to attach Finally, click Create Endpoint 6 Make Your First Calls 🎉 Congratulations! You’ve successfully connected your local phone number to your AI agent. Call the number to start a conversation with your agent. Call Not Connecting Verify your Vapi API key is correct Check the assistant ID exists Ensure the assistant is active in Vapi Review KrosAI Dashboard → Calls for error details Audio Issues Check your Vapi assistant's voice settings Verify SIP connectivity in Vapi Dashboard Review call events for media errors Assistant Not Responding Test the assistant directly in Vapi Check for LLM errors in Vapi logs Verify function calling permissions • [📲Retell](https://docs.krosai.com/integration-1/retell.md): Connect your Retell AI agents to KrosAI phone numbers for emerging market coverage. Overview Retell AI provides voice agents with natural conversation capabilities. KrosAI enables routing calls from African and Middle Eastern phone numbers to Retell agents. Prerequisites KrosAI account with verified KYC Retell account with an agent created At least one KrosAI phone number Setup Steps ' 1 Get Your Retell Agent ID Log into your Retell Dashboard Navigate to Agents Select your agent Copy the Agent ID 2 Connect Retell in KrosAI Go to Settings → Integrations in your KrosAI Dashboard Click Connect next to Retell Enter your Retell API Key Click Save & 3 Create a Retell Endpoint Bash curl -X POST "https://api.krosai.com/v1/endpoints" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Retell Booking Agent", "type": "agent", "url": "sip:agent@retell.ai", "provider_config": { "provider": "retell", "agent_id": "your-retell-agent-id" } }' 4 Attach to Phone Number Bash curl -X PATCH "https://api.krosai.com/v1/phone-numbers/pn_abc123" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "endpoint_id": "ep_retell_xyz" }' Configuration Options Provider Config Fields ' Fiels Required Description agent_id Yes Your Retell agent ID retell_phone_number No Retell phone number for outbound (optional) Outbound Calls CURL curl -X POST "https://api.krosai.com/v1/outbound-calls" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "from_number": "+2348012345678", "to_number": "+14155551234", "endpoint_id": "ep_retell_xyz", "metadata": { "appointment_id": "apt_123" } }' Dynamic Variables Pass dynamic data to your Retell agent: CURL curl -X POST "https://api.krosai.com/v1/outbound-calls" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "from_number": "+2348012345678", "to_number": "+14155551234", "endpoint_id": "ep_retell_xyz", "metadata": { "retell_dynamic_variables": { "customer_name": "John Smith", "appointment_time": "2:00 PM", "location": "Lagos Office" } } }' Webhooks Receive call events including Retell-specific data: JSON { "event": "call.completed", "call_id": "call_abc123", "direction": "outbound", "from_number": "+2348012345678", "to_number": "+14155551234", "duration": 245, "provider": "retell", "agent_id": "agent_123", "transcript": "[Agent]: Hello! I'm calling to confirm your appointment...", "call_analysis": { "sentiment": "positive", "outcome": "confirmed" } } ' Call Not Connecting Verify your Retell API key is valid Check the agent ID exists in Retell Ensure your Retell account has sufficient credits Review call events in the KrosAI Dashboard Audio Quality Issues Check network connectivity Review Retell's voice settings Verify audio codec compatibility (Opus recommended) Agent Not Following Script Test the agent directly in Retell Check your prompt configuration Verify custom LLM settings • [☏ Elevenlabs](https://docs.krosai.com/integration-1/elevenlabs.md): Connect your ElevenLabs Conversational AI agents to KrosAI phone numbers for emerging market coverage. Overview ElevenLabs offers state-of-the-art voice synthesis and conversational AI. With KrosAI, you can route calls from African and Middle Eastern phone numbers to ElevenLabs agents. Prerequisites KrosAI account with verified KYC ElevenLabs account with Conversational AI enabled An ElevenLabs agent created At least one KrosAI phone number Setup Steps ' 1 Import Your KrosAI Phone Number to ElevenLabs Log into your ElevenLabs Dashboard Switch to ElevenAgents if you are not in agents Open Phone Number on the sidebar Click Import Number and select From SIP Trunk Enter the Label for the number Enter the number in the Phone Number field On your KrosAI Phone Number details page, copy the SIP Credentials Enter the SIP credentials in the ElevenLabs Outbound Configuration Click Import 2 Get Your ElevenLabs Agent ID Click on Agents in the sidebar Select your agent Copy the Agent ID from the configuration panel 3 Connect ElevenLabs in KrosAI 4 Create an ElevenLabs Endpoint On your KrosAI dashboard, go to Endpoints Click Add Endpoint Enter a Name Select ElevenLabs as your AI agent provider Enter the ElevenLabs Assistant ID Select the phone number to attach Finally, click Create Endpoint 5 Make Your First Calls 🎉 Congratulations! You’ve successfully connected your local phone number to your AI agent. Call the number to start a conversation with your agent. • [✆Vogent](https://docs.krosai.com/integration-1/vogent.md): Connect your Vogent AI self-improving voice agents to KrosAI phone numbers for emerging market coverage. Overview Vogent offers AI voice agents that learn and improve from every conversation. With KrosAI, you can route calls from African and Middle Eastern phone numbers to Vogent agents with ultra-low latency. Key Features Self-Improving Agents: Vogent agents learn from past conversations Ultra-Low Latency: Sub-1-second response times Custom Voice Cloning: Use your own voice Evaluation Suite: Built-in testing and quality monitoring Prerequisites KrosAI account with verified KYC Vogent account with an active agent At least one KrosAI phone number Setup Steps 1 Create Vogent SIP URI Log into your Vogent Dashboard Navigate to Call Settings Click on Add Phone Number Select the Vogent SIP tab Enter details and create your SIP URI 2 Link Vogent SIP URI to Agent Navigate to Agents on your Vogent Dashboard Select your Agent Open the Number tab Click Link Number Select your Vogent SIP URI Save 3 Connect Vogent in KrosAI Go to Settings → Integrations in your KrosAI Dashboard Click Connect next to Vogent Enter your Vogent API Key Click Save & Test 4 Get Your Vogent Agent ID Navigate to Agents on your Vogent Dashboard Select your agent Copy the Agent ID 5 Create a Vogent Endpoint On your KrosAI dashboard, navigate to Endpoints Click Add Endpoint Enter a name for the endpoint Provide the SIP prefix of the Vogent SIP URI you created in Step 1 Enter the Vogent SIP URI username and password (Optional) Enter the Vogent Agent ID Select the phone number you want to attach to this endpoint Finally, click Create Endpoint 6 Make Your First Calls 🎉 Congratulations! You’ve successfully connected your local phone number to your AI agent. Call the number to start a conversation with your agent. • [🔌Livekit](https://docs.krosai.com/integration-1/livekit.md): Connect your LiveKit real-time voice agents to KrosAI phone numbers for emerging market coverage. Overview LiveKit is an open-source platform for building real-time audio/video applications. With KrosAI, you can bridge LiveKit agents to phone calls in Africa and the Middle East. Prerequisites KrosAI account with verified KYC LiveKit Cloud account or self-hosted instance A LiveKit agent configured and running SIP Trunk configured in LiveKit At least one KrosAI phone number Setup Steps ' 1 Configure LiveKit SIP Trunk Log into the LiveKit Dashboard Navigate to SIP → Trunks Create or select a SIP Trunk Copy: Agent ID (your agent's name/ID) SIP Trunk ID SIP URI (e.g., sip:xxxxx.sip.livekit.cloud ) 2 2. Connect LiveKit in KrosAI Go to Settings → Integrations in your KrosAI Dashboard Click Connect next to LiveKit Enter: API Key (from LiveKit) API Secret Server URL (WebSocket URL, e.g., wss://your-app.livekit.cloud ) Click Save & Test 3 Create a LiveKit Endpoint Bash curl -X POST "https://api.krosai.com/v1/endpoints" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "name": "LiveKit Voice Agent", "type": "agent", "url": "sip:xxxxx.sip.livekit.cloud", "provider_config": { "provider": "livekit", "livekit_agent_name": "my-voice-agent", "livekit_sip_trunk_id": "trunk_abc123", "livekit_sip_uri": "sip:xxxxx.sip.livekit.cloud" } }' 4 4. Attach to Phone Number Bash curl -X PATCH "https://api.krosai.com/v1/phone-numbers/pn_abc123" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "endpoint_id": "ep_livekit_xyz" }' Configuration Options Provider Config Fields Field Required Description livekit_agent_name Yes Your LiveKit agent ID for dispatch livekit_sip_trunk_id Yes Your LiveKit SIP Trunk ID livekit_sip_uri Yes Full SIP URI from LiveKit Global Settings (Integration Level) Field Required Description api_key Yes LiveKit API Key api_secret Yes LiveKit API Secret server_url Yes WebSocket URL (wss://...) Agent Verification Important: Agent verification behavior LiveKit agents are ephemeral worker processes. They cannot be verified via API before a call. Verification happens at call-time dispatch. Ensure your agent is: Running and connected to LiveKit Registered with the correct Agent ID Ready to handle SIP calls Outbound Calls Bash curl -X POST "https://api.krosai.com/v1/outbound-calls" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "from_number": "+2348012345678", "to_number": "+14155551234", "endpoint_id": "ep_livekit_xyz" }' Webhooks Receive call events: Bash { "event": "call.completed", "call_id": "call_abc123", "direction": "inbound", "from_number": "+14155551234", "to_number": "+2348012345678", "duration": 180, "provider": "livekit", "agent_name": "my-voice-agent" } Troubleshooting Call Not Connecting Verify SIP Trunk is configured in LiveKit Check the SIP URI is correct Ensure your agent is running Review LiveKit logs for SIP errors Agent Not Dispatching Confirm agent is registered with correct ID Check LiveKit worker is connected Verify room permissions in LiveKit Audio Issues Check codec compatibility (Opus preferred) Verify SIP trunk audio settings Review network latency LiveKit Agent Example Python # Python LiveKit Agent Example from livekit.agents import AutoSubscribe, JobContext, WorkerOptions, cli from livekit.agents.voice_assistant import VoiceAssistant from livekit.plugins import openai, silero async def entrypoint(ctx: JobContext): await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY) assistant = VoiceAssistant( vad=silero.VAD.load(), stt=openai.STT(), llm=openai.LLM(), tts=openai.TTS(), ) assistant.start(ctx.room) await assistant.say("Hello! How can I help you today?") if __name__ == "__main__": cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint)) • [📱Outbound Calls](https://docs.krosai.com/voice/outbound-calls.md): The Outbound Calls API allows you to programmatically initiate phone calls from your AI agents to any phone number. Base URL: https://api.krosai.com/v1/outbound-calls Initiate Outbound Call Start a new outbound call from your KrosAI phone number to a destination. Endpoint POST /outbound-calls Request Body Field Type Required Description from_number string Yes Your KrosAI phone number (E.164 format) to_number string Yes Destination phone number (E.164 format) endpoint_id string Yes The endpoint (AI agent) to handle the call metadata object No Custom metadata to attach to the call webhook_url string No Override webhook URL for this call max_duration integer No Maximum call duration in seconds Request CURL curl -X POST "https://api.krosai.com/v1/outbound-calls" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "from_number": "+2348012345678", "to_number": "+14155551234", "endpoint_id": "ep_abc123", "metadata": { "customer_id": "cust_xyz", "campaign": "follow-up-q1" } }' Response JSON { "call_id": "call_xyz789", "status": "initiated", "from_number": "+2348012345678", "to_number": "+14155551234", "endpoint_id": "ep_abc123", "created_at": "2025-01-10T12:00:00Z" } Phone Number Format All phone numbers must be in E.164 format : Title Description Title Format Example Valid E.164 +14155551234 ✅ E.164 +2348012345678 ✅ Local 08012345678 ❌ Formatted (415) 555-1234 ❌ Note: The from_number must be a phone number owned by your organization. Call Lifecycle When you initiate an outbound call, it goes through these stages: initiated → ringing → answered → in_progress → completed Possible failure outcomes include failed , no_answer , and busy . Status Values Status Description initiated Call request accepted, setting up ringing Destination phone is ringing answered Destination answered in_progress Call is active with AI agent completed Call ended normally failed Call failed to connect no_answer Destination didn't answer busy Destination was busy Metadata Attach custom metadata to calls for tracking and analytics: Metadata is: JSON { "from_number": "+2348012345678", "to_number": "+14155551234", "endpoint_id": "ep_abc123", "metadata": { "customer_id": "cust_123", "campaign_id": "camp_456", "lead_source": "website", "custom_field": "any value" } } Metadata is: Included in webhook payloads Searchable in call logs Available in analytics exports Maximum Duration Set a maximum call duration to prevent unexpectedly long calls: JSON { "from_number": "+2348012345678", "to_number": "+14155551234", "endpoint_id": "ep_abc123", "max_duration": 600 } When the limit is reached, the call is automatically terminated. Error Responses Status Code Description 400 INVALID_PHONE_NUMBER Invalid E.164 format 400 NUMBER_NOT_OWNED from_number not in your inventory 400 OUTBOUND_DISABLED Outbound calls disabled for this number 400 INSUFFICIENT_BALANCE Not enough credits 404 ENDPOINT_NOT_FOUND Invalid endpoint_id 429 RATE_LIMIT_EXCEEDED Too many concurrent calls Error Response Format JSON { "from_number": "+2348012345678", "to_number": "+14155551234", "endpoint_id": "ep_abc123", "metadata": { "customer_id": "cust_123", "campaign_id": "camp_456", "lead_source": "website", "custom_field": "any value" } } Concurrent Call Limits ' Plan Concurrent Outbound Calls Free 1 Pro 10 Business 15 Enterprise Unlimited Code Examples TypeScript interface OutboundCallOptions { fromNumber: string; toNumber: string; endpointId: string; metadata?: Record<string, string>; maxDuration?: number; } async function initiateOutboundCall(options: OutboundCallOptions) { const response = await fetch('https://api.krosai.com/v1/outbound-calls', { method: 'POST', headers: { 'x-api-key': process.env.KROSAI_API_KEY!, 'Content-Type': 'application/json', }, body: JSON.stringify({ from_number: options.fromNumber, to_number: options.toNumber, endpoint_id: options.endpointId, metadata: options.metadata, max_duration: options.maxDuration, }), }); if (!response.ok) { const error = await response.json(); throw new Error(`Call failed: ${error.code} - ${error.error}`); } return response.json(); } // Usage const call = await initiateOutboundCall({ fromNumber: '+2348012345678', toNumber: '+14155551234', endpointId: 'ep_abc123', metadata: { customer_id: 'cust_123', campaign: 'welcome-series', }, maxDuration: 300, // 5 minutes max }); console.log(`Call initiated: ${call.call_id}`); Python import requests import os def initiate_outbound_call( from_number: str, to_number: str, endpoint_id: str, metadata: dict = None, max_duration: int = None ): payload = { 'from_number': from_number, 'to_number': to_number, 'endpoint_id': endpoint_id } if metadata: payload['metadata'] = metadata if max_duration: payload['max_duration'] = max_duration response = requests.post( 'https://api.krosai.com/v1/outbound-calls', headers={ 'x-api-key': os.environ['KROSAI_API_KEY'], 'Content-Type': 'application/json' }, json=payload ) if not response.ok: error = response.json() raise Exception(f"Call failed: {error['code']} - {error['error']}") return response.json() # Usage call = initiate_outbound_call( from_number='+2348012345678', to_number='+14155551234', endpoint_id='ep_abc123', metadata={ 'customer_id': 'cust_123', 'campaign': 'welcome-series' } ) print(f"Call initiated: {call['call_id']}") TSX interface Contact { phone: string; customerId: string; } async function runCampaign( contacts: Contact[], fromNumber: string, endpointId: string ) { const results = []; for (const contact of contacts) { try { const call = await initiateOutboundCall({ fromNumber, toNumber: contact.phone, endpointId, metadata: { customer_id: contact.customerId, campaign: 'batch-outreach', }, }); results.push({ success: true, callId: call.call_id, contact }); // Respect rate limits - wait between calls await new Promise(r => setTimeout(r, 1000)); } catch (error) { results.push({ success: false, error: error.message, contact }); } } return results; } Webhook Integration Receive real-time updates about your outbound calls: JSON { "error": "Phone number format is invalid. Use E.164 format (+14155551234)", "code": "INVALID_PHONE_NUMBER", "details": { "field": "to_number", "value": "4155551234" } } → Set up Webhooks Best Practices Do's ✅ Validate phone numbers before calling Use metadata to track campaign performance Set max_duration to prevent runaway calls Handle errors gracefully Respect rate limits in batch operations Test with small batches first Don'ts ❌ Don't hardcode phone numbers in source code Don't exceed concurrent limits — queue calls instead Don't ignore webhook failures — implement retries Don't call without consent — follow local regulations Compliance Notes When making outbound calls, ensure compliance with: TCPA (US) - Prior consent required GDPR (EU) - Data protection requirements Local regulations - Check destination country laws KrosAI provides the infrastructure; you're responsible for compliance. • [🔗Endpoints](https://docs.krosai.com/voice/endpoints.md): Endpoints define where inbound calls are routed. They can point to AI voice providers (ElevenLabs, Vapi, Retell) or custom webhook URLs. Base URL: https://api.krosai.com/v1/endpoints Endpoint Types Type Description Use Case agent AI voice provider ElevenLabs, Vapi, Retell, LiveKit webhook HTTP webhook Custom server handling List Endpoints Retrieve all endpoints for your organization. Endpoint GET /endpoints Query Parameters Parameter Type Description type string Filter by type: agent , webhook status string Filter by status: active , inactive limit integer Number of results (default: 50) offset integer Pagination offset Request CURL curl -X GET "https://api.krosai.com/v1/endpoints" \ -H "x-api-key: kros_live_your_key" Response JSON { "endpoints": [ { "id": "ep_abc123", "name": "Customer Support Agent", "type": "agent", "url": "sip:agent@sip.rtc.elevenlabs.io", "status": "active", "provider_config": { "provider": "elevenlabs", "agent_id": "agent_xyz" }, "created_at": "2025-01-10T10:00:00Z", "updated_at": "2025-01-10T10:00:00Z" }, { "id": "ep_def456", "name": "Custom Handler", "type": "webhook", "url": "https://api.yourapp.com/call-handler", "status": "active", "secret": "whsec_...", "created_at": "2025-01-09T15:00:00Z", "updated_at": "2025-01-09T15:00:00Z" } ], "total": 2 } Get Endpoint Retrieve details for a specific endpoint. Endpoint GET /endpoints/{id} Request CURL curl -X GET "https://api.krosai.com/v1/endpoints/ep_abc123" \ -H "x-api-key: kros_live_your_key" Response JSON { "id": "ep_abc123", "name": "Customer Support Agent", "type": "agent", "url": "sip:agent@sip.rtc.elevenlabs.io", "status": "active", "provider_config": { "provider": "elevenlabs", "agent_id": "agent_xyz" }, "phone_numbers": [ { "id": "pn_123", "number": "+2348012345678" } ], "call_count_24h": 45, "created_at": "2025-01-10T10:00:00Z", "updated_at": "2025-01-10T10:00:00Z" } Create Endpoint Create a new endpoint for call routing. Endpoint POST /endpoints Request Body Field Type Required Description name string Yes Descriptive name type string Yes agent or webhook url string Yes SIP URI or webhook URL provider_config object For agents Provider-specific configuration Agent Endpoint (ElevenLabs) CURL curl -X POST "https://api.krosai.com/v1/endpoints" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "name": "ElevenLabs Support Agent", "type": "agent", "url": "sip:agent@sip.rtc.elevenlabs.io", "provider_config": { "provider": "elevenlabs", "agent_id": "your-elevenlabs-agent-id" } }' Agent Endpoint (Vapi) CURL curl -X POST "https://api.krosai.com/v1/endpoints" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Vapi Sales Assistant", "type": "agent", "url": "sip:assistant@sip.vapi.ai", "provider_config": { "provider": "vapi", "assistant_id": "your-vapi-assistant-id" } }' Agent Endpoint (Retell) CURL curl -X POST "https://api.krosai.com/v1/endpoints" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Retell Booking Agent", "type": "agent", "url": "sip:agent@retell.ai", "provider_config": { "provider": "retell", "agent_id": "your-retell-agent-id" } }' Webhook Endpoint CURL curl -X POST "https://api.krosai.com/v1/endpoints" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Custom Call Handler", "type": "webhook", "url": "https://api.yourapp.com/inbound-call" }' Response JSON { "id": "ep_new789", "name": "ElevenLabs Support Agent", "type": "agent", "url": "sip:agent@sip.rtc.elevenlabs.io", "status": "active", "provider_config": { "provider": "elevenlabs", "agent_id": "your-elevenlabs-agent-id" }, "secret": "whsec_abc123...", "created_at": "2025-01-10T12:00:00Z" } Note: For webhook endpoints, a signing secret is automatically generated. Use this to verify webhook payloads. Update Endpoint Update an existing endpoint. Endpoint PATCH /endpoints/{id} Request Body Field Type Description name string New name url string New SIP URI or webhook URL status string active or inactive provider_config object Updated provider configuration Request CURL curl -X PATCH "https://api.krosai.com/v1/endpoints/ep_abc123" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "name": "Updated Support Agent", "status": "active" }' Response JSON { "id": "ep_abc123", "name": "Updated Support Agent", "status": "active", "updated_at": "2025-01-10T13:00:00Z" } Delete Endpoint Delete an endpoint. Phone numbers attached to this endpoint will need to be reconfigured. Endpoint DELETE /endpoints/{id} Request CURL curl -X DELETE "https://api.krosai.com/v1/endpoints/ep_abc123" \ -H "x-api-key: kros_live_your_key" Response JSON { "success": true, "message": "Endpoint deleted successfully" } Warning: Deleting an endpoint will cause any attached phone numbers to stop receiving calls until a new endpoint is assigned. Provider Configuration ElevenLabs JSON { "provider": "elevenlabs", "agent_id": "your-agent-id" } The agent_id is found in your ElevenLabs Conversational AI dashboard. Vapi JSON { "provider": "vapi", "assistant_id": "your-assistant-id" } Retell JSON { "provider": "retell", "agent_id": "your-agent-id" } LiveKit JSON { "provider": "livekit", "livekit_agent_name": "my-voice-agent", "livekit_sip_trunk_id": "trunk-id", "livekit_sip_uri": "sip:xxxxx.sip.livekit.cloud" } Webhook Payload When using webhook endpoints, KrosAI sends HTTP POST requests with call information: JSON { "event": "call.incoming", "call_id": "call_xyz789", "from_number": "+14155551234", "to_number": "+2348012345678", "timestamp": "2025-01-10T12:00:00Z", "metadata": {} } Verifying Webhook Signatures TypeScript import crypto from 'crypto'; function verifySignature(payload: string, signature: string, secret: string): boolean { const expected = crypto .createHmac('sha256', secret) .update(payload, 'utf8') .digest('hex'); return crypto.timingSafeEqual( Buffer.from(`sha256=${expected}`), Buffer.from(signature) ); } Code Examples TypeScript TypeScript // Create an ElevenLabs endpoint async function createElevenLabsEndpoint(name: string, agentId: string) { const response = await fetch('https://api.krosai.com/v1/endpoints', { method: 'POST', headers: { 'x-api-key': process.env.KROSAI_API_KEY!, 'Content-Type': 'application/json', }, body: JSON.stringify({ name, type: 'agent', url: 'sip:agent@sip.rtc.elevenlabs.io', provider_config: { provider: 'elevenlabs', agent_id: agentId, }, }), }); return response.json(); } // Create a webhook endpoint async function createWebhookEndpoint(name: string, webhookUrl: string) { const response = await fetch('https://api.krosai.com/v1/endpoints', { method: 'POST', headers: { 'x-api-key': process.env.KROSAI_API_KEY!, 'Content-Type': 'application/json', }, body: JSON.stringify({ name, type: 'webhook', url: webhookUrl, }), }); const data = await response.json(); // Save data.secret for webhook verification return data; } Python Python import requests import os def create_endpoint(name, endpoint_type, url, provider_config=None): payload = { 'name': name, 'type': endpoint_type, 'url': url } if provider_config: payload['provider_config'] = provider_config response = requests.post( 'https://api.krosai.com/v1/endpoints', headers={ 'x-api-key': os.environ['KROSAI_API_KEY'], 'Content-Type': 'application/json' }, json=payload ) return response.json() # Create ElevenLabs endpoint endpoint = create_endpoint( name='Support Agent', endpoint_type='agent', url='sip:agent@sip.rtc.elevenlabs.io', provider_config={ 'provider': 'elevenlabs', 'agent_id': 'your-agent-id' } ) • [☎Call logs](https://docs.krosai.com/voice/call-logs.md): The Calls API provides access to call history, recordings, transcripts, and real-time call events. Base URL: https://api.krosai.com/v1/calls List Calls Retrieve call history with filtering and pagination. Endpoint GET /calls Query Parameters Title Description Title Parameter Type Description status string Filter by status: completed , failed , in_progress direction string Filter by direction: inbound , outbound phone_number_id string Filter by phone number endpoint_id string Filter by endpoint from_date string Start date (ISO 8601) to_date string End date (ISO 8601) limit integer Results per page (default: 50, max: 100) offset integer Pagination offset Request curl -X GET "https://api.krosai.com/v1/calls?limit=10&status=completed" \ -H "x-api-key: kros_live_your_key" Response Plain text { "calls": [ { "id": "call_abc123", "from_number": "+14155551234", "to_number": "+2348012345678", "direction": "inbound", "status": "completed", "duration": 180, "cost_cents": 12, "endpoint_id": "ep_xyz789", "phone_number_id": "pn_123", "recording_url": "https://storage.krosai.com/recordings/call_abc123.mp3", "transcript": "Hello, how can I help you today?...", "created_at": "2025-01-10T10:00:00Z", "answered_at": "2025-01-10T10:00:05Z", "completed_at": "2025-01-10T10:03:05Z" } ], "total": 156, "limit": 10, "offset": 0 } { "calls": [ { "id": "call_abc123", "from_number": "+14155551234", "to_number": "+2348012345678", "direction": "inbound", "status": "completed", "duration": 180, "cost_cents": 12, "endpoint_id": "ep_xyz789", "phone_number_id": "pn_123", "recording_url": "https://storage.krosai.com/recordings/call_abc123.mp3", "transcript": "Hello, how can I help you today?...", "created_at": "2025-01-10T10:00:00Z", "answered_at": "2025-01-10T10:00:05Z", "completed_at": "2025-01-10T10:03:05Z" } ], "total": 156, "limit": 10, "offset": 0 } Get Call Retrieve detailed information about a specific call. Endpoint Plain text GET /calls/{id} GET /calls/{id} Request Plain text curl -X GET "https://api.krosai.com/v1/calls/call_abc123" \ -H "x-api-key: kros_live_your_key" curl -X GET "https://api.krosai.com/v1/calls/call_abc123" \ -H "x-api-key: kros_live_your_key" Response Plain text { "id": "call_abc123", "from_number": "+14155551234", "to_number": "+2348012345678", "direction": "inbound", "status": "completed", "duration": 180, "cost_cents": 12, "endpoint": { "id": "ep_xyz789", "name": "Support Agent", "provider": "elevenlabs" }, "phone_number": { "id": "pn_123", "number": "+2348012345678" }, "recording_url": "https://storage.krosai.com/recordings/call_abc123.mp3", "transcript": "Hello, how can I help you today? I'm looking for information about...", "quality_metrics": { "latency_ms": 120, "audio_codec": "opus", "packet_loss": 0.01 }, "hangup_cause": "normal_clearing", "created_at": "2025-01-10T10:00:00Z", "answered_at": "2025-01-10T10:00:05Z", "completed_at": "2025-01-10T10:03:05Z" } { "id": "call_abc123", "from_number": "+14155551234", "to_number": "+2348012345678", "direction": "inbound", "status": "completed", "duration": 180, "cost_cents": 12, "endpoint": { "id": "ep_xyz789", "name": "Support Agent", "provider": "elevenlabs" }, "phone_number": { "id": "pn_123", "number": "+2348012345678" }, "recording_url": "https://storage.krosai.com/recordings/call_abc123.mp3", "transcript": "Hello, how can I help you today? I'm looking for information about...", "quality_metrics": { "latency_ms": 120, "audio_codec": "opus", "packet_loss": 0.01 }, "hangup_cause": "normal_clearing", "created_at": "2025-01-10T10:00:00Z", "answered_at": "2025-01-10T10:00:05Z", "completed_at": "2025-01-10T10:03:05Z" } Get Call Statistics Get aggregated statistics for calls. Endpoint Plain text GET /calls/stats GET /calls/stats Query Parameters Parameter Type Description phone_number_id string Filter by phone number endpoint_id string Filter by endpoint from_date string Start date (ISO 8601) to_date string End date (ISO 8601) Request Plain text curl -X GET "https://api.krosai.com/v1/calls/stats?from_date=2025-01-01" \ -H "x-api-key: kros_live_your_key" curl -X GET "https://api.krosai.com/v1/calls/stats?from_date=2025-01-01" \ -H "x-api-key: kros_live_your_key" Response Plain text { "total_calls": 1250, "completed_calls": 1180, "failed_calls": 70, "total_duration_seconds": 45000, "average_duration_seconds": 38, "total_cost_cents": 3600, "inbound_calls": 800, "outbound_calls": 450, "success_rate": 0.944 } { "total_calls": 1250, "completed_calls": 1180, "failed_calls": 70, "total_duration_seconds": 45000, "average_duration_seconds": 38, "total_cost_cents": 3600, "inbound_calls": 800, "outbound_calls": 450, "success_rate": 0.944 } Get Call Events Retrieve the event timeline for a specific call. Endpoint Plain text GET /calls/{id}/events GET /calls/{id}/events Request Plain text curl -X GET "https://api.krosai.com/v1/calls/call_abc123/events" \ -H "x-api-key: kros_live_your_key" curl -X GET "https://api.krosai.com/v1/calls/call_abc123/events" \ -H "x-api-key: kros_live_your_key" Response Plain text { "events": [ { "id": "evt_001", "event_type": "call_initiated", "created_at": "2025-01-10T10:00:00Z", "event_data": {} }, { "id": "evt_002", "event_type": "sip_invite_sent", "created_at": "2025-01-10T10:00:01Z", "event_data": { "sip_uri": "sip:agent@sip.rtc.elevenlabs.io" } }, { "id": "evt_003", "event_type": "call_answered", "created_at": "2025-01-10T10:00:05Z", "event_data": {} }, { "id": "evt_004", "event_type": "sip_media_established", "created_at": "2025-01-10T10:00:06Z", "event_data": { "codec": "opus", "latency_ms": 120 } }, { "id": "evt_005", "event_type": "call_completed", "created_at": "2025-01-10T10:03:05Z", "event_data": { "duration": 180, "hangup_cause": "normal_clearing" } } ] } { "events": [ { "id": "evt_001", "event_type": "call_initiated", "created_at": "2025-01-10T10:00:00Z", "event_data": {} }, { "id": "evt_002", "event_type": "sip_invite_sent", "created_at": "2025-01-10T10:00:01Z", "event_data": { "sip_uri": "sip:agent@sip.rtc.elevenlabs.io" } }, { "id": "evt_003", "event_type": "call_answered", "created_at": "2025-01-10T10:00:05Z", "event_data": {} }, { "id": "evt_004", "event_type": "sip_media_established", "created_at": "2025-01-10T10:00:06Z", "event_data": { "codec": "opus", "latency_ms": 120 } }, { "id": "evt_005", "event_type": "call_completed", "created_at": "2025-01-10T10:03:05Z", "event_data": { "duration": 180, "hangup_cause": "normal_clearing" } } ] } Hangup Call Terminate an active call. Endpoint Plain text POST /calls/{id}/hangup POST /calls/{id}/hangup Request Plain text curl -X POST "https://api.krosai.com/v1/calls/call_abc123/hangup" \ -H "x-api-key: kros_live_your_key" curl -X POST "https://api.krosai.com/v1/calls/call_abc123/hangup" \ -H "x-api-key: kros_live_your_key" Response Plain text { "success": true, "message": "Call hangup initiated" } { "success": true, "message": "Call hangup initiated" } Call Status Values Status Description initiated Call is being set up ringing Destination is ringing in_progress Call is active completed Call ended normally failed Call failed to connect busy Destination was busy no_answer No answer at destination Hangup Causes Cause Description normal_clearing Normal call termination user_hangup Caller hung up agent_hangup Agent/endpoint hung up no_answer Destination didn't answer busy Destination busy rejected Call rejected network_error Network failure timeout Call timed out Recordings Call recordings are automatically generated for completed calls and stored securely. Recording URL Recordings are available via the recording_url field: https://storage.krosai.com/recordings/call_abc123.mp3 Recording Formats Format: MP3 Sample Rate: 48kHz Channels: Mono (mixed) Retention: 90 days (configurable) Transcripts Full transcripts are generated using speech-to-text and available in the transcript field. Transcript Format Plain text with speaker labels (when available): Plain text [Agent]: Hello, how can I help you today? [Caller]: Hi, I'm calling about my order status. [Agent]: I'd be happy to help. Can you provide your order number? ... [Agent]: Hello, how can I help you today? [Caller]: Hi, I'm calling about my order status. [Agent]: I'd be happy to help. Can you provide your order number? ... Code Examples TypeScript • [📹Recordings](https://docs.krosai.com/voice/recordings.md): KrosAI automatically records all calls and generates transcripts. Access recordings via the API or dashboard. Overview Automatic Recording: All calls are recorded by default Transcription: Speech-to-text transcripts generated automatically Storage: Secure cloud storage with 90-day retention (configurable) Format: MP3 audio, 48kHz mono Accessing Recordings Via Call Detail Recordings are included in the call detail response: CURL curl -X GET "https://api.krosai.com/v1/calls/call_abc123" \ -H "x-api-key: kros_live_your_key" Response: JSON { "id": "call_abc123", "status": "completed", "duration": 180, "recording_url": "https://storage.krosai.com/recordings/call_abc123.mp3", "transcript": "[Agent]: Hello, how can I help you today?\n[Caller]: I need help with my order...", "created_at": "2025-01-10T10:00:00Z" } Download Recording Recordings are served via presigned URLs that are valid for 1 hour: TypeScript async function downloadRecording(callId: string): Promise<Blob> { // Get call details with recording URL const call = await fetch(`https://api.krosai.com/v1/calls/${callId}`, { headers: { 'x-api-key': process.env.KROSAI_API_KEY! }, }).then(r => r.json()); if (!call.recording_url) { throw new Error('No recording available'); } // Download the audio file const response = await fetch(call.recording_url); return response.blob(); } Get Recording URL Only For efficiency, you can request just the recording URL: Plain text GET /calls/{id}/recording GET /calls/{id}/recording Response: JSON { "recording_url": "https://storage.krosai.com/recordings/call_abc123.mp3", "expires_at": "2025-01-10T11:00:00Z", "duration_seconds": 180, "format": "mp3", "size_bytes": 2160000 } Transcripts Transcript Format Transcripts are provided as plain text with speaker labels: Plain text [Agent]: Hello, thank you for calling. How can I help you today? [Caller]: Hi, I'm calling about my recent order. [Agent]: I'd be happy to help with that. Can you provide your order number? [Caller]: Sure, it's ORD-12345. [Agent]: Thank you. I can see your order here. It was shipped yesterday and should arrive tomorrow. [Caller]: Great, thanks for the update! [Agent]: You're welcome. Is there anything else I can help with? [Caller]: No, that's all. Thank you. [Agent]: Have a great day. Goodbye! [Agent]: Hello, thank you for calling. How can I help you today? [Caller]: Hi, I'm calling about my recent order. [Agent]: I'd be happy to help with that. Can you provide your order number? [Caller]: Sure, it's ORD-12345. [Agent]: Thank you. I can see your order here. It was shipped yesterday and should arrive tomorrow. [Caller]: Great, thanks for the update! [Agent]: You're welcome. Is there anything else I can help with? [Caller]: No, that's all. Thank you. [Agent]: Have a great day. Goodbye! Get Transcript Only Plain text GET /calls/{id}/transcript GET /calls/{id}/transcript Response: JSON { "transcript": "[Agent]: Hello, thank you for calling...", "word_count": 156, "language": "en", "confidence": 0.94 } Recording Settings Enable/Disable Recording Configure recording at the organization level: CURL curl -X PATCH "https://api.krosai.com/v1/settings" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "recording_enabled": true, "transcription_enabled": true }' Per-Call Recording Control Override recording settings for specific calls: CURL curl -X POST "https://api.krosai.com/v1/outbound-calls" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "from_number": "+2348012345678", "to_number": "+14155551234", "endpoint_id": "ep_abc123", "recording_enabled": false }' Recording Retention Plan Default Retention Maximum Retention Free 7 days 7 days Pro 30 days 90 days Business 90 days 365 days Enterprise Custom Unlimite Extend Retention Keep specific recordings longer: CURL curl -X POST "https://api.krosai.com/v1/calls/call_abc123/recording/extend" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "days": 365 }' Code Examples TypeScript - Batch Download Recordings TypeScript import fs from 'fs'; import path from 'path'; async function downloadAllRecordings(fromDate: string, outputDir: string) { // Get calls with recordings const response = await fetch( `https://api.krosai.com/v1/calls?from_date=${fromDate}&status=completed`, { headers: { 'x-api-key': process.env.KROSAI_API_KEY! }, } ); const { calls } = await response.json(); for (const call of calls) { if (!call.recording_url) continue; const audioResponse = await fetch(call.recording_url); const buffer = await audioResponse.arrayBuffer(); const filename = `${call.id}_${call.from_number}_${call.duration}s.mp3`; fs.writeFileSync( path.join(outputDir, filename), Buffer.from(buffer) ); console.log(`Downloaded: ${filename}`); } } Python - Export Transcripts Python import requests import os import json def export_transcripts(from_date: str, output_file: str): api_key = os.environ['KROSAI_API_KEY'] # Get completed calls response = requests.get( f'https://api.krosai.com/v1/calls', headers={'x-api-key': api_key}, params={ 'from_date': from_date, 'status': 'completed', 'limit': 100 } ) calls = response.json()['calls'] transcripts = [] for call in calls: if call.get('transcript'): transcripts.append({ 'call_id': call['id'], 'from': call['from_number'], 'to': call['to_number'], 'duration': call['duration'], 'transcript': call['transcript'], 'timestamp': call['created_at'] }) with open(output_file, 'w') as f: json.dump(transcripts, f, indent=2) print(f'Exported {len(transcripts)} transcripts to {output_file}') # Export last 30 days export_transcripts('2025-01-01', 'transcripts.json') Streaming Audio Playback TSX // React component for audio playback function CallRecordingPlayer({ callId }: { callId: string }) { const [audioUrl, setAudioUrl] = useState<string | null>(null); const [loading, setLoading] = useState(true); useEffect(() => { async function loadRecording() { const response = await fetch(`/api/calls/${callId}`); const call = await response.json(); setAudioUrl(call.recording_url); setLoading(false); } loadRecording(); }, [callId]); if (loading) return <Skeleton className="h-12 w-full" />; if (!audioUrl) return <p>No recording available</p>; return ( <audio controls className="w-full"> <source src={audioUrl} type="audio/mpeg" /> Your browser does not support the audio element. </audio> ); } Compliance & Privacy Recording Disclosure Ensure compliance with local laws regarding call recording: United States: Two-party consent in some states European Union: GDPR requires explicit consent Nigeria: Recording allowed for business purposes Data Protection Recordings are encrypted at rest (AES-256) Transmitted via HTTPS/TLS 1.3 Access logged for audit purposes Automatic deletion after retention period Delete Recording Permanently delete a recording: CURL curl -X DELETE "https://api.krosai.com/v1/calls/call_abc123/recording" \ -H "x-api-key: kros_live_your_key" Warning: This action is irreversible. • [▦Overview](https://docs.krosai.com/webhooks-1/overview.md): Webhooks allow you to receive real-time HTTP notifications when events occur in your KrosAI account. Setup Follow the steps below to configure a webhook endpoint from your KrosAI Dashboard. 1 Go to the Webhooks page Go to Developers → Webhooks in the Dashboard. 2 Create a webhook Click Create Webhook . 3 Enter your endpoint Enter your endpoint URL. 4 Select events Select the events you want to subscribe to. 5 Save and copy secret Save the webhook and copy the signing secret. Keep your signing secret safe — you will need it to verify incoming webhook payloads. Available Events Subscribe only to the events your application needs to reduce unnecessary traffic. Event Description call.started Call connected call.ended Call ended call.failed Call failed to connect call.recording.completed Recording available transcription.completed Transcript ready Payload Structure Every webhook payload follows the same envelope structure regardless of event type. JSON { "id": "evt_abc123", "event": "call.ended", "timestamp": "2025-01-12T10:30:00Z", "data": { "call_id": "call_xyz789", "from_number": "+2348012345678", "to_number": "+14155551234", "direction": "outbound", "duration": 180, "cost_cents": 12, "status": "completed" } } Signature Verification Always verify the webhook signature before processing any payload. Skipping this step exposes your endpoint to spoofed requests. Verify the X-Webhook-Signature header: JavaScript const crypto = require('crypto'); function verifySignature(payload, signature, secret) { const expected = crypto .createHmac('sha256', secret) .update(payload, 'utf8') .digest('hex'); return `sha256=${expected}` === signature; } Retry Policy Your endpoint must respond with HTTP 2xx within 10 seconds. Failure to do so will trigger the retry schedule below. Attempt Delay 1 Immediate 2 1 minute 3 5 minutes 4 30 minutes 5 2 hours After 5 failed attempts, the webhook will be disabled automatically. You must re-enable it manually from the Dashboard. • [🌀Events](https://docs.krosai.com/webhooks-1/events.md): This page documents all webhook events sent by KrosAI. Event Format All webhook events follow this structure: JavaScript { "event": "event.type", "id": "evt_abc123", "timestamp": "2025-01-10T12:00:00Z", "data": { // Event-specific data } } Call Events call.initiated Sent when a call is initiated (inbound or outbound). JavaScript { "event": "call.initiated", "id": "evt_001", "timestamp": "2025-01-10T12:00:00Z", "data": { "call_id": "call_abc123", "direction": "inbound", "from_number": "+14155551234", "to_number": "+2348012345678", "phone_number_id": "pn_123", "endpoint_id": "ep_456" } } call.ringing Sent when the destination is ringing. JavaScript { "event": "call.initiated", "id": "evt_001", "timestamp": "2025-01-10T12:00:00Z", "data": { "call_id": "call_abc123", "direction": "inbound", "from_number": "+14155551234", "to_number": "+2348012345678", "phone_number_id": "pn_123", "endpoint_id": "ep_456" } } call.answered Sent when the call is answered. JavaScript { "event": "call.answered", "id": "evt_003", "timestamp": "2025-01-10T12:00:05Z", "data": { "call_id": "call_abc123", "answered_at": "2025-01-10T12:00:05Z" } } call.completed Sent when a call ends normally. Plain text "event": "call.completed", "id": "evt_004", "timestamp": "2025-01-10T12:03:05Z", "data": { "call_id": "call_abc123", "direction": "inbound", "from_number": "+14155551234", "to_number": "+2348012345678", "duration": 180, "cost_cents": 12, "hangup_cause": "normal_clearing", "recording_url": "https://storage.krosai.com/recordings/call_abc123.mp3", "transcript": "Hello, how can I help you today?...", "metadata": { "customer_id": "cust_123" } } } "event": "call.completed", "id": "evt_004", "timestamp": "2025-01-10T12:03:05Z", "data": { "call_id": "call_abc123", "direction": "inbound", "from_number": "+14155551234", "to_number": "+2348012345678", "duration": 180, "cost_cents": 12, "hangup_cause": "normal_clearing", "recording_url": "https://storage.krosai.com/recordings/call_abc123.mp3", "transcript": "Hello, how can I help you today?...", "metadata": { "customer_id": "cust_123" } } } call.failed Sent when a call fails to connect. Plain text { "event": "call.failed", "id": "evt_005", "timestamp": "2025-01-10T12:00:30Z", "data": { "call_id": "call_abc123", "direction": "outbound", "from_number": "+2348012345678", "to_number": "+14155551234", "error_code": "NETWORK_ERROR", "error_message": "Failed to establish connection" } } { "event": "call.failed", "id": "evt_005", "timestamp": "2025-01-10T12:00:30Z", "data": { "call_id": "call_abc123", "direction": "outbound", "from_number": "+2348012345678", "to_number": "+14155551234", "error_code": "NETWORK_ERROR", "error_message": "Failed to establish connection" } } Phone Number Events phone_number.purchased Sent when a phone number is purchased. Plain text { "event": "phone_number.purchased", "id": "evt_010", "timestamp": "2025-01-10T12:00:00Z", "data": { "phone_number_id": "pn_abc123", "number": "+2348012345678", "country": "NG", "type": "local", "monthly_cost_cents": 500 } } { "event": "phone_number.purchased", "id": "evt_010", "timestamp": "2025-01-10T12:00:00Z", "data": { "phone_number_id": "pn_abc123", "number": "+2348012345678", "country": "NG", "type": "local", "monthly_cost_cents": 500 } } phone_number.released Sent when a phone number is released. Plain text { "event": "phone_number.released", "id": "evt_011", "timestamp": "2025-01-10T12:00:00Z", "data": { "phone_number_id": "pn_abc123", "number": "+2348012345678" } } { "event": "phone_number.released", "id": "evt_011", "timestamp": "2025-01-10T12:00:00Z", "data": { "phone_number_id": "pn_abc123", "number": "+2348012345678" } } phone_number.updated Sent when a phone number configuration changes. Plain text { "event": "phone_number.updated", "id": "evt_012", "timestamp": "2025-01-10T12:00:00Z", "data": { "phone_number_id": "pn_abc123", "changes": { "endpoint_id": { "old": "ep_old", "new": "ep_new" } } } } { "event": "phone_number.updated", "id": "evt_012", "timestamp": "2025-01-10T12:00:00Z", "data": { "phone_number_id": "pn_abc123", "changes": { "endpoint_id": { "old": "ep_old", "new": "ep_new" } } } } Endpoint Events endpoint.created Sent when an endpoint is created. Plain text { "event": "endpoint.created", "id": "evt_020", "timestamp": "2025-01-10T12:00:00Z", "data": { "endpoint_id": "ep_abc123", "name": "Support Agent", "type": "agent", "provider": "elevenlabs" } } { "event": "endpoint.created", "id": "evt_020", "timestamp": "2025-01-10T12:00:00Z", "data": { "endpoint_id": "ep_abc123", "name": "Support Agent", "type": "agent", "provider": "elevenlabs" } } endpoint.updated Sent when an endpoint is updated. Plain text { "event": "endpoint.updated", "id": "evt_021", "timestamp": "2025-01-10T12:00:00Z", "data": { "endpoint_id": "ep_abc123", "changes": { "status": { "old": "active", "new": "inactive" } } } } { "event": "endpoint.updated", "id": "evt_021", "timestamp": "2025-01-10T12:00:00Z", "data": { "endpoint_id": "ep_abc123", "changes": { "status": { "old": "active", "new": "inactive" } } } } endpoint.deleted Sent when an endpoint is deleted. Plain text { "event": "endpoint.deleted", "id": "evt_022", "timestamp": "2025-01-10T12:00:00Z", "data": { "endpoint_id": "ep_abc123" } } { "event": "endpoint.deleted", "id": "evt_022", "timestamp": "2025-01-10T12:00:00Z", "data": { "endpoint_id": "ep_abc123" } } Recording Events recording.ready Sent when a call recording is processed and available. Plain text { "event": "recording.ready", "id": "evt_030", "timestamp": "2025-01-10T12:05:00Z", "data": { "call_id": "call_abc123", "recording_url": "https://storage.krosai.com/recordings/call_abc123.mp3", "duration_seconds": 180, "size_bytes": 2160000 } } { "event": "recording.ready", "id": "evt_030", "timestamp": "2025-01-10T12:05:00Z", "data": { "call_id": "call_abc123", "recording_url": "https://storage.krosai.com/recordings/call_abc123.mp3", "duration_seconds": 180, "size_bytes": 2160000 } } transcript.ready Sent when a call transcript is processed and available. Plain text { "event": "transcript.ready", "id": "evt_031", "timestamp": "2025-01-10T12:05:30Z", "data": { "call_id": "call_abc123", "transcript": "[Agent]: Hello...", "word_count": 156, "language": "en" } } { "event": "transcript.ready", "id": "evt_031", "timestamp": "2025-01-10T12:05:30Z", "data": { "call_id": "call_abc123", "transcript": "[Agent]: Hello...", "word_count": 156, "language": "en" } } Port Request Events port_request.submitted Plain text { "event": "port_request.submitted", "id": "evt_040", "timestamp": "2025-01-10T12:00:00Z", "data": { "port_request_id": "pr_abc123", "phone_number": "+2348012345678", "current_carrier": "mtn" } } { "event": "port_request.submitted", "id": "evt_040", "timestamp": "2025-01-10T12:00:00Z", "data": { "port_request_id": "pr_abc123", "phone_number": "+2348012345678", "current_carrier": "mtn" } } port_request.completed Plain text { "event": "port_request.completed", "id": "evt_041", "timestamp": "2025-01-25T10:00:00Z", "data": { "port_request_id": "pr_abc123", "phone_number_id": "pn_new123", "phone_number": "+2348012345678" } } { "event": "port_request.completed", "id": "evt_041", "timestamp": "2025-01-25T10:00:00Z", "data": { "port_request_id": "pr_abc123", "phone_number_id": "pn_new123", "phone_number": "+2348012345678" } } port_request.failed Plain text { "event": "port_request.failed", "id": "evt_042", "timestamp": "2025-01-15T14:00:00Z", "data": { "port_request_id": "pr_abc123", "reason": "Account name mismatch", "phone_number": "+2348012345678" } } { "event": "port_request.failed", "id": "evt_042", "timestamp": "2025-01-15T14:00:00Z", "data": { "port_request_id": "pr_abc123", "reason": "Account name mismatch", "phone_number": "+2348012345678" } } Billing Events balance.low Sent when account balance falls below threshold. Plain text { "event": "balance.low", "id": "evt_050", "timestamp": "2025-01-10T12:00:00Z", "data": { "current_balance_cents": 500, "threshold_cents": 1000 } } { "event": "balance.low", "id": "evt_050", "timestamp": "2025-01-10T12:00:00Z", "data": { "current_balance_cents": 500, "threshold_cents": 1000 } } payment.received Plain text { "event": "payment.received", "id": "evt_051", "timestamp": "2025-01-10T12:00:00Z", "data": { "amount_cents": 10000, "payment_method": "card", "new_balance_cents": 10500 } } { "event": "payment.received", "id": "evt_051", "timestamp": "2025-01-10T12:00:00Z", "data": { "amount_cents": 10000, "payment_method": "card", "new_balance_cents": 10500 } } Event Subscriptions Configure which events to receive when creating a webhook: Plain text curl -X POST "https://api.krosai.com/v1/webhooks" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "url": "https://api.yourapp.com/webhooks/krosai", "events": [ "call.completed", "call.failed", "recording.ready" ] }' curl -X POST "https://api.krosai.com/v1/webhooks" \ -H "x-api-key: kros_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "url": "https://api.yourapp.com/webhooks/krosai", "events": [ "call.completed", "call.failed", "recording.ready" ] }' Event Wildcards Subscribe to all events in a category: call.* — All call events phone_number.* — All phone number events * — All events • [⏳Rate limits](https://docs.krosai.com/reference-1/rate-limits.md): KrosAI applies rate limits to ensure fair usage and platform stability. Limits by Plan Plan Requests/Second Requests/Day Concurrent Calls Free 10 1,000 1 Pro 50 50,000 10 Business 200 500,000 50 Enterprise Custom Custom Unlimited Rate Limit Headers Every API response includes rate limit information: X-RateLimit-Limit: 50 X-RateLimit-Remaining: 45 X-RateLimit-Reset: 1704891600 Title Description X-RateLimit-Limit Maximum requests per second X-RateLimit-Remaining Requests remaining in current window X-RateLimit-Reset Unix timestamp when limit resets Rate Limit Response When you exceed the rate limit, you'll receive a 429 Too Many Requests response: Plain text { "error": "Rate limit exceeded", "code": "RATE_LIMIT_EXCEEDED", "retry_after": 1.5 } { "error": "Rate limit exceeded", "code": "RATE_LIMIT_EXCEEDED", "retry_after": 1.5 } The Retry-After header indicates seconds to wait: Retry-After: 1.5 Endpoint-Specific Limits Some endpoints have additional limits: Title Description Title POST /outbound-calls 10/sec Per organization POST /phone-numbers 5/sec KYC required GET /calls 100/sec Pagination recommended POST /webhooks 10/sec Per organization • [⚠️Error Codes](https://docs.krosai.com/reference-1/error-codes.md): HTTP Status Codes Code Meaning 200 Success 201 Created 400 Bad Request 401 Unauthorized 403 Forbidden 404 Not Found 429 Rate Limited 500 Server Error Authentication Code solution INVALID_API_KEY Check API Key MISSING_API_KEY Add x-api-key header INSUFFICIENT_SCOPE Create key with proper scopes Phone Numbers Code Solution KYC_REQUIRED Complete verification INSUFFICENT_BALANCE Add credits NUMBER_NOT_AVAILABLE Choose different number Calls Code Solution INVALID_PHONE_NUMBERS Use E.164 format N0_ENDPOINT Attach endpoint to number ENDPOINT_UNREACHABLE Check endpoint config