# Get Classification Analytics Source: https://docs.ringg.ai/api-reference/endpoint/analytics/get-classification-analytics get /analytics/classification-analytics Retrieves call classification analytics data. Return analytics grouped by call classification. Classifications are useful for outcome dashboards such as interested, not interested, payment confirmed, callback requested, or custom categories configured for your assistant. ## When to use * Build outcome funnels. * Compare campaign quality by classification. * Trigger downstream workflows based on call outcomes. ## Related data For per-call classification values, use [Get call history](/api-reference/endpoint/history/get-call-history), [Get call details](/api-reference/endpoint/history/get-call-details), or webhook payloads. # Get Drill-Down Analytics Source: https://docs.ringg.ai/api-reference/endpoint/analytics/get-drill-down-analytics get /analytics/drill-down-analytics Retrieves detailed analytics for a specific bulk list/campaign with drill-down capabilities. Return detailed analytics for one campaign or bulk list. This is the endpoint to use when a dashboard user clicks from a summary metric into campaign performance. ## Required input * `bulk_list_id`: the campaign/contact-list identifier returned by campaign upload and used when starting the campaign. ## Use this for * Campaign performance views. * Status and outcome breakdowns. * Detailed campaign troubleshooting. Pair it with [Get call history](/api-reference/endpoint/history/get-call-history) filtered by the same `bulk_list_id` when users need call-level rows. # Get Duration Distribution Source: https://docs.ringg.ai/api-reference/endpoint/analytics/get-duration-distribution get /analytics/duration-distribution Retrieves call duration distribution analytics. Return call duration distribution analytics. Use this to understand whether conversations are too short, too long, or clustered around expected script lengths. ## Use this for * Detecting early hangups or low engagement. * Spotting calls that exceed the expected script length. * Tuning assistant prompts, transfer rules, and max call length. Filter by `agent_id` or `bulk_list_id` when investigating one assistant or campaign. For campaign dashboards, combine this distribution with classification analytics so teams can see whether short calls are failed attempts, successful quick confirmations, or early hangups. # Get Number Analytics Source: https://docs.ringg.ai/api-reference/endpoint/analytics/get-number-analytics get /analytics/number-analytics Retrieves analytics broken down by phone numbers. Break analytics down by phone number. Use this to compare caller ID performance, monitor BYOT numbers, and identify numbers with poor pickup or completion rates. ## Useful filters * `start_date` and `end_date` for reporting windows. * `agent_id` to compare numbers used by one assistant. * `bulk_list_id` to compare numbers inside one campaign. ## How to act on results If one number underperforms, check number assignment, telephony provider health, calling hours, and recipient region fit. # Get Platform Analytics Source: https://docs.ringg.ai/api-reference/endpoint/analytics/get-platform-analytics get /analytics/platform-analytics Retrieves comprehensive platform analytics including performance metrics and summaries. Return high-level platform analytics for calls in the workspace. Use this endpoint for overview dashboards and executive summaries. ## Common filters * `start_date` and `end_date` for the reporting period. * `agent_id` for one assistant. * `bulk_list_id` for one campaign. * `voicemail` when voicemail-heavy traffic should be included or separated. ## Developer guidance Use this endpoint for top-level numbers, then use drill-down analytics or call history when a user clicks into a specific campaign, number, or status bucket. # Create Agent Source: https://docs.ringg.ai/api-reference/endpoint/assistant/create-agent post /public/agent Creates a new AI agent with the specified configuration. The agent will be created with a single prompt-based flow. Create a new assistant programmatically. This endpoint is best for productized setup flows where your application creates Ringg assistants from templates or customer-provided configuration. ## When to use * Onboard customers into a pre-defined assistant template. * Create one assistant per team, location, or campaign type. * Provision assistants from your own admin backend. ## Call settings Pass `call_config` to fix the assistant's call behaviour at creation time instead of following up in the dashboard. Every field is optional — omit the block, or any key in it, to accept the default. | Field | Purpose | Default | | - | - | - | | `call_time` | Daily window the assistant may place calls in: `call_start_time` and `call_end_time` as `HH:MM` 24-hour, plus the `timezone` they are expressed in. | `09:00`-`21:00` `Asia/Kolkata` | | `max_call_length` | Hard cap on call duration, in seconds. | `240` | | `idle_timeout_warning` | Seconds of caller silence before the assistant checks in ("Are you still there?"). `0` disables the check-in. | `5` | | `idle_timeout_end` | Seconds of caller silence before the call is dropped. | `10` | | `noise_filter_config` | Background-noise cancellation on the caller's audio: `filter_noise` to switch it on, `noise_suppression_level` (0-100) for strength. | off, level `80` | | `voicemail` | Voicemail handling: `detect` to switch detection on, `action` for what happens next (`end`, `summarise`, `static_message`), `retry` to re-queue the call for a later attempt. | detect and retry on, action `end` | | `background_audio_config` | Ambient audio mixed under the assistant's speech: `audio_id` (`office_ambience` is the only track) and `volume` as a `0.0`-`1.0` fraction. Omit the object to keep it off. | off | | `mute_during_intro` | When `true`, the caller cannot interrupt the intro message. Set `false` to make the first message interruptible. | `true` | ```json theme={null} { "agent_name": "Support Assistant", "introduction_and_objective": "You are a support agent for Acme Corp.", "response_guidelines": "Be polite, helpful, and concise.", "task": "Help customers with their orders.", "primary_language": "en-IN", "voice_id": "your-voice-id", "intro_message": "Hello, this is Sarah from Acme Corp.", "call_config": { "call_time": { "call_start_time": "10:00", "call_end_time": "18:30", "timezone": "America/New_York" }, "max_call_length": 600, "idle_timeout_warning": 8, "idle_timeout_end": 20, "noise_filter_config": { "filter_noise": true, "noise_suppression_level": 95 }, "voicemail": { "detect": true, "action": "end", "retry": true }, "background_audio_config": { "audio_id": "office_ambience", "volume": 0.35 }, "mute_during_intro": false } } ``` ### Calling window and timezones Outside the window an outbound call is not dialled immediately, and retries are pushed to the next opening. The window is per assistant; a campaign or an individual call can override it. **Any IANA timezone is supported** — this is not India-only. `Asia/Kolkata` is merely the default when you omit it. ```json theme={null} { "call_time": { "call_start_time": "09:00", "call_end_time": "17:30", "timezone": "America/New_York" } } { "call_time": { "call_start_time": "08:00", "call_end_time": "20:00", "timezone": "Europe/London" } } { "call_time": { "call_start_time": "10:00", "call_end_time": "19:00", "timezone": "Asia/Dubai" } } { "call_time": { "call_start_time": "09:00", "call_end_time": "18:00", "timezone": "Australia/Sydney" } } { "call_time": { "call_start_time": "00:00", "call_end_time": "23:59", "timezone": "UTC" } } ``` A window may cross midnight — `"call_start_time": "22:00"` with `"call_end_time": "06:00"` is a valid overnight window. **Always use the full `Region/City` form.** Abbreviations behave in two different, equally unhelpful ways: * `IST`, `PST` and `CST` are **rejected** — they are not IANA zones. * `EST`, `MST`, `HST` and `GMT` are **accepted, and are a trap**. They are fixed-offset zones that never observe daylight saving, so an assistant on `EST` runs an hour behind actual New York time for the \~8 months that `America/New_York` is on EDT. Use `America/New_York`, not `EST`. Times must be zero-padded 24-hour: send `09:00`, not `9:00` or `9:00 AM`. Both the window and the timezone are validated when you create the assistant, so a bad value fails the create call rather than every call the assistant later tries to place. `scheduled_at` is **not** accepted inside `call_time` here. It schedules one specific call, so on an assistant it would pin every call that assistant ever places to the same timestamp. Pass it per call, on the [individual call](/api-reference/endpoint/calling/initiate-individual-call) endpoint's own `call_config.call_time`. `idle_timeout_warning` must be **less than** `idle_timeout_end`, otherwise the request is rejected. If the warning fires at or after the hangup, the check-in can never be spoken. Use `0` to disable the check-in and keep only the hangup. Two easy ones to get backwards: * `background_audio_config.volume` is a fraction between `0.0` and `1.0`, not a percentage. `50` is rejected; send `0.5`. * `mute_during_intro` reads as the opposite of "interruptible". `true` (the default) means the caller **cannot** cut in over the intro message. `call_config` is accepted on create only. To change these settings afterwards, use the dashboard — the [edit assistant](/api-reference/endpoint/assistant/edit-assistant) endpoint does not accept them yet, and they are not returned by [get assistant](/api-reference/endpoint/assistant/get-assistant-by-id). ## Integration notes * For most teams, creating the assistant in the dashboard first is simpler. * Store the returned `agent_id`; it is required for calls and campaigns. * Keep prompts concise and make every variable explicit in `custom_args_values` or campaign CSV mappings. ## After creation Use [get assistants](/api-reference/endpoint/assistant/get-assistants) to confirm the assistant is visible, then test with one [individual call](/api-reference/endpoint/calling/initiate-individual-call) before using campaigns. # Edit Assistant Source: https://docs.ringg.ai/api-reference/endpoint/assistant/edit-assistant patch /agent/v1 Updates an existing assistant with new configuration settings. Each operation requires specific fields to be provided. Update an existing assistant. The request uses an `operation` field so each edit is explicit, such as updating prompts, variables, or webhook event subscriptions. ## When to use * Update assistant configuration from your own admin backend. * Configure event subscriptions for webhooks. * Keep assistant behavior synchronized with templates in your product. ## Integration notes * Test configuration changes with one individual call before running a campaign. * Avoid overwriting unrelated assistant settings in broad update flows. * For webhook setup, use `operation: "edit_event_subscriptions"` and provide the events plus callback URL Ringg should call. ## Related guide See [webhook setup](/webhooks/initial-setup) for a complete event subscription example. # Get Assistant By ID Source: https://docs.ringg.ai/api-reference/endpoint/assistant/get-assistant-by-id get /agent/{agent_id} Retrieves detailed information about a specific assistant by its ID. Fetch details for one assistant. Use this after an operator selects an assistant or when debugging why a call did not behave as expected. ## Useful checks * Confirm the assistant exists in the current workspace. * Inspect call direction, prompt configuration, variables, and assigned resources. * Verify the assistant is the one your integration intended to use. ## Related endpoints * [List assistants](/api-reference/endpoint/assistant/get-assistants) * [Initiate individual call](/api-reference/endpoint/calling/initiate-individual-call) * [Upload campaign contact list](/api-reference/endpoint/campaign/upload-campaign-contact-list) # Get Assistant Voices Source: https://docs.ringg.ai/api-reference/endpoint/assistant/get-assistant-voices get /agent/voices Retrieves a list of available voices for assistants, optionally filtered by language. List available voices for assistant configuration. You can optionally filter by language when building assistant creation or configuration workflows. ## When to use * Populate a voice picker in a custom assistant setup UI. * Validate that a desired language has available voices before creating an assistant. * Let internal operators compare voice options without opening the Ringg dashboard. ## Integration notes Voice availability can vary by language and provider. Store the selected voice ID only after the operator confirms the assistant configuration. # Get Assistants Source: https://docs.ringg.ai/api-reference/endpoint/assistant/get-assistants get /agent/all Retrieves a list of all available assistants in your workspace. List assistants in the workspace. Most integrations call this during setup so an operator can choose which assistant should handle calls. ## When to use * Populate an assistant picker in your internal admin UI. * Find the `agent_id` required by outbound call and campaign APIs. * Filter for assistants configured for the channel you are integrating, such as outbound calls or web calls. ## Integration notes * Store the selected `agent_id` in your database rather than looking it up before every call. * If an assistant is edited in the dashboard, its ID remains the stable integration handle. * Use `GET /agent/{agent_id}` when you need details for one assistant. # Initiate Individual Call Source: https://docs.ringg.ai/api-reference/endpoint/calling/initiate-individual-call post /calling/outbound/individual Starts one outbound call to a recipient. **Exactly one caller-number option is required: from_number_id or from_number.** **Deprecated.** This endpoint requires you to pass and manage caller numbers yourself via `from_number_id` or `from_number`. New integrations should use [Initiate Individual Call (Pool)](/api-reference/endpoint/calling/initiate-individual-call-v2), which can resolve numbers automatically from a managed pool (rotation, spam skipping, and auto-purchase). Start one outbound call with a configured assistant. Use this endpoint for transactional calls, test calls before campaigns, and product workflows where one user action should trigger one phone call. ## Required inputs | Field | Purpose | | - | - | | `name` | Recipient name. Ringg also uses this as `callee_name` if you do not provide one in `custom_args_values`. | | `mobile_number` | Recipient phone number in E.164 format, for example `+919876543210`. | | `agent_id` | Assistant that will handle the conversation. Get it from `GET /agent/all`. | | `from_number_id` or `from_number` | Caller ID to use. **Exactly one is required.** Use `from_number_id` when possible because it is stable across number formatting changes. | **Provide either `from_number_id` or `from_number`, not both.** Phone numbers passed as `from_number` must include country code. ## Minimal request ```json theme={null} { "name": "John Doe", "mobile_number": "+919876543210", "agent_id": "your-agent-id", "from_number_id": "your-from-number-id", "custom_args_values": { "callee_name": "John", "order_id": "ORD-1042" } } ``` ## Custom variables Use `custom_args_values` to pass dynamic data to your assistant. * Reference variables in prompts with `@{{variable_name}}`. * Keep keys stable across your code, prompts, CSV mappings, and analytics. * Common keys include `callee_name`, `mobile_number`, `company_name`, `appointment_date`, and your product-specific IDs. ## Scheduled calls Add `call_config.call_time.scheduled_at` when the call should be queued for a specific date and time. ```json theme={null} { "call_config": { "call_time": { "call_start_time": "09:00", "call_end_time": "18:00", "timezone": "Asia/Kolkata", "scheduled_at": "2026-10-18T10:30:00" } } } ``` `call_start_time` and `call_end_time` still act as the allowed calling window in the specified timezone. ## Retry configuration Use retry settings when a recipient is busy, does not answer, or the provider fails the call. ```json theme={null} { "call_config": { "call_retry_config": { "retry_count": 1, "retry_busy": 30, "retry_not_picked": 30, "retry_failed": 30 } } } ``` The retry delay values are in minutes. ## Smart formatter `smart_formatter` can normalize callee names before the call. ```json theme={null} { "smart_formatter": { "extract_first_name": true, "transliteration": true, "transliteration_language": { "source": "en", "target": "hi" } } } ``` For example, `Mr Rajesh Kumar` can become `Rajesh` or a transliterated value in `callee_name`. The original name is preserved as `original_callee_name` in `custom_args_values`. ## Result handling Store the returned call ID. Use it to: * Match webhook events to your internal record. * Fetch details with [Get call details](/api-reference/endpoint/history/get-call-details). * Reconcile rows from [Get call history](/api-reference/endpoint/history/get-call-history). ## Common failure checks | Symptom | Check | | - | - | | `401 Unauthorized` | Missing or invalid `X-API-KEY`. | | Validation error | Missing required field, both `from_number_id` and `from_number` provided, or invalid phone number. | | Call remains queued | Calling window, scheduled time, workspace credits, or provider health. | | Assistant says wrong data | Prompt placeholders do not match `custom_args_values` keys. | # Initiate Individual Call (Number Pool) Source: https://docs.ringg.ai/api-reference/endpoint/calling/initiate-individual-call-v2 post /calling/v2/outbound/individual Starts one outbound call to a recipient using a managed number pool or an explicit caller number. Start one outbound call with a configured assistant, using a managed number pool for caller-number resolution. The pool handles rotation, spam skipping, and auto-purchase automatically — so you don't have to manage `from_number` lists yourself. ## Required inputs | Field | Purpose | | - | - | | `name` | Recipient name. Ringg also uses this as `callee_name` if you do not provide one in `custom_args_values`. | | `mobile_number` | Recipient phone number in E.164 format, for example `+919876543210`. | | `agent_id` | Assistant that will handle the conversation. Get it from `GET /agent/all`. | ## Caller number source Provide **exactly one** of the following: | Field | When to use | | - | - | | `number_pool_id` | Recommended. Resolve the caller number automatically from a managed pool. | | `from_number_id` | Use a specific workspace number ID as caller ID. | | `from_number` | Use an explicit caller phone number (with country code). | **`from_number_id` and `from_number` cannot both be set.** At least one number source is required. ## Minimal request ```json theme={null} { "name": "John Doe", "mobile_number": "+919876543210", "agent_id": "your-agent-id", "number_pool_id": "your-number-pool-id", "custom_args_values": { "callee_name": "John", "order_id": "ORD-1042" } } ``` ## Custom variables Use `custom_args_values` to pass dynamic data to your assistant. * Reference variables in prompts with `@{{variable_name}}`. * Keep keys stable across your code, prompts, CSV mappings, and analytics. * Common keys include `callee_name`, `mobile_number`, `company_name`, `appointment_date`, and your product-specific IDs. ## Smart formatter `smart_formatter` can normalize callee names before the call. ```json theme={null} { "smart_formatter": { "extract_first_name": true, "transliteration": true, "transliteration_language": { "source": "en", "target": "hi" } } } ``` For example, `Mr Rajesh Kumar` can become `Rajesh` or a transliterated value in `callee_name`. The original name is preserved as `original_callee_name` in `custom_args_values`. ## Result handling Store the returned call ID. Use it to: * Match webhook events to your internal record. * Fetch details with [Get call details](/api-reference/endpoint/history/get-call-details). * Reconcile rows from [Get call history](/api-reference/endpoint/history/get-call-history). ## Common failure checks | Symptom | Check | | - | - | | `401 Unauthorized` | Missing or invalid `X-API-KEY`. | | Validation error | Missing required field, no number source provided, or both `from_number_id` and `from_number` set. | | Call remains queued | Calling window, scheduled time, workspace credits, pool availability, or provider health. | | Assistant says wrong data | Prompt placeholders do not match `custom_args_values` keys. | # Check large campaign balance (Beta) Source: https://docs.ringg.ai/api-reference/endpoint/campaign/check-large-campaign-balance post /campaign/check-balance/{bulk_list_id} Confirm workspace balance before starting beta large-campaign calls. This endpoint is beta. Use it only after upload processing is complete for a beta large campaign. `POST /campaign/check-balance/{bulk_list_id}` checks whether the workspace has enough balance to start calls for the validated rows in a large campaign. ## Endpoint ```text theme={null} POST /campaign/check-balance/{bulk_list_id} ``` ## Path parameters | Parameter | Required | Description | | - | - | - | | `bulk_list_id` | Yes | Large campaign list ID returned by `POST /campaign/upload-csv` | ## Request ```bash theme={null} curl --request POST "https://prod-api.ringg.ai/ca/api/v0/campaign/check-balance/your-bulk-list-id" \ --header "X-API-KEY: $RINGG_API_KEY" ``` ## Response guidance A successful response confirms whether the current balance can cover the validated campaign rows. ```json theme={null} { "bulk_list_id": "123e4567-e89b-12d3-a456-426614174000", "required_credits": 6200, "available_credits": 8500, "sufficient_balance": true } ``` If `sufficient_balance` is `false`, add balance, reduce the campaign size, or contact Ringg support before starting calls. ## Next step When balance is sufficient, call [Make large campaign calls async](/api-reference/endpoint/campaign/make-large-campaign-calls-async). # Get All Campaigns Source: https://docs.ringg.ai/api-reference/endpoint/campaign/get-all-campaigns get /campaign/all Retrieves a paginated list of campaigns for the current user with optional call count information. Return campaigns in the current workspace. Use this for campaign dashboards, monitoring pages, and post-run reconciliation after either the standard flow or the beta large-campaign flow. ## Query guidance * Use `limit` and `offset` for pagination. * Use `call_count=true` when the UI needs call totals with each campaign. * Pair this endpoint with call history filtered by `bulk_list_id` for detailed call-level results. * For beta large campaigns, poll [Upload status](/api-reference/endpoint/campaign/get-large-campaign-upload-status) until CSV processing is complete before relying on campaign-level call progress. ## Typical flow 1. Upload contacts with [Upload campaign contact list](/api-reference/endpoint/campaign/upload-campaign-contact-list). 2. Start calls with [Start campaign](/api-reference/endpoint/campaign/start-campaign). 3. Monitor campaign state here. 4. Inspect calls through [Get call history](/api-reference/endpoint/history/get-call-history). ## Beta 5,000+ row flow 1. Upload the CSV with [Upload large campaign CSV](/api-reference/endpoint/campaign/upload-large-campaign-csv). 2. Poll [Get large campaign upload status](/api-reference/endpoint/campaign/get-large-campaign-upload-status). 3. Confirm balance with [Check large campaign balance](/api-reference/endpoint/campaign/check-large-campaign-balance). 4. Start calls with [Make large campaign calls async](/api-reference/endpoint/campaign/make-large-campaign-calls-async). 5. Monitor campaign state here and inspect call rows through call history. # Get large campaign upload status (Beta) Source: https://docs.ringg.ai/api-reference/endpoint/campaign/get-large-campaign-upload-status get /campaign/upload-status/{bulk_list_id} Poll asynchronous CSV processing status for a beta large campaign. This endpoint is beta. Use it only for lists created with [Upload large campaign CSV](/api-reference/endpoint/campaign/upload-large-campaign-csv). `GET /campaign/upload-status/{bulk_list_id}` returns the processing state for a large campaign CSV upload. ## Endpoint ```text theme={null} GET /campaign/upload-status/{bulk_list_id} ``` ## Path parameters | Parameter | Required | Description | | - | - | - | | `bulk_list_id` | Yes | Large campaign list ID returned by `POST /campaign/upload-csv` | ## Request ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/campaign/upload-status/your-bulk-list-id" \ --header "X-API-KEY: $RINGG_API_KEY" ``` ## Status flow | Status | Meaning | Next action | | - | - | - | | `uploaded` | Ringg accepted the CSV and queued processing | Keep polling | | `processing` | Rows are being parsed and validated | Keep polling | | `completed` | Processing finished and valid rows are ready | Check balance | | `failed` | Processing could not complete | Fix the CSV and upload again | Some beta workspaces may return equivalent status names such as `ready` for a completed upload. Continue only when the response clearly indicates that CSV processing has finished. ## Response guidance The response includes the upload state and may include row counts or validation details. ```json theme={null} { "bulk_list_id": "123e4567-e89b-12d3-a456-426614174000", "status": "processing", "total_rows": 6200, "processed_rows": 2800, "successful_rows": 2744, "failed_rows": 56 } ``` ## Next step When processing is complete, call [Check large campaign balance](/api-reference/endpoint/campaign/check-large-campaign-balance). If the response shows invalid rows, fix and re-upload the CSV unless your workflow intentionally removes invalid rows. # Make large campaign calls async (Beta) Source: https://docs.ringg.ai/api-reference/endpoint/campaign/make-large-campaign-calls-async post /campaign/make-call-async Start outbound calls for a beta large campaign after upload processing and balance checks. This endpoint is beta. Use it only after [Get large campaign upload status](/api-reference/endpoint/campaign/get-large-campaign-upload-status) shows processing is complete and [Check large campaign balance](/api-reference/endpoint/campaign/check-large-campaign-balance) confirms sufficient balance. `POST /campaign/make-call-async` queues outbound calls for a beta large campaign. Use it instead of `POST /campaign/start` for 5,000+ row campaigns created with `POST /campaign/upload-csv`. ## Endpoint ```text theme={null} POST /campaign/make-call-async ``` ## Request body Send JSON. | Field | Required | Description | | - | - | - | | `agent_id` | Yes | Assistant that will handle the campaign calls | | `bulk_list_id` | Yes | Large campaign list ID returned by `POST /campaign/upload-csv` | | `from_numbers` | Yes | Workspace caller numbers or number IDs to use for outbound calls | | `callback_url` | No | URL that should receive post-call events, if configured | ```bash theme={null} curl --request POST "https://prod-api.ringg.ai/ca/api/v0/campaign/make-call-async" \ --header "X-API-KEY: $RINGG_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "agent_id": "your-agent-id", "bulk_list_id": "your-bulk-list-id", "from_numbers": ["your-from-number-id"], "callback_url": "https://api.example.com/ringg/campaign-callback" }' ``` ## Response guidance A successful response means the large campaign was accepted for async scheduling. ```json theme={null} { "bulk_list_id": "123e4567-e89b-12d3-a456-426614174000", "status": "scheduled", "message": "Large campaign calls queued" } ``` Avoid submitting the same `bulk_list_id` more than once unless a previous attempt clearly failed. ## Next step Monitor progress with [Get all campaigns](/api-reference/endpoint/campaign/get-all-campaigns) and inspect call rows with [Get call history](/api-reference/endpoint/history/get-call-history) filtered by the same `bulk_list_id`. # Start Campaign Source: https://docs.ringg.ai/api-reference/endpoint/campaign/start-campaign post /campaign/start Initiates a new campaign with the specified configuration. **Deprecated.** This endpoint requires you to pass and manage `from_numbers` yourself. New integrations should use [Start Campaign (Pool)](/api-reference/endpoint/campaign/start-campaign-v2), which resolves numbers automatically from a managed pool (rotation, spam skipping, and auto-purchase). Start a campaign that was created with `POST /campaign/save`. This is the legacy start endpoint for the standard campaign flow. The endpoint schedules outbound calls for all valid contacts in the uploaded campaign list. Before starting a campaign, ensure you have: * Uploaded a contact list using [Upload campaign contact list](/api-reference/endpoint/campaign/upload-campaign-contact-list) * Configured your agent with the appropriate prompts and settings * Selected valid `from_numbers` that are provisioned for your workspace ## Request parameters | Parameter | Type | Required | Description | | - | - | - | - | | `agent_id` | string | Yes | ID of the agent that will handle all campaign calls | | `list_id` | string | Yes | ID of the uploaded campaign contact list | | `from_numbers` | array | Yes | Workspace caller numbers or number IDs to use for outbound calls | ## Standard flow 1. Upload contacts with [Upload campaign contact list](/api-reference/endpoint/campaign/upload-campaign-contact-list). 2. Save the returned `list_id`. 3. Start calls with this endpoint. 4. Monitor progress with [Get all campaigns](/api-reference/endpoint/campaign/get-all-campaigns) and call history filtered by `bulk_list_id`. ## Beta large-campaign start Do not use this endpoint for the beta 5,000+ row flow. After `POST /campaign/upload-csv`, wait for upload processing to complete, check balance, then start calls with [Make large campaign calls async](/api-reference/endpoint/campaign/make-large-campaign-calls-async). ## Important notes * **Credits Required**: Ensure your workspace has sufficient credits for all contacts in the campaign * **International Calls**: For international numbers, only Twilio from\_numbers are supported * **Campaign Status**: Once started, the campaign status changes to "scheduled" or "ongoing" * **Duplicate Prevention**: Cannot start a campaign that's already in "scheduled" or "ongoing" status ## Error responses * **400**: Invalid agent\_id, campaign not found, insufficient credits, or campaign already started * **401**: Invalid or missing API key * **404**: Campaign or agent not found * **402**: Insufficient credits to initiate campaign # Start Campaign (Number Pool) Source: https://docs.ringg.ai/api-reference/endpoint/campaign/start-campaign-v2 post /campaign/v2/start Initiates a new campaign using a managed number pool for outbound calls. Numbers are resolved automatically from the pool (rotation, spam skipping, auto-purchase). Start a campaign using a managed number pool. Numbers are resolved automatically from the pool — handling rotation, spam skipping, and auto-purchase — so you don't need to specify individual `from_numbers`. Before starting a campaign, ensure you have: * Uploaded a contact list using [Upload campaign contact list](/api-reference/endpoint/campaign/upload-campaign-contact-list) * Configured your agent with the appropriate prompts and settings * Created a number pool and added numbers to it ## Request parameters | Parameter | Type | Required | Description | | - | - | - | - | | `agent_id` | string | Yes | ID of the agent that will handle all campaign calls | | `list_id` | string | Yes | ID of the uploaded campaign contact list | | `number_pool_id` | string | Yes | ID of the managed number pool to use for outbound calls | | `callback_url` | string | No | URL to receive a webhook when the campaign completes | | `email_completion_user_ids` | array | No | User IDs to notify by email on campaign completion | ## Standard flow 1. Upload contacts with [Upload campaign contact list](/api-reference/endpoint/campaign/upload-campaign-contact-list). 2. Save the returned `list_id`. 3. Start calls with this endpoint using a `number_pool_id`. 4. Monitor progress with [Get all campaigns](/api-reference/endpoint/campaign/get-all-campaigns). ## Error responses * **400**: Invalid agent\_id, list\_id, or number\_pool\_id; campaign already started * **401**: Invalid or missing API key * **500**: Unexpected server error # Upload Campaign Contact List Source: https://docs.ringg.ai/api-reference/endpoint/campaign/upload-campaign-contact-list post /campaign/save Uploads a contact list for a campaign. Accepts a CSV file and campaign configuration as form data. Upload a CSV file with contact data to create a campaign. This is the primary upload endpoint for the standard campaign flow: first call `POST /campaign/save`, then start calls with `POST /campaign/start`. For CSVs with 5,000 or more rows, use the beta large-campaign flow instead: [Upload large campaign CSV](/api-reference/endpoint/campaign/upload-large-campaign-csv), poll upload status, check balance, then start calls asynchronously. ## Quick start 1. **Prepare your CSV** - Download template from your campaigns tab 2. **Configure your agent** - Set up prompts and custom variables 3. **Upload & configure** - Submit CSV with campaign settings 4. **Start calling** - Use the returned `list_id` to start your campaign ## CSV file requirements **Important File Rules:** * CSV format only * Must include "Mobile Number" column * Phone numbers need country code, for example `+919876543210` * Download the exact template from the campaign tab for your agent ### Example CSV Structure ``` Mobile Number,Name,Company,Email +918882876897,John Doe,XYZ Corp,user@example.com +918882876898,Jane Smith,ABC Inc,user@example.com ``` ## Configuration parameters ### Required Fields | Field | Format | Example | | - | - | - | | **CSV File** | .csv file | contacts.csv | | **Agent ID** | UUID | 830f767a-397e-4b39-82ff-235cd344e2f9 | | **Campaign Name** | Text | "Q1 Sales Outreach" | | **Country Code** | Phone dialing prefix | "+91", "+1" | | **Campaign Start Time** | DD/MM/YYYY, HH:MM | 18/10/2026, 09:00 | | **Campaign End Time** | DD/MM/YYYY, HH:MM | 18/10/2026, 21:00 | ### Optional Settings | Setting | Default | Purpose | | - | - | - | | Remove Invalid Rows | false | Auto-remove bad data | | Transliterate Callee Name | false | Convert to English | ## CSV File Format **Download the exact CSV template from your campaigns tab** to get the correct format according to your specific agent configuration. The required columns vary based on your agent's custom variables. `campaign_start_time` and `campaign_end_time` use the timezone in `call_config.call_time.timezone`. The backend expects the `DD/MM/YYYY, HH:MM` format and validates that the start time is in the future. ## Variable mapping Connect your CSV columns to agent variables so your AI can use the contact data during calls. ### How It Works Map CSV column names to your agent's custom variables: ```json theme={null} { "callee_name": "Name", "company_name": "Company", "email": "Email", "custom_field": "Custom Field 1" } ``` ### Using Variables Reference mapped variables in your agent prompt with `@{{variable_name}}`: * `@{{callee_name}}` becomes "John Doe" * `@{{company_name}}` becomes "XYZ Corp" ## Call configuration Control when and how your campaign calls are made: ### Call timing and limits ```json theme={null} { "idle_timeout_warning": 10, "idle_timeout_end": 15, "max_call_length": 300, "call_time": { "call_start_time": "09:00", "call_end_time": "18:00", "timezone": "Asia/Kolkata" } } ``` ### Retry settings ```json theme={null} { "call_retry_config": { "retry_count": 3, "retry_busy": 30, "retry_not_picked": 30, "retry_failed": 30 } } ``` ## What happens next? ### Success Response You'll receive a `list_id`. Save it because you need it to start the campaign. ```json theme={null} { "message": "Contacts imported successfully!", "list_id": "123e4567-e89b-12d3-a456-426614174000", "total_rows": 100, "successful_rows": 98, "failed_rows": 2 } ``` ### Next Steps 1. **Save the `list_id`** from the response 2. **[Start your campaign](/api-reference/endpoint/campaign/start-campaign)** using the `list_id` 3. **[Monitor progress](/api-reference/endpoint/campaign/get-all-campaigns)** and view results For 5,000+ row CSVs, the beta flow returns `bulk_list_id` and requires status polling before calls can start. ### Error Handling If upload fails, check: * CSV format and required columns * Valid phone number format with country codes * Agent ID exists and is active * API key permissions Set `remove_invalid_rows=true` to automatically skip problematic contacts instead of failing the entire upload. # Upload large campaign CSV (Beta) Source: https://docs.ringg.ai/api-reference/endpoint/campaign/upload-large-campaign-csv post /campaign/upload-csv Upload a 5,000+ row campaign CSV for asynchronous processing. This endpoint is beta. Use it only when large-campaign access is enabled for your workspace. For most campaigns, use [Upload campaign contact list](/api-reference/endpoint/campaign/upload-campaign-contact-list) and then [Start campaign](/api-reference/endpoint/campaign/start-campaign). `POST /campaign/upload-csv` starts the beta large-campaign flow. It accepts a large CSV and campaign configuration, then returns a `bulk_list_id` that you use for status polling, balance checking, and async call scheduling. ## Endpoint ```text theme={null} POST /campaign/upload-csv ``` ## When to use Use this endpoint for CSVs with 5,000 or more rows. It lets Ringg process and validate the upload asynchronously instead of making the initial upload request wait for the full import. ## Request guidance Send `multipart/form-data`. Use the same CSV template and campaign fields as the standard `POST /campaign/save` flow. | Field | Required | Notes | | - | - | - | | `file` | Yes | CSV file with `Mobile Number` and assistant variable columns | | `agent_id` | Yes | Assistant that will handle the campaign calls | | `campaign_name` | Yes | Human-readable campaign name | | `country_code` | Yes | Dialing prefix, such as `+91` or `+1` | | `variables_map` | Yes | JSON string mapping assistant variables to CSV columns | | `campaign_start_time` | Yes | Campaign start time in `DD/MM/YYYY, HH:MM` format | | `campaign_end_time` | Yes | Campaign end time in `DD/MM/YYYY, HH:MM` format | | `call_config` | Yes | JSON string for call window, retry, and call limit settings | | `remove_invalid_rows` | No | Set to `true` to skip invalid rows when supported | | `transliterate_callee_name` | No | Set to `true` when callee names should be transliterated | ```bash theme={null} curl --request POST "https://prod-api.ringg.ai/ca/api/v0/campaign/upload-csv" \ --header "X-API-KEY: $RINGG_API_KEY" \ --form 'agent_id="your-agent-id"' \ --form 'campaign_name="Renewal reminders - large batch"' \ --form 'country_code="+91"' \ --form 'variables_map="{\"mobile_number\":\"Mobile Number\",\"callee_name\":\"Name\"}"' \ --form 'campaign_start_time="18/10/2026, 09:00"' \ --form 'campaign_end_time="18/10/2026, 18:00"' \ --form 'call_config="{\"call_time\":{\"call_start_time\":\"09:00\",\"call_end_time\":\"18:00\",\"timezone\":\"Asia/Kolkata\"}}"' \ --form "file=@contacts-5000-plus.csv" ``` Do not set `Content-Type` manually in browser or Node `FormData` clients. Let the client include the multipart boundary. ## Response guidance Persist the returned `bulk_list_id`. It identifies the uploaded list for every later beta endpoint. ```json theme={null} { "bulk_list_id": "123e4567-e89b-12d3-a456-426614174000", "status": "uploaded", "message": "CSV upload accepted for processing" } ``` ## Next step Poll [Get large campaign upload status](/api-reference/endpoint/campaign/get-large-campaign-upload-status) until the upload is processed. Do not check balance or start calls until processing is complete. # Download Call History Source: https://docs.ringg.ai/api-reference/endpoint/history/download-call-history post /calling/history/download Downloads call history data in CSV format. Supports bulk download of call records with optional filtering. Use 'include_analysis=true' to include call analysis data (platform_analysis and client_analysis) in the export. ## Download Call History This endpoint queues call history data for download and sends it via email. The export includes comprehensive call records with optional filtering capabilities. **Email Delivery**: * Large datasets may take several minutes to process * You'll receive an email with the download link once processing is complete ## Key Features * **Comprehensive Data Export**: Includes call details, transcripts, recordings, and metadata * **Flexible Filtering**: Filter by date range, agent, status, and more * **Analysis Data**: Optionally include call analysis and insights * **Email Delivery**: Secure download link sent to your email ## Export Format The download contains a CSV file with the following data: * Call basic information (ID, numbers, duration, cost) * Call status and timestamps * Agent and campaign details * Transcript and recording URLs * Custom variables and analysis data (when enabled) ## Important Notes * **Processing Time**: Large exports may take 5-10 minutes to process * **File Size**: Very large datasets are automatically compressed * **Recording Validity**: Recording URLs in the export are valid for 24 hours after each call. Download any recordings you need to keep within that window. # Get Call Details Source: https://docs.ringg.ai/api-reference/endpoint/history/get-call-details get /calling/call-details Retrieves detailed information about a specific call using its unique identifier. Use the send_analysis parameter to include analysis data in the response. Fetch a detailed record for one call. Use this when a user opens a call detail view or when support needs the full context for a specific `call_id`. ## When to use * Show transcript, recording, status, and metadata for one call. * Debug a failed or unexpected call. * Fetch analysis for a call after receiving a webhook event. ## Integration notes * Pass the unique call ID as the `id` query parameter. * Use `send_analysis=true` only when the caller needs analysis data; this keeps lightweight detail views faster. * Store the `call_id` returned by call initiation and webhook payloads. * The returned recording URL is valid for 24 hours after the call. Download and store the recording within that window if you need to retain it. # Get Call History Source: https://docs.ringg.ai/api-reference/endpoint/history/get-call-history get /calling/history Retrieves the history of calls made through the Ringg AI platform with optional filtering and pagination. Retrieve call records for dashboards, support tools, exports, and reconciliation. This is the polling counterpart to webhooks. ## When to use * Show recent calls in your product. * Reconcile webhook events with stored call records. * Filter campaign results by `bulk_list_id`. * Debug a recipient's latest call status. ## Query guidance Use date ranges and pagination for production dashboards. Add filters such as `agent_id`, `status`, `call_type`, or `bulk_list_id` to keep responses focused. ## Production note Prefer webhooks for real-time workflows. Use call history for dashboards, backfills, and periodic consistency checks. # Create Knowledge Base Source: https://docs.ringg.ai/api-reference/endpoint/kb/create-knowledge-base post /external/kb Creates a new non-deterministic knowledge base. Rate limit: 10 requests per hour per workspace. File size limit: 2 MB per file, 5 MB total. Maximum 10 files and 20 URLs per request. ## Create Knowledge Base Create a new non-deterministic knowledge base that can be used to provide context and information to your AI agents. Knowledge bases support multiple content types including files, URLs, and FAQs. **Rate Limits**: * Maximum 10 requests per hour per workspace * File size limit: 2 MB per file, 5 MB total * Maximum 10 files and 20 URLs per request ## Content Types ### Files Upload documents (PDF, TXT, DOCX, etc.) to provide structured information to your knowledge base. * Max 10 files per request * 2 MB per file limit * 5 MB total size limit ### URLs Index web pages to automatically extract and store their content. * Max 20 URLs per request * URLs are crawled and indexed automatically * Content is refreshed periodically ### FAQs Provide question-answer pairs for deterministic responses to common queries. ```json theme={null} { "faqs": "[{\"question\": \"What is your return policy?\", \"answer\": \"30-day money back guarantee\"}]" } ``` ## Processing Status Knowledge base creation is asynchronous. The response includes: * `kb_id`: Unique identifier for the knowledge base * `processing_status`: Current status (`pending`, `processing`, `completed`) * `files_queued`: Number of files being processed Use the [Get Knowledge Base by ID](/api-reference/endpoint/kb/get-knowledge-base-by-id) endpoint to check processing status. ## Important Notes * **Asynchronous Processing**: Files and URLs are processed in the background * **Content Updates**: Use the [Edit Knowledge Base](/api-reference/endpoint/kb/edit-knowledge-base) endpoint to update content * **Agent Integration**: Link knowledge bases to agents via the assistant configuration # Delete Knowledge Base Source: https://docs.ringg.ai/api-reference/endpoint/kb/delete-knowledge-base delete /external/kb/{kb_id} Deletes a knowledge base by its ID. Rate limit: 10 requests per minute per workspace. ## Delete Knowledge Base Permanently delete a knowledge base and all its associated content including files, URLs, and FAQs. **Permanent Action**: * This operation cannot be undone * All associated content will be permanently deleted * Agents using this knowledge base will lose access to its content * Rate limit: Maximum 10 requests per minute per workspace ## Before Deleting Consider these steps before deleting a knowledge base: 1. **Check Agent Dependencies**: Verify no active agents are using this knowledge base 2. **Backup Important Content**: Download or note any critical information 3. **Review Usage**: Check if the knowledge base is referenced in any campaigns ## Response On successful deletion, you'll receive: * `message`: Confirmation message * `kb_id`: ID of the deleted knowledge base ## Common Use Cases * **Cleanup**: Remove test or outdated knowledge bases * **Reorganization**: Delete before recreating with updated structure * **Resource Management**: Free up workspace resources **Agent Impact**: If agents are actively using this knowledge base, they will immediately lose access. Update agent configurations before deletion to avoid disruptions. ## Alternative: Edit Instead Consider using [Edit Knowledge Base](/api-reference/endpoint/kb/edit-knowledge-base) instead if you only need to: * Remove specific files or URLs * Update content * Add new information Editing preserves the knowledge base ID and agent associations. # Edit Knowledge Base Source: https://docs.ringg.ai/api-reference/endpoint/kb/edit-knowledge-base patch /external/kb Edits an existing knowledge base by adding or removing files, URLs, and FAQs. Rate limit: 20 requests per hour per workspace. File size limit: 2 MB per file, 5 MB total. ## Edit Knowledge Base Update an existing knowledge base by adding new content or removing existing files, URLs, and FAQs. This endpoint allows you to maintain and refine your knowledge base over time. **Rate Limits**: * Maximum 20 requests per hour per workspace * File size limit: 2 MB per file, 5 MB total ## Adding Content Add new files, URLs, or FAQs to expand your knowledge base: * `new_files`: Upload additional documents * `new_urls`: Index new web pages * `new_faqs`: Add more question-answer pairs ## Removing Content Remove outdated or incorrect content using IDs: * `files_to_remove`: JSON array of file IDs * `urls_to_remove`: JSON array of URLs * `faqs_to_remove`: JSON array of FAQ IDs ### Example Removal ```json theme={null} { "files_to_remove": "[\"7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d\"]", "urls_to_remove": "[\"https://example.com/old-page\"]", "faqs_to_remove": "[\"9c0d1e2f-3a4b-5c6d-7e8f-9a0b1c2d3e4f\"]" } ``` **Get Content IDs**: Use [Get Knowledge Base by ID](/api-reference/endpoint/kb/get-knowledge-base-by-id) to retrieve file IDs, URLs, and FAQ IDs before removing them. ## Response Details The response includes: * `items_removed`: Count of items successfully removed * `new_files_queued`: Count of new files being processed * `new_files`: Array of newly added files with their IDs and processing status ## Important Notes * **Atomic Operations**: Additions and removals are processed together * **Processing Time**: New content is processed asynchronously * **No Rollback**: Removals are permanent - ensure you have the correct IDs # Get All Knowledge Bases Source: https://docs.ringg.ai/api-reference/endpoint/kb/get-all-knowledge-bases get /external/kb/all Retrieves all knowledge bases for the current workspace. Rate limit: 60 requests per hour per workspace. ## Get All Knowledge Bases Retrieve a list of all knowledge bases in your workspace with basic information about each one. **Rate Limit**: Maximum 60 requests per hour per workspace ## Response Format Returns an array of knowledge base objects, each containing: * `kb_id`: Unique identifier * `kb_name`: Name of the knowledge base * `type`: Knowledge base type (e.g., "non\_deterministic") * `created_at`: Creation timestamp ## Use Cases ### Dashboard View Display all knowledge bases in your application or dashboard: ```javascript theme={null} const response = await fetch('https://api.ringg.ai/external/kb/all', { headers: { 'X-API-KEY': 'your-api-key' } }); const knowledgeBases = await response.json(); ``` ### Dropdown Selection Populate a dropdown for users to select a knowledge base when configuring agents. ### Audit and Management * Review all knowledge bases in your workspace * Identify unused or outdated knowledge bases * Track knowledge base creation dates ## Getting Detailed Information This endpoint returns only basic information. For detailed content including files, URLs, and FAQs, use [Get Knowledge Base by ID](/api-reference/endpoint/kb/get-knowledge-base-by-id) with a specific `kb_id`. **Pagination**: Currently, this endpoint returns all knowledge bases. For workspaces with many knowledge bases, consider caching this data to reduce API calls. ## Example Response ```json theme={null} [ { "kb_id": "550e8400-e29b-41d4-a716-446655440000", "kb_name": "Product Documentation", "type": "non_deterministic", "created_at": "2024-12-16T13:03:29.947147+00:00" }, { "kb_id": "660e8400-e29b-41d4-a716-446655440001", "kb_name": "Customer Support FAQs", "type": "non_deterministic", "created_at": "2024-12-17T10:15:42.123456+00:00" } ] ``` # Get Knowledge Base by ID Source: https://docs.ringg.ai/api-reference/endpoint/kb/get-knowledge-base-by-id get /external/kb/{kb_id} Retrieves a specific knowledge base by its ID. Rate limit: 60 requests per hour per workspace. ## Get Knowledge Base by ID Retrieve detailed information about a specific knowledge base, including all files, URLs, and FAQs along with their processing status. **Rate Limit**: Maximum 60 requests per hour per workspace ## Response Structure The response includes comprehensive details about your knowledge base: ### Basic Information * `kb_id`: Unique identifier * `kb_name`: Name of the knowledge base * `status`: Overall processing status (`pending`, `processing`, `completed`, `failed`) * `created_at`: Creation timestamp * `updated_at`: Last modification timestamp ### Content Arrays #### Files Each file object includes: * `file_id`: Unique identifier for removal operations * `file_type`: Document type (pdf, txt, docx, etc.) * `file_size`: Size in bytes * `filename`: Original filename * `file_path`: Storage path #### URLs Each URL object includes: * `file_id`: Unique identifier for removal operations * `file_type`: Content type * `file_size`: Extracted content size * `url`: Original URL * `file_path`: Storage path for indexed content #### FAQs Each FAQ object includes: * `file_id`: Unique identifier for removal operations * `file_type`: Always "faq" * `file_size`: Content size * `content`: Question and answer object ## Use Cases * **Check Processing Status**: Monitor when content is ready for use * **Get Content IDs**: Retrieve file and FAQ IDs for removal operations * **Audit Content**: Review what's currently in your knowledge base * **Debug Issues**: Identify failed or pending items **Processing Time**: Large files or many URLs may take several minutes to process. Check the `status` field to confirm completion. # Get Workspace Numbers Source: https://docs.ringg.ai/api-reference/endpoint/numbers/get-workspace-numbers get /workspace/numbers Retrieves a list of available phone numbers in your workspace. List phone numbers available in the workspace. Outbound calls and campaigns use these numbers as caller IDs. Inbound assistants use assigned numbers as the numbers users dial. ## When to use * Populate a caller-number selector before starting calls. * Find the `from_number_id` for `POST /calling/outbound/individual`. * Confirm imported BYOT numbers are available after telephony setup. ## Integration notes * Store the selected `from_number_id` alongside your assistant or campaign configuration. * Numbers must be provisioned, imported, or assigned in the Ringg workspace before they can be used. * For campaigns, pass selected numbers in `from_numbers`. # Allocate Concurrency to a Ringg Space Source: https://docs.ringg.ai/api-reference/endpoint/sub-workspace/allocate-concurrency patch /workspace/sub/{sub_workspace_id}/concurrency Sets how many concurrent calls one Ringg Space may run, taken from the family's capacity (bought on the primary). Allocations across all Ringg Spaces cannot exceed the capacity. In an individual-billing family the allocation is also the Ringg Space's hard ceiling; in a common-billing family the ceiling is the family total, so idle capacity flows to whichever Ringg Space is busy. Set how many concurrent calls one Ringg Space may run. Capacity is bought on the primary; the allocations across all Ringg Spaces cannot exceed it. ## When to use * Giving a newly created Ringg Space its first capacity (it starts at `0` and cannot call until allocated). * Rebalancing capacity between clients or teams. ## Request parameters | Parameter | Type | Required | Description | | - | - | - | - | | `sub_workspace_id` | string (path) | Yes | ID of the Ringg Space. | | `concurrency` | integer | Yes | Concurrent calls to allocate, `0` or more. `0` stops the Ringg Space from calling. | ## Integration notes * Authenticate with the primary workspace's API key. * The value is absolute, not a delta. Lowering an allocation always succeeds; raising it must fit `family.concurrency_available` from [Get Ringg Spaces](/api-reference/endpoint/sub-workspace/get-sub-workspaces). * `limit_concurrency` in the response is the persisted ceiling. In an individual-billing family it equals the allocation. In a common-billing family it is the family total, because idle capacity is shared, so it can be larger than `concurrency`. * This is the only allocation endpoint that applies to common-billing families; money is pooled on the primary there. ## Error responses * **400**: `Only 30 concurrent calls are available to allocate from the parent workspace (capacity 50, 20 already allocated to other sub-workspaces).` — the allocation does not fit. * **400**: `Sub-workspaces cannot have their own sub-workspaces.` — the key belongs to a Ringg Space. * **401**: Invalid or missing API key. * **403**: `Sub-workspaces are not enabled for this workspace.` * **404**: `Sub-workspace not found` — no active Ringg Space with this id under your primary. * **422**: `sub_workspace_id` is not a UUID, or `concurrency` is negative or missing. ## Example ```bash theme={null} curl --request PATCH "https://prod-api.ringg.ai/ca/api/v0/workspace/sub/b7c1f0e2-4d3a-4a91-9f2e-8c1d5a6b7e30/concurrency" \ --header "X-API-KEY: $RINGG_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "concurrency": 20 }' ``` ## Common follow-up Buy more capacity on the primary when `family.concurrency_available` reaches `0`, then allocate the new slots here. # Create Ringg Space Source: https://docs.ringg.ai/api-reference/endpoint/sub-workspace/create-sub-workspace post /workspace/sub Creates a new Ringg Space under the primary workspace that owns the API key. The Ringg Space is a full workspace (own assistants, numbers, campaigns, call history, members) that starts with zero balance or credit limit and zero concurrency; allocate to it afterwards. Every member of the primary is given inherited access to it. The first Ringg Space turns the primary into a family in individual billing mode. Create a new Ringg Space under the primary workspace that owns the API key. The Ringg Space starts empty: no balance or credit limit, no concurrency, no assistants, and no API key. ## When to use * Onboarding a new client, brand, or team that needs its own isolated assistants, numbers, and call history. * Automating tenant provisioning from your own admin system. ## Request parameters | Parameter | Type | Required | Description | | - | - | - | - | | `name` | string | Yes | Display name, 1 to 100 characters. Surrounding whitespace is trimmed; a blank name is rejected. | ## Integration notes * Authenticate with the **primary** workspace's API key. A Ringg Space's key returns `400`. * Store the returned `sub_workspace.id`; every allocation call needs it. * The first Ringg Space you create turns the primary into a family in **individual** billing mode. Contact Ringg support if the family should use common billing instead. * Every member of the primary automatically gets access to the new Ringg Space. * The response never contains an API key. See [Ringg Spaces](/api-reference/endpoint/sub-workspace/overview#create-an-assistant-inside-a-ringg-space) for how to get one. ## Error responses * **400**: `Sub-workspaces cannot have their own sub-workspaces.` — the key belongs to a Ringg Space. * **401**: Invalid or missing API key. * **403**: `Sub-workspaces are not enabled for this workspace.` * **422**: Missing or blank `name`, or a name longer than 100 characters. ## Example ```bash theme={null} curl --request POST "https://prod-api.ringg.ai/ca/api/v0/workspace/sub" \ --header "X-API-KEY: $RINGG_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "name": "Mumbai Collections" }' ``` ## After creation Give the Ringg Space capacity with [Allocate Concurrency](/api-reference/endpoint/sub-workspace/allocate-concurrency) and, in an individual family, a [credit limit](/api-reference/endpoint/sub-workspace/reallocate-credit-limits) or [balance](/api-reference/endpoint/sub-workspace/reallocate-credit-balances). Then generate its API key in the dashboard and [create an assistant](/api-reference/endpoint/assistant/create-agent) with that key. # Get Ringg Spaces Source: https://docs.ringg.ai/api-reference/endpoint/sub-workspace/get-sub-workspaces get /workspace/sub Returns the whole family in one call: the primary's summary, one row per active Ringg Space with its allocation, members and month-to-date usage, and the family totals. Works on a primary that has no Ringg Spaces yet (empty list). Return the whole family in one call: the primary's summary, one row per active Ringg Space with its allocation, member counts, and month-to-date usage, and the family totals. ## When to use * A tenant dashboard in your own admin tool. * Checking headroom before allocating concurrency or credit. * Reconciling per-client usage at month end. ## Reading the response * `billing` on each row is `{account_type, currency, total_available_credits}` for prepaid and `{account_type, currency, credit_limit, utilized_limit}` for postpaid. In a common-billing family the Ringg Space rows carry `null` limits because charges pool on the primary. * `family` always has the concurrency keys and `is_individual_entity`. Postpaid families add `credit_limit`, `utilized_total`, and `available_total`. Prepaid families add `available_pot` (the primary's unallocated money) and `family_available_total`; individual prepaid families also add `allocated_balance_total`. * `usage_this_period` is the value of completed calls since the 1st of the current month in the `Asia/Kolkata` timezone, in the workspace's billing currency. * `limit_concurrency` is a Ringg Space's ceiling: its own allocation in an individual family, the family total in a common family. * Amounts are JSON numbers here. ## Integration notes * Authenticate with the primary workspace's API key. * Works on a primary with no Ringg Spaces yet; `sub_workspaces` is then an empty list. * Archived Ringg Spaces are not listed. ## Error responses * **400**: `Sub-workspaces cannot have their own sub-workspaces.` — the key belongs to a Ringg Space. * **401**: Invalid or missing API key. * **403**: `Sub-workspaces are not enabled for this workspace.` ## Example ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/workspace/sub" \ --header "X-API-KEY: $RINGG_API_KEY" ``` # List Family Members Source: https://docs.ringg.ai/api-reference/endpoint/sub-workspace/list-family-members get /workspace/sub/members Lists every person with access anywhere in the family and where that access comes from: members of the primary (who inherit access to every Ringg Space) and people added directly to one or more Ringg Spaces. List everyone with access anywhere in the family and where that access comes from. Members of the primary inherit access to every Ringg Space; people added directly to a Ringg Space see only that Ringg Space. ## When to use * Access audits across all client or team workspaces. * Showing who can reach a given Ringg Space in your own admin tool. ## Reading the response * `scope` is `primary` for members of the primary (they have inherited access to every current and future Ringg Space) and `sub` for people added only to Ringg Spaces. * `sub_workspace_ids` lists direct Ringg Space memberships only. Inherited access is not repeated there. * `permissions_by_workspace` gives the effective permissions per workspace id, inherited rows included, so you can render access without re-deriving it. * `invite_status` is `success` or `pending`. ## Integration notes * Authenticate with the primary workspace's API key. * To add or remove people, use the workspace member endpoints against the relevant workspace; this endpoint is read-only. ## Error responses * **400**: `Sub-workspaces cannot have their own sub-workspaces.` — the key belongs to a Ringg Space. * **401**: Invalid or missing API key. * **403**: `Sub-workspaces are not enabled for this workspace.` ## Example ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/workspace/sub/members" \ --header "X-API-KEY: $RINGG_API_KEY" ``` # Ringg Spaces Source: https://docs.ringg.ai/api-reference/endpoint/sub-workspace/overview Run a family of workspaces from one primary: create Ringg Spaces for clients or teams, and allocate concurrency, credit limits, or balances to them over the API. A Ringg Space family is one **primary** workspace with any number of **Ringg Spaces** under it, typically one per client, brand, or team. Each Ringg Space is a full workspace with its own assistants, numbers, campaigns, call history, API key, and members, fully isolated from its siblings. The primary is the management console: it holds the family's money and calling capacity, shares them out, and sees every Ringg Space's data in one place. The primary itself does not place calls. Ringg Spaces are enabled per customer. If the endpoints below return `403 Sub-workspaces are not enabled for this workspace.`, contact Ringg support to turn the feature on for your primary workspace. ## Billing modes The family's billing mode is set when it is created and applies to every Ringg Space. | Mode | Money | What you allocate over the API | | - | - | - | | **Individual** | Each Ringg Space has its own wallet (prepaid) or credit limit (postpaid). | Concurrency, plus [credit limits](/api-reference/endpoint/sub-workspace/reallocate-credit-limits) (postpaid) or [credit balances](/api-reference/endpoint/sub-workspace/reallocate-credit-balances) (prepaid). | | **Common** | One shared wallet or credit limit on the primary; every Ringg Space spends from it and one consolidated invoice covers the family. | Concurrency only. The credit-limit and credit-balance endpoints return `400` because there is nothing per Ringg Space to allocate. | Concurrency (how many calls can run at once) is bought on the primary and allocated to Ringg Spaces in both modes. In an individual family each allocation is that Ringg Space's hard ceiling. In a common family idle capacity flows to whichever Ringg Space is busy, so a Ringg Space's ceiling is the family total. ## Authentication Call every endpoint in this section with the **primary workspace's** API key in `X-API-KEY`. The key identifies the family; there is no workspace header to set. A Ringg Space's API key cannot manage the family. Using one returns `400 Sub-workspaces cannot have their own sub-workspaces.` ## Endpoints * [Create Ringg Space](/api-reference/endpoint/sub-workspace/create-sub-workspace) — `POST /workspace/sub` * [Get Ringg Spaces](/api-reference/endpoint/sub-workspace/get-sub-workspaces) — `GET /workspace/sub`, the whole family in one call * [List Family Members](/api-reference/endpoint/sub-workspace/list-family-members) — `GET /workspace/sub/members` * [Allocate Concurrency](/api-reference/endpoint/sub-workspace/allocate-concurrency) — `PATCH /workspace/sub/{sub_workspace_id}/concurrency` * [Reallocate Credit Limits](/api-reference/endpoint/sub-workspace/reallocate-credit-limits) — `PATCH /workspace/sub/credit-limits`, postpaid individual families * [Reallocate Credit Balances](/api-reference/endpoint/sub-workspace/reallocate-credit-balances) — `PATCH /workspace/sub/credit-balances`, prepaid individual families ## Money formats The read endpoints and the concurrency endpoint return amounts as JSON numbers (`200000.0`). The two allocation endpoints return amounts as decimal strings (`"200000.00"`). Parse both before doing arithmetic. ## Create an assistant inside a Ringg Space There is no separate endpoint for this. A Ringg Space is a normal workspace, so use its own API key with the existing [create assistant](/api-reference/endpoint/assistant/create-agent) endpoint and the assistant is created inside that Ringg Space, invisible from the primary and from sibling Ringg Spaces. The same applies to every other endpoint in this reference: numbers, campaigns, calls, and history all scope to the workspace that owns the key. A new Ringg Space starts without an API key. To get one, switch into the Ringg Space in the [Ringg AI dashboard](https://www.ringg.ai/dashboard/api), open **Settings → API Key**, and generate it there. The key is shown once, exactly as described in [Authentication](/api-reference/quick-start/authentication). Keys cannot be created or rotated through the API. ## Typical flow 1. Create the Ringg Space with the primary's key. 2. Allocate concurrency to it, and a credit limit or balance in an individual family. 3. Generate the Ringg Space's API key in the dashboard. 4. Create assistants, attach numbers, and run campaigns with the Ringg Space's key. 5. Watch usage across the family with [Get Ringg Spaces](/api-reference/endpoint/sub-workspace/get-sub-workspaces). # Reallocate Credit Balances Source: https://docs.ringg.ai/api-reference/endpoint/sub-workspace/reallocate-credit-balances patch /workspace/sub/credit-balances Prepaid, individual-billing families only. Sets every active Ringg Space's wallet to an absolute balance; the net difference moves from or to the primary's unallocated pot, which must be able to cover it. Top up on the primary first, then allocate. Not applicable to common-billing families, where the wallet is shared on the primary. Set every Ringg Space's wallet to an absolute balance. The net difference moves from or to the primary's unallocated pot. Prepaid families in **individual** billing mode only. ## When to use * Distributing a top-up made on the primary across clients or teams. * Pulling unused balance back from one Ringg Space to fund another. ## Request parameters | Parameter | Type | Required | Description | | - | - | - | - | | `allocations` | object | Yes | Map of `sub_workspace_id` to its **new absolute balance**, not a delta. Must include **every active Ringg Space exactly once**. Values are `0` or more, two decimals. | ## Rules * The net amount moving out of the primary's pot cannot exceed what the pot holds. Top up on the primary first, then allocate. * A Ringg Space with a `0` balance cannot place calls; Ringg Spaces have no overdraft. * Every move is recorded in the workspace ledgers as a transfer, never as a charge. ## Integration notes * Authenticate with the primary workspace's API key. * Read the current wallets and `family.available_pot` from [Get Ringg Spaces](/api-reference/endpoint/sub-workspace/get-sub-workspaces) first, then send the full map. * Amounts in the response are **decimal strings** (`"5000.00"`), unlike the read endpoints. In a **common-billing** family the wallet is shared on the primary and Ringg Spaces hold nothing. This endpoint returns `400 This family uses a shared balance; per-sub wallets do not exist.` Allocate [concurrency](/api-reference/endpoint/sub-workspace/allocate-concurrency) instead. ## Error responses * **400**: `Balance allocation applies to prepaid families only.` * **400**: `This family uses a shared balance; per-sub wallets do not exist.` * **400**: `allocations name workspaces that are not active sub-workspaces of this family: [...]` * **400**: `allocations must cover every active sub-workspace; missing: [...]` * **400**: `These allocations need 9000.00 from the primary's pot, which only holds 4000.00. Lower the allocations or add balance to the primary workspace first.` * **401**: Invalid or missing API key. * **403**: `Sub-workspaces are not enabled for this workspace.` * **404**: `Workspace is not a sub-workspace family parent.` — the primary has no Ringg Spaces yet. * **422**: Empty map, negative value, or a key that is not a UUID. ## Example ```bash theme={null} curl --request PATCH "https://prod-api.ringg.ai/ca/api/v0/workspace/sub/credit-balances" \ --header "X-API-KEY: $RINGG_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "allocations": { "b7c1f0e2-4d3a-4a91-9f2e-8c1d5a6b7e30": 5000.00, "d21e8c55-9a0f-4c3b-86de-1f4b7a2c9e88": 3000.00 } }' ``` # Reallocate Credit Limits Source: https://docs.ringg.ai/api-reference/endpoint/sub-workspace/reallocate-credit-limits patch /workspace/sub/credit-limits Postpaid, individual-billing families only. Sets every active Ringg Space's credit limit in one call and optionally the family total. The map must name every active Ringg Space exactly once; a slice cannot drop below what that Ringg Space has already used this month, the slices cannot exceed the family total, and what remains for the primary must cover its own usage. Not applicable to common-billing families, where credit is pooled on the primary. Set every Ringg Space's credit limit in one call, and optionally the family total. Postpaid families in **individual** billing mode only. ## When to use * Splitting the family's credit limit across clients or teams. * Raising one client's limit at month end while keeping the total unchanged. ## Request parameters | Parameter | Type | Required | Description | | - | - | - | - | | `allocations` | object | Yes | Map of `sub_workspace_id` to its new credit limit. Must include **every active Ringg Space exactly once**. Values are absolute, `0` or more, two decimals. | | `parent_credit_limit` | number | No | New family total (the primary's credit limit). Omit to keep the current total. | ## Rules * A Ringg Space's limit cannot go below what it has already used this month. * The sum of all allocations cannot exceed the family total. Allocating less than the total is allowed; the remainder stays with the primary. * What remains with the primary must still cover the primary's own utilized amount. ## Integration notes * Authenticate with the primary workspace's API key. * Read the current limits and usage from [Get Ringg Spaces](/api-reference/endpoint/sub-workspace/get-sub-workspaces) first, then send the full map. * Amounts in the response are **decimal strings** (`"200000.00"`), unlike the read endpoints. In a **common-billing** family there are no limits per Ringg Space: every charge utilizes the primary's single credit limit. This endpoint returns `400 This family uses common billing; per-sub credit limits do not exist.` Allocate [concurrency](/api-reference/endpoint/sub-workspace/allocate-concurrency) instead. ## Error responses * **400**: `Credit-limit reallocation applies to postpaid families only.` * **400**: `This family uses common billing; per-sub credit limits do not exist.` * **400**: `Allocations must cover every active sub-workspace exactly once. Missing: [...]; unknown: [...].` * **400**: `Credit limit 100.00 for sub-workspace 'Mumbai Collections' is below its utilized amount 34210.50.` * **400**: `The total credit limit across sub-workspaces must not exceed the parent workspace's credit limit (500000.00); allocations sum to 600000.00.` * **400**: `These allocations would leave the primary workspace with 1000.00, below its already-utilized 12500.00. Lower the sub-workspace limits or raise the primary credit limit.` * **401**: Invalid or missing API key. * **403**: `Sub-workspaces are not enabled for this workspace.` * **404**: `Workspace is not a sub-workspace family parent.` — the primary has no Ringg Spaces yet. * **422**: Empty map, negative value, or a key that is not a UUID. ## Example ```bash theme={null} curl --request PATCH "https://prod-api.ringg.ai/ca/api/v0/workspace/sub/credit-limits" \ --header "X-API-KEY: $RINGG_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "parent_credit_limit": 500000.00, "allocations": { "b7c1f0e2-4d3a-4a91-9f2e-8c1d5a6b7e30": 200000.00, "d21e8c55-9a0f-4c3b-86de-1f4b7a2c9e88": 150000.00 } }' ``` # Get All User Workspaces Source: https://docs.ringg.ai/api-reference/endpoint/workspace/get-all-user-workspaces get /workspace/all Retrieves a list of all workspaces accessible to the current user. Return every workspace the authenticated user or API key can access. Most single-workspace integrations do not need this endpoint, but it is useful for admin panels that let operators switch context. ## When to use * Workspace switchers in internal tools. * Account audits where one user belongs to multiple workspaces. * Setup flows that need to confirm which workspace owns an API key. ## Integration notes Use the selected workspace's own API key for production call, campaign, and analytics operations. A row whose `parent_workspace_id` is set is a Ringg Space of that primary. See [Ringg Spaces](/api-reference/endpoint/sub-workspace/overview) for how families are managed over the API. # Get Workspace Info Source: https://docs.ringg.ai/api-reference/endpoint/workspace/get-workspace-info get /workspace Retrieves information about your current workspace. Use this endpoint as the first health check for a new integration. It verifies that your API key is valid and returns the workspace context Ringg will use for subsequent API calls. ## When to use * Confirm backend connectivity during setup. * Display workspace name, credit balance, or locked credits in an internal admin screen. * Verify that a copied API key belongs to the expected workspace before storing it. ## Integration notes * Send the API key in the `X-API-KEY` header. * Treat the returned `api_key` value as sensitive; do not log or expose it in client applications. * If this endpoint returns `401`, stop the flow and ask an administrator to check or regenerate the API key. ## Example ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/workspace" \ --header "X-API-KEY: $RINGG_API_KEY" ``` # List Workspace Users Source: https://docs.ringg.ai/api-reference/endpoint/workspace/list-workspace-users get /workspace/users Retrieves a list of all users in your current workspace. List users who belong to the current workspace. This is useful for internal admin tooling, audit views, and choosing users for campaign completion notifications. ## Query guidance * Use `limit` and `offset` for pagination. * Keep the API key server-side; do not call this endpoint from browser code. * Cache lightly if you show this in dashboards because workspace membership changes infrequently. ## Common follow-up Campaign APIs can notify selected users when a campaign completes. Use this endpoint to identify the user IDs available in the workspace. # API Overview Source: https://docs.ringg.ai/api-reference/quick-start/api-overview Understand the structure, versioning, and usage patterns of the Ringg AI API The Ringg AI API lets your backend create assistants, initiate calls, run campaigns, manage numbers, and retrieve post-call results. Use this page as the mental model before jumping into individual endpoints. ## API Architecture Ringg AI provides REST-style APIs that allow you to: * Create and manage AI voice assistants * Initiate individual and bulk calls * Embed voice assistants on websites * Manage reusable contact lists and phone numbers * Access call history and analytics * Subscribe assistants to webhook events ## Base URL All API requests should be made to the following base URL: ``` https://prod-api.ringg.ai/ca/api/v0 ``` ## Available Resources The Ringg AI API is organized around the following main resources: * **Workspace**: Verify authentication, manage workspace metadata, users, credits, and API keys. * **Ringg Spaces**: Create client or team workspaces under a primary workspace and allocate concurrency, credit limits, or balances to them. * **Assistant**: Create, list, fetch, and configure AI voice assistants. * **Numbers**: Fetch caller numbers available for outbound calls and campaigns. * **Calling**: Initiate individual outbound calls and inspect call history. * **Campaigns**: Upload campaign CSVs, start bulk calls, and monitor campaign state. * **Webhooks**: Subscribe assistants to call, recording, and analysis events. * **Analytics**: Build dashboards from call, number, duration, and classification metrics. ## Request and Response Formats Most Ringg API endpoints accept and return JSON. Use this header for `POST` and `PATCH` requests with JSON bodies: ``` Content-Type: application/json ``` For campaign CSV uploads and contact CSV uploads, send `multipart/form-data` and let your HTTP client set the `Content-Type` boundary. ## Common Headers All API requests require the following headers: * `X-API-KEY`: Workspace API key for authentication. * `Content-Type`: Set to `application/json` for JSON requests. Omit it for `FormData`/multipart requests unless your HTTP client requires otherwise. ## Core ID fields Store these IDs in your application. They are how Ringg APIs and webhooks connect. | ID | Where it comes from | Where it is used | | - | - | - | | `agent_id` | Assistant APIs or dashboard | Individual calls, campaigns, webhook subscriptions | | `from_number_id` | `GET /workspace/numbers` | Individual outbound calls | | `list_id` / `bulk_list_id` | Campaign upload | Campaign start, campaign analytics, history filters | | `call_id` | Call initiation, call history, webhooks | Webhook dedupe, call details, support debugging | ## Error Handling The Ringg AI API uses conventional HTTP response codes to indicate the success or failure of requests: * `2xx`: Success * `4xx`: Client errors (invalid request, authentication issues) * `5xx`: Server errors Error responses include a JSON body with details about what went wrong: ```json theme={null} { "error": { "code": "invalid_request", "message": "The mobile_number parameter is required" } } ``` ### Common Error Codes * **400**: Bad Request – Invalid parameters or request format * **401**: Unauthorized – Invalid or missing API key * **404**: Not Found – Resource doesn’t exist * **429**: Too Many Requests – Rate limit exceeded * **500**: Internal Server Error – Something went wrong on our end ## API Versioning The current version of the Ringg AI API is `v0`. The version is included in the base URL: ``` https://prod-api.ringg.ai/ca/api/v0 ``` Future versions will follow the pattern `v1`, `v2`, etc. We’ll provide ample notice before deprecating any API version to ensure a smooth transition for your applications. ## Pagination For endpoints that return lists of objects, the API supports pagination through the following query parameters: * **limit**: Number of items to return (default: 20, max: 100) * **offset**: Number of items to skip (default: 0) ## Recommended integration order 1. Verify API key with `GET /workspace`. 2. Select an assistant with `GET /agent/all`. 3. Select a number with `GET /workspace/numbers`. 4. Make one call with `POST /calling/outbound/individual`. 5. Configure webhooks for post-call events. 6. Add campaigns, analytics, and history views. ## Next Steps Now that you understand the basics of the Ringg AI API, you’re ready to start building! > Check out our detailed documentation for each resource to learn more about specific endpoints and capabilities. # Authentication Source: https://docs.ringg.ai/api-reference/quick-start/authentication Authenticate Ringg AI API requests with workspace API keys and keep keys secure in production. Ringg API requests use a workspace API key in the `X-API-KEY` header. Treat the API key as a server-side secret. Do not include it in browser JavaScript, mobile app bundles, public repositories, screenshots, logs, or support tickets. ## Get your API key 1. Log in to the [Ringg AI dashboard](https://www.ringg.ai/dashboard/api). 2. Open **Settings → API Key** from the dashboard sidebar. 3. Click **Generate API Key** and copy it immediately. The key is shown **only once**, at the moment it is generated. It cannot be retrieved afterwards — the dashboard stores only a masked form of it. If you lose it, regenerate from the same screen, which immediately revokes the old key and breaks any integration still using it. Ringg dashboard API key screen Regenerating an API key immediately invalidates the previous key. Update every backend service that uses the old key before relying on the new one. ## Send the API key ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/workspace" \ --header "X-API-KEY: $RINGG_API_KEY" ``` ```javascript theme={null} const response = await fetch("https://prod-api.ringg.ai/ca/api/v0/workspace", { headers: { "X-API-KEY": process.env.RINGG_API_KEY } }); if (!response.ok) { throw new Error(`Ringg API error: ${response.status} ${await response.text()}`); } const workspace = await response.json(); ``` ## Successful response `GET /workspace` is the simplest authentication check. ```json theme={null} { "workspace_info": { "id": "7251cb4b-72a3-42dc-9586-edf0328e2973", "name": "Acme Support Workspace", "created_at": "2026-04-15T10:30:00.000000+00:00", "credits": 3025.0, "locked_credits": 0.0 } } ``` ## Production practices * Store the key in a secret manager or environment variable. * Use one backend service as the integration boundary when possible. * Rotate the key if you suspect it's been exposed. * Avoid logging request headers. * Alert on unexpected usage volume or repeated `401` responses. * Use HTTPS for every API call. ## Troubleshooting | Response | Meaning | Fix | | - | - | - | | `401 Unauthorized` | Missing, invalid, or rotated API key | Verify `X-API-KEY` and redeploy secrets | | `403 Forbidden` | Key is valid but lacks permission for that action | Check workspace role and API permissions | | `429 Too Many Requests` | Rate limit exceeded | Back off and retry later | | `5xx` | Ringg server or upstream provider issue | Retry with backoff and log `call_id` or request context | ## Next steps Use the key to make your first call. Read your workspace details. # Quick Start Guide Source: https://docs.ringg.ai/api-reference/quick-start/guide Make your first Ringg AI outbound call from your backend and understand the minimum production flow. This guide takes you from API key to the first outbound call. The same IDs and patterns are used for campaigns, webhooks, and analytics. Run these requests from your backend. `X-API-KEY` is a workspace secret and should not be exposed in client-side code. ## Prerequisites * An active Ringg AI workspace * A workspace API key * An assistant configured for outbound calls * At least one phone number provisioned in the workspace * A server environment that can make HTTPS requests ## Step 1: Set the base URL All examples use the production API base URL: ```bash theme={null} export RINGG_BASE_URL="https://prod-api.ringg.ai/ca/api/v0" export RINGG_API_KEY="your-api-key" ``` ## Step 2: Verify authentication Start with `GET /workspace`. This confirms that the key is valid and that your backend can reach Ringg. ```bash cURL theme={null} curl --request GET "$RINGG_BASE_URL/workspace" \ --header "X-API-KEY: $RINGG_API_KEY" ``` ```javascript Node.js theme={null} const BASE_URL = "https://prod-api.ringg.ai/ca/api/v0"; async function ringg(path, options = {}) { const response = await fetch(`${BASE_URL}${path}`, { ...options, headers: { "X-API-KEY": process.env.RINGG_API_KEY, "Content-Type": "application/json", ...(options.headers || {}), }, }); if (!response.ok) { throw new Error(`Ringg API error: ${response.status} ${await response.text()}`); } return response.json(); } const workspace = await ringg("/workspace"); console.log(workspace.workspace_info.id); ``` ## Step 3: Choose an assistant Use `GET /agent/all` and select the assistant that should run the call. ```bash theme={null} curl --request GET "$RINGG_BASE_URL/agent/all" \ --header "X-API-KEY: $RINGG_API_KEY" ``` Save the selected `agent_id`. If you do not have an assistant yet, create one in the dashboard first, then come back to the API flow. ## Step 4: Choose a caller number Use `GET /workspace/numbers` and save the caller number ID you want Ringg to use. ```bash theme={null} curl --request GET "$RINGG_BASE_URL/workspace/numbers" \ --header "X-API-KEY: $RINGG_API_KEY" ``` Save the selected `from_number_id`. The individual-call API requires exactly one caller-number option: `from_number_id` or `from_number`. Use `from_number_id` when possible because it is stable across number formatting changes. ## Step 5: Make the call Call `POST /calling/outbound/individual` with the recipient, assistant, caller number, and any variables your assistant prompt uses. ```bash cURL theme={null} export AGENT_ID="your-agent-id" export FROM_NUMBER_ID="your-from-number-id" curl --request POST "$RINGG_BASE_URL/calling/outbound/individual" \ --header "X-API-KEY: $RINGG_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "name": "John Doe", "mobile_number": "+919876543210", "agent_id": "'"$AGENT_ID"'", "from_number_id": "'"$FROM_NUMBER_ID"'", "custom_args_values": { "callee_name": "John", "account_id": "ACC-42" }, "call_config": { "call_time": { "call_start_time": "09:00", "call_end_time": "18:00", "timezone": "Asia/Kolkata" }, "call_retry_config": { "retry_count": 1, "retry_busy": 30, "retry_not_picked": 30, "retry_failed": 30 } } }' ``` ```javascript Node.js theme={null} const call = await ringg("/calling/outbound/individual", { method: "POST", body: JSON.stringify({ name: "John Doe", mobile_number: "+919876543210", agent_id: process.env.RINGG_AGENT_ID, from_number_id: process.env.RINGG_FROM_NUMBER_ID, custom_args_values: { callee_name: "John", account_id: "ACC-42", }, call_config: { call_time: { call_start_time: "09:00", call_end_time: "18:00", timezone: "Asia/Kolkata", }, call_retry_config: { retry_count: 1, retry_busy: 30, retry_not_picked: 30, retry_failed: 30, }, }, }), }); console.log(call); ``` ## Step 6: Store the response A successful request returns a call object. Store the unique call ID in your application so you can join webhook events, history records, and support logs. ```json theme={null} { "Call Status": "success", "data": { "Unique Call ID": "dd6c63db-66c7-42ae-9a82-e4988bef428e", "Call Direction": "outbound", "Call Status": "registered", "From Number": "+918035737034", "To Number": "+919876543210", "Agent ID": "cdcf1b39-173a-4492-8396-c493123ea443", "System generated message": "Call initiated successfully" } } ``` ## Step 7: Receive results For production integrations, subscribe the assistant to webhook events so your application receives call state, recording, transcript, and analysis updates without polling. Recommended event: * `all_processing_completed`: one final event after transcript, recording, platform analysis, and custom analysis are available You can also use `GET /calling/history` for dashboards, reconciliation, and manual debugging. ## Production checklist * Keep `X-API-KEY` in a server secret manager. * Store `agent_id`, `from_number_id`, and returned `call_id`. * Send recipient numbers in E.164 format with country code. * Match `custom_args_values` keys to prompt placeholders like `@{{callee_name}}`. * Configure calling windows and retries in `call_config` for your market. * Make webhook handlers idempotent and respond with `2xx` quickly. ## Next steps Learn how API keys are created, sent, rotated, and protected. Review every supported request field for outbound calls. Subscribe to real-time call and analysis events. # Terminate All Calls by Agent ID Source: https://docs.ringg.ai/api-reference/terminate/agent PATCH /campaign/terminate Stop queued and retry calls for a specific assistant. Stop all active calls for a specific AI agent across all campaigns. This is useful when you need to halt all operations for a particular agent. **Impact**: This will terminate ALL active calls for the specified agent, regardless of which campaign they belong to. Your Ringg AI API key. ID of the agent whose calls should be terminated. Example: `196d8d88-591e-4e08-8324-2f928d152fff` ## When to Use This * **Agent Issues**: When an agent has problems and needs to stop all calls * **Emergency Stop**: Quick way to halt all calls for a specific agent * **Agent Maintenance**: Before updating or modifying an agent configuration * **Resource Management**: When an agent is consuming too many resources ## What Gets Terminated ✅ **Calls that will be terminated:** * Calls in "registered" status (queued and waiting) * Calls in "retry" status (scheduled for retry) Calls already in progress are marked as user-terminated so follow-up retries are suppressed when the live call ends. Already completed calls are not cancelled retroactively. **Note**: You can find your agent ID in the agent the top of your dashboard. # Terminate Calls by Call IDs Source: https://docs.ringg.ai/api-reference/terminate/call-ids PATCH /campaign/terminate Stop specific queued or retry calls by call ID. Stop individual calls by providing their unique call IDs. This gives you precise control over which calls to terminate. **Precision Required**: Make sure you have the correct call IDs. Invalid IDs will be ignored. Your Ringg AI API key. Array of call IDs to terminate. Example: `["86815974-8a87-4e32-9953-aca4f97868ab", "9ab99d2d-595c-4ca1-bab7-07d13f253156"]` ## When to Use This * **Selective Termination**: Stop only specific problematic calls * **Quality Control**: Terminate calls that aren't performing well * **Customer Requests**: Stop calls to specific contacts who requested removal * **Targeted Control**: Fine-grained call management ## How to Get Call IDs You can find call IDs from: * **Call History API**: Use the [Get Call History](/api-reference/endpoint/history/get-call-history) endpoint * **Real-time Monitoring**: Dashboard call monitoring section * **Webhook Notifications**: Call status updates include call IDs * **Campaign Reports**: Export campaign data to get call IDs **Tip**: You can terminate up to 100 calls in a single request for efficient bulk operations. # Terminate Calls by Campaign ID Source: https://docs.ringg.ai/api-reference/terminate/campaign PATCH /campaign/terminate Stop queued and retry calls for a campaign. Stop all active calls within a specific campaign. This terminates all queued and retry calls for the entire campaign. **Campaign Impact**: This will terminate ALL active calls in the specified campaign, affecting all contacts in that campaign. Your Ringg AI API key. ID of the campaign whose calls should be terminated. Example: `0b52ca2b-7767-4cb5-ac4c-b2a4f892a856` ## When to Use This * **Campaign Issues**: When a campaign has problems and needs to be stopped * **Content Problems**: If the campaign script or agent has errors * **Budget Management**: When campaign costs exceed budget * **Schedule Changes**: If campaign timing needs to be adjusted * **Quality Control**: When campaign performance is poor ## What Gets Terminated ✅ **Calls that will be terminated:** * All calls in "registered" status (queued and waiting) * All calls in "retry" status (scheduled for retry) * Affects ALL contacts within this specific campaign Calls from other campaigns are not affected. Calls already in progress are marked as user-terminated so follow-up retries are suppressed when the live call ends. Already completed calls are not cancelled retroactively. ## How to Get Campaign ID Find your campaign ID from: * **Campaign Dashboard**: Listed in your campaign management section * **Campaign API**: Use `/campaign/all` to list campaigns with IDs * **Campaign Creation**: Returned when you start a campaign * **Reports**: Campaign reports include the campaign ID **Note**: After terminating a campaign, you can restart it later if needed using the original campaign configuration. # Terminate Calls by Campaign Numbers Source: https://docs.ringg.ai/api-reference/terminate/campaign-numbers PATCH /campaign/terminate Stop calls to specific numbers within one campaign. Stop calls to specific phone numbers within a particular campaign. This gives you precise control to remove individual contacts from an active campaign. **Targeted Termination**: This only affects the specified numbers within the given campaign. The same numbers in other campaigns will continue. Your Ringg AI API key. ID of the campaign. Example: `0b52ca2b-7767-4cb5-ac4c-b2a4f892a856` Array of mobile numbers to terminate within the campaign (max 100). Example: `["+918882876897", "+918882876898"]` ## When to Use This * **Customer Requests**: When contacts ask to be removed from calls * **Data Quality**: Remove invalid or problematic numbers from campaign * **Compliance**: Honor do-not-call requests for specific numbers * **Selective Control**: Keep campaign running but exclude certain contacts ## Important Details ### Number Format * Correct: `+918882876897` with country code * Correct: `+14155550100` in international format * Wrong: `8882876897` without country code ### Limitations * **Maximum**: 100 numbers per request * **Scope**: Only affects specified campaign * **Status**: Only terminates registered/retry calls **Pro Tip**: Use this endpoint to implement real-time opt-out functionality in your application. Customers can request removal and you can immediately stop their calls. # Terminate Calls by Numbers Source: https://docs.ringg.ai/api-reference/terminate/numbers PATCH /campaign/terminate Stop queued and retry calls to specific numbers across campaigns. Stop ALL active calls to specific phone numbers across ALL campaigns. This is the most comprehensive way to ensure certain numbers are no longer contacted. **Global Impact**: This terminates calls to the specified numbers across ALL active campaigns, not just one campaign. Your Ringg AI API key. Array of mobile numbers to terminate calls for across all campaigns (max 100). Example: `["+918882876897", "+918882876898"]` ## When to Use This * **Global Opt-Outs**: Customers who want to stop ALL calls from your organization * **Legal Compliance**: Honor comprehensive do-not-call requests * **Data Privacy**: Implement "right to be forgotten" requests * **Emergency Stops**: Immediately halt all contact attempts to specific numbers * **Account Closure**: Stop all calls when customers close accounts ## Number Format Requirements * **Correct**: `+918882876897` with country code * **Correct**: `+14155550100` in international format * **Wrong**: `8882876897` without country code ### Limits & Constraints * **Maximum**: 100 numbers per request * **Rate Limits**: Standard API rate limits apply **Best Practice**: Use this endpoint for definitive opt-outs. For temporary or campaign-specific issues, consider using the campaign-numbers endpoint instead. # Making Your First Call Source: https://docs.ringg.ai/api-reference/tutorials/making-your-first-call Make one outbound call with Ringg AI, then verify the result through call history or webhooks. Use this tutorial when you already have a Ringg workspace and want to prove the end-to-end phone call flow from your backend. Keep `X-API-KEY` on your server. Do not expose it in browser or mobile source code. ## Prerequisites * A Ringg AI workspace and API key * An outbound assistant * A provisioned workspace number * A recipient phone number in E.164 format, for example `+919876543210` ## Step 1: Verify your workspace ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/workspace" \ --header "X-API-KEY: $RINGG_API_KEY" ``` If this returns `401`, fix the key before continuing. ## Step 2: Get an assistant ID ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/agent/all" \ --header "X-API-KEY: $RINGG_API_KEY" ``` Choose the assistant that should conduct the conversation and save its `agent_id`. ## Step 3: Get a caller number ID ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/workspace/numbers" \ --header "X-API-KEY: $RINGG_API_KEY" ``` Choose a number available in your workspace and save its `from_number_id`. ## Step 4: Initiate the outbound call ```bash theme={null} curl --request POST "https://prod-api.ringg.ai/ca/api/v0/calling/outbound/individual" \ --header "X-API-KEY: $RINGG_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "name": "John Doe", "mobile_number": "+919876543210", "agent_id": "your-agent-id", "from_number_id": "your-from-number-id", "custom_args_values": { "callee_name": "John", "order_id": "ORD-1042" } }' ``` `custom_args_values` should include every variable your assistant prompt references, such as `@{{callee_name}}` or `@{{order_id}}`. ## Step 5: Store the call ID A successful response includes a unique call ID. Store it in your system. ```json theme={null} { "Call Status": "success", "data": { "Unique Call ID": "dd6c63db-66c7-42ae-9a82-e4988bef428e", "Call Direction": "outbound", "Call Status": "registered", "From Number": "+918035737034", "To Number": "+919876543210", "Agent ID": "cdcf1b39-173a-4492-8396-c493123ea443", "System generated message": "Call initiated successfully" } } ``` ## Step 6: Check the result For manual verification, use call history: ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/calling/history?limit=20&offset=0" \ --header "X-API-KEY: $RINGG_API_KEY" ``` For production, configure webhooks and subscribe to `all_processing_completed` so your backend receives the final transcript, recording, and analysis data automatically. ## Status reference | Status | Meaning | | - | - | | `registered` | Call is queued and waiting to be processed | | `ongoing` | Call is in progress | | `retry` | Ringg will retry based on retry configuration | | `completed` | Recipient answered and the call reached a terminal completed state | | `failed` | Retries were exhausted or the provider failed the call | | `error` | Unexpected terminal error | | `cancelled` | Call was cancelled before completion | ## Next steps Receive call events instead of polling call history. Move from one call to campaign calling. # Setting Up Bulk Calls Source: https://docs.ringg.ai/api-reference/tutorials/setting-up-bulk-calls Upload a campaign CSV, map variables, start outbound calls, and monitor campaign results. Bulk calls are campaign-driven in Ringg. For most campaigns, create the campaign with `POST /campaign/save`, then start it with `POST /campaign/start`. For CSVs with 5,000 or more rows, use the beta large-campaign flow after it is enabled for your workspace. That path uploads and validates the CSV asynchronously before starting calls. ## Prerequisites * A workspace API key * An outbound assistant ID * One or more workspace number IDs * A CSV file with a `Mobile Number` column and any assistant variables ## Choose the campaign flow | Use case | Flow | Endpoints | | - | - | - | | Most campaign CSVs | Standard campaign flow | `POST /campaign/save` then `POST /campaign/start` | | 5,000+ row CSVs | Beta large-campaign flow | `POST /campaign/upload-csv`, `GET /campaign/upload-status/{bulk_list_id}`, `POST /campaign/check-balance/{bulk_list_id}`, `POST /campaign/make-call-async` | ## Step 1: Prepare the CSV Use the exact template from the Ringg dashboard when possible. At minimum, include the recipient number and every variable your assistant prompt uses. ```text theme={null} Mobile Number,Name,Policy ID,Due Date +919876543210,John Doe,POL-123,20/10/2026 +919876543211,Jane Smith,POL-124,21/10/2026 ``` ## Standard flow ### Step 2: Upload the campaign contact list `POST /campaign/save` accepts `multipart/form-data`. Do not set `Content-Type` manually in browser or Node `FormData` clients; let the client set the multipart boundary. ```javascript theme={null} const formData = new FormData(); formData.append("variables_map", JSON.stringify({ mobile_number: "Mobile Number", callee_name: "Name", policy_id: "Policy ID", due_date: "Due Date" })); formData.append("agent_id", process.env.RINGG_AGENT_ID); formData.append("country_code", "+91"); formData.append("campaign_name", "Renewal reminders"); formData.append("campaign_start_time", "18/10/2026, 09:00"); formData.append("campaign_end_time", "18/10/2026, 18:00"); formData.append("call_config", JSON.stringify({ call_time: { call_start_time: "09:00", call_end_time: "18:00", timezone: "Asia/Kolkata" }, call_retry_config: { retry_count: 1, retry_busy: 30, retry_not_picked: 30, retry_failed: 30 } })); formData.append("file", csvFile); const uploadResponse = await fetch("https://prod-api.ringg.ai/ca/api/v0/campaign/save", { method: "POST", headers: { "X-API-KEY": process.env.RINGG_API_KEY }, body: formData }); const uploadedCampaign = await uploadResponse.json(); console.log(uploadedCampaign.list_id); ``` Save the returned `list_id`; it is required to start the campaign. ### Step 3: Choose caller numbers ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/workspace/numbers" \ --header "X-API-KEY: $RINGG_API_KEY" ``` Pick one or more number IDs to use as `from_numbers`. ### Step 4: Start the campaign ```bash theme={null} curl --request POST "https://prod-api.ringg.ai/ca/api/v0/campaign/start" \ --header "X-API-KEY: $RINGG_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "agent_id": "your-agent-id", "list_id": "your-list-id", "from_numbers": ["your-from-number-id"], "callback_url": "https://api.example.com/ringg/campaign-callback" }' ``` ### Step 5: Monitor campaign calls Use campaign and history endpoints together: ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/campaign/all?call_count=true" \ --header "X-API-KEY: $RINGG_API_KEY" ``` ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/calling/history?bulk_list_id=your-list-id" \ --header "X-API-KEY: $RINGG_API_KEY" ``` ### Step 6: Stop calls if needed Use termination endpoints for emergency stops or selective campaign cleanup. ```bash theme={null} curl --request PATCH "https://prod-api.ringg.ai/ca/api/v0/campaign/terminate" \ --header "X-API-KEY: $RINGG_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "campaign_id": "your-list-id" }' ``` ## Beta large-campaign flow Use this path for CSVs with 5,000 or more rows. It separates upload, validation, balance checking, and call scheduling so long CSV imports do not block one request. This flow is beta. Use the standard `POST /campaign/save` plus `POST /campaign/start` flow unless large-campaign beta access is enabled for your workspace. ### Beta step 1: Upload the CSV `POST /campaign/upload-csv` accepts the large CSV and campaign metadata. Use the same CSV headers, variable mapping, assistant ID, campaign window, country code, and call configuration you would send to `POST /campaign/save`. ```bash theme={null} curl --request POST "https://prod-api.ringg.ai/ca/api/v0/campaign/upload-csv" \ --header "X-API-KEY: $RINGG_API_KEY" \ --form 'agent_id="your-agent-id"' \ --form 'campaign_name="Renewal reminders - large batch"' \ --form 'country_code="+91"' \ --form 'variables_map="{\"mobile_number\":\"Mobile Number\",\"callee_name\":\"Name\"}"' \ --form 'campaign_start_time="18/10/2026, 09:00"' \ --form 'campaign_end_time="18/10/2026, 18:00"' \ --form 'call_config="{\"call_time\":{\"call_start_time\":\"09:00\",\"call_end_time\":\"18:00\",\"timezone\":\"Asia/Kolkata\"}}"' \ --form "file=@contacts-5000-plus.csv" ``` Save the returned `bulk_list_id`. Use it for every following beta step. ### Beta step 2: Poll upload status ```bash theme={null} curl --request GET "https://prod-api.ringg.ai/ca/api/v0/campaign/upload-status/your-bulk-list-id" \ --header "X-API-KEY: $RINGG_API_KEY" ``` Wait until processing is complete before checking balance or starting calls. If the status reports invalid rows, fix the CSV or remove invalid rows according to your campaign policy. ### Beta step 3: Check balance ```bash theme={null} curl --request POST "https://prod-api.ringg.ai/ca/api/v0/campaign/check-balance/your-bulk-list-id" \ --header "X-API-KEY: $RINGG_API_KEY" ``` Only continue when the response confirms the workspace has enough balance for the validated rows. ### Beta step 4: Start calls asynchronously ```bash theme={null} curl --request POST "https://prod-api.ringg.ai/ca/api/v0/campaign/make-call-async" \ --header "X-API-KEY: $RINGG_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "agent_id": "your-agent-id", "bulk_list_id": "your-bulk-list-id", "from_numbers": ["your-from-number-id"], "callback_url": "https://api.example.com/ringg/campaign-callback" }' ``` After scheduling, monitor the campaign with `GET /campaign/all` and call history filtered by the same `bulk_list_id`. Start the beta 5k+ row import. Poll CSV processing before starting calls. Confirm available balance for the validated contacts. Queue the large campaign for outbound calling. ## Production checklist * Start with a small CSV before uploading a large campaign. * Set campaign windows in the audience's timezone. * Validate CSV headers before upload. * Store `list_id` and selected `from_numbers`. * Store `bulk_list_id` for beta large campaigns. * Subscribe to webhooks for post-call results. * Use `remove_invalid_rows=true` when you prefer skipping invalid contacts instead of failing the whole upload. # Voice Calling Source: https://docs.ringg.ai/api-reference/tutorials/voice-calling Manage and initiate AI-powered voice calls with Ringg AI's Voice API. Ringg AI's Voice API enables businesses to create and manage AI-powered voice calls, enhancing customer interactions through intelligent voice assistants. *** ## Voice API Overview Ringg AI's Voice Calling system supports two primary call types: * **Inbound Calls**: Users call a designated number and interact with an AI assistant * **Outbound Calls**: Ringg AI initiates calls to users via telephony partners, connecting them to an AI assistant The platform manages the entire call lifecycle, from initiation to completion, while providing comprehensive analytics and management tools. *** ## How Voice Calling Works Ringg AI uses a sophisticated system to connect callers with AI assistants: * **Assistants**: AI voice agents that handle conversations based on predefined goals * **Numbers**: Phone numbers connected to assistants that serve as the point of contact * **Telephony Partners**: Underlying infrastructure that connects calls * **Custom Variables**: Dynamic data points that personalize conversations *** ## Relationship Between Assistants and Calls Each call is connected to a specific assistant that manages the conversation. The assistant is linked to a phone number, which serves as the point of contact for inbound calls or the caller ID for outbound calls. This relationship ensures that calls are routed to the appropriate assistant with the relevant context and capabilities. *** ## Call States and Lifecycle Calls progress through several states during their lifecycle: * **Call Initiated**: The call has been requested but not yet connected * **Call Transferred**: The call has been transferred to the assistant * **Ongoing**: The call is currently active * **Call Completed**: The call has ended normally * **Call Failed**: The call did not connect or ended unexpectedly *** ## Best Practices for Implementing Voice Calls * Choose a number from the Ringg AI dashboard that aligns with your business needs * Consider using Karnataka (KA) numbers that start with `080` for better recognition * Focus on transactional use cases for optimal pick-up rates * Ensure all custom variables are properly configured for personalized conversations * Test your implementation thoroughly before scaling to production # TrueFoundry Integration Source: https://docs.ringg.ai/external-integrations/truefoundry-integration Add and configure Ringg.AI Parrot Speech-to-Text (STT) in TrueFoundry's AI Gateway using Custom Endpoints. ## Overview Add [Ringg.AI](https://www.ringg.ai/) Parrot STT to the TrueFoundry AI Gateway using **Custom Endpoints**. Parrot is Ringg's speech-to-text model built for real-time voice agents, with strong support for Hindi, English, and code-mixed speech. Learn more on the [Parrot STT model page](https://www.ringg.ai/models/speech-to-text/v1) and in the [Parrot STT announcement](https://www.ringg.ai/blog/parrot-speech-to-text-api). [TrueFoundry AI Gateway](https://www.truefoundry.com/ai-gateway) is the proxy layer that sits between your applications and the LLM providers and MCP Servers. It is an enterprise-grade platform that enables users to access 1000+ LLMs using a unified interface while taking care of observability and governance. ## Adding models In the TrueFoundry dashboard, go to **AI Gateway** → **Models** → **Custom Endpoints** and click **Add Custom Endpoint**. In **Configure Account**, set: * **Name**: any unique name (this becomes `{providerAccountName}` in the URL) * **Endpoint Type**: `None` (or any value you use for tracking) * **Header Auth**: keep **disabled** Click **Add Endpoint** (or **Add Endpoint** from the list view) and configure the integration: * **Display Name**: any name (this becomes `{endpointName}` in the URL) * **Base URL**: `https://prod-api.ringg.ai/stt/v1/transcriptions` Enable **Custom Headers** and add: * `x-api-key`: `` Keep **Header Auth** disabled. Custom Endpoint form for Ringg.AI STT with Base URL and x-api-key custom header This **x-api-key** header is sent **from the AI Gateway to Ringg.AI**. Your client should only send the **TrueFoundry API key** to the AI Gateway. On the **Access Control** step, add the users/teams who can view/use this provider account, then **Save**. ## Inference Once saved, call your endpoint through the AI Gateway's **proxy-api** path. URL shape and path rules are documented under [Custom Endpoints](https://docs.truefoundry.com/docs/ai-gateway/custom-endpoints#endpoint-structure). ## Supported APIs | API | Endpoint | Tracing | Cost Tracking | | - | - | - | - | | [Speech-to-Text](#speech-to-text) | `/proxy-api/{providerAccountName}/{endpointName}` | **✅** | | **Before you start:** Replace `{GATEWAY_BASE_URL}` with your gateway base URL ([how to find it](https://docs.truefoundry.com/docs/ai-gateway/quick-start#gateway-base-url)) and set `TFY_API_KEY` to your TrueFoundry API key. Send a multipart form request with the audio file and optional transcription parameters (for example `language` and `enable_cap_punc`). ```python theme={null} import json import os import requests GATEWAY_BASE_URL = "{GATEWAY_BASE_URL}" TFY_API_KEY = os.environ.get("TFY_API_KEY", "your-tfy-api-key") # providerAccountName = Custom Endpoint account name # endpointName = integration display name URL = f"{GATEWAY_BASE_URL}/proxy-api/{providerAccountName}/{endpointName}" with open("audio.mp3", "rb") as f: response = requests.post( URL, headers={"Authorization": f"Bearer {TFY_API_KEY}"}, files={"file": f}, data={ "language": "hi", "enable_cap_punc": "false", }, timeout=120, ) response.raise_for_status() result = response.json() with open("response.json", "w", encoding="utf-8") as out: json.dump(result, out, ensure_ascii=False, indent=2) print("Saved response to response.json") ``` **Support scope:** Not all APIs are supported through this integration. Only **HTTPS** and **non-streaming** requests are supported. Support will expand over time, including additional endpoints on customer request. Send a request to [support@truefoundry.com](mailto:support@truefoundry.com). # Security Guidelines Source: https://docs.ringg.ai/get-started/best-practices/security-guidelines Follow these security best practices to protect your Ringg AI integration and user data ## API Key Management * **Secure storage**: Never expose your API key in client-side code, public repositories, or browser-accessible files. * **Environment variables**: Store your API key in environment variables or secure configuration systems. * **Access control**: Implement proper access controls to limit who can use your API key. * **Rotation**: Rotate your API key if you suspect it's been exposed. * **Monitoring**: Set up alerts for unusual API usage patterns that might indicate a compromised key. ## Data Protection * **Minimize data collection**: Only collect and transmit the data necessary for the assistant to function. * **Secure transmission**: Always use HTTPS for API requests to ensure encrypted data transmission. * **Data retention**: Implement appropriate data retention policies for call recordings and transcripts. * **User consent**: Clearly inform users when calls are being recorded and obtain necessary consent. * **PII handling**: Be cautious when handling Personally Identifiable Information (PII) and follow relevant regulations. ## Web Integration Security * **Content Security Policy**: Configure your CSP to allow only the necessary Ringg AI resources. * **Domain validation**: Verify that your domains are properly whitelisted in the Ringg AI dashboard. * **Cross-site scripting protection**: Implement proper input sanitization to prevent XSS attacks. * **Iframe protection**: If embedding in an iframe, use appropriate sandbox attributes. * **CORS configuration**: Ensure your CORS settings allow only necessary origins. ## Authentication and Authorization * **Principle of least privilege**: Grant only the minimum necessary permissions to systems and users. * **Regular audits**: Periodically review who has access to your Ringg AI account and API keys. * **Strong passwords**: Use strong, unique passwords for your Ringg AI account. * **Two-factor authentication**: Enable 2FA if available for your Ringg AI account. * **Session management**: Implement proper session timeouts and invalidation procedures. ## Compliance Considerations * **Privacy regulations**: Ensure your implementation complies with relevant privacy regulations (GDPR, CCPA, etc.). * **Industry standards**: Follow industry-specific security standards if applicable (PCI DSS, HIPAA, etc.). * **Disclosure requirements**: Clearly disclose to users that they are interacting with an AI assistant. * **Opt-out mechanisms**: Provide clear ways for users to opt out of AI-powered calls. * **Documentation**: Maintain documentation of your security measures and compliance efforts. # Voice Call Optimization Source: https://docs.ringg.ai/get-started/best-practices/voice-call-optimization Follow these best practices to optimize your voice calls for better performance and user experience ## Assistant Configuration * **Choose the right voice**: Select a voice that matches your brand personality and target audience. Test different voices to find the one that resonates best with your users. * **Craft clear prompts**: Write concise, natural-sounding prompts that guide the conversation effectively. * **Use custom variables**: Personalize conversations by incorporating custom variables like the caller's name, transaction details, or other relevant information. * **Set appropriate voice speed**: Adjust the voice speed to ensure clarity. A moderate pace (around 1.0) works best for most use cases. ## Call Quality * **Use Karnataka (KA) numbers**: For Indian audiences, numbers starting with 080 (Karnataka) often have better recognition and pickup rates. * **Optimize call timing**: Schedule calls during business hours when recipients are more likely to answer. * **Implement call retries**: Configure retry attempts for unanswered calls, but limit to 1-2 retries to avoid being perceived as spam. * **Monitor call metrics**: Regularly review call duration, completion rates, and user feedback to identify areas for improvement. ## Content Strategy * **Keep introductions brief**: Start with a concise introduction that identifies the assistant and the purpose of the call. * **Use natural language**: Write conversational scripts that sound human and avoid robotic language. * **Prepare for common scenarios**: Anticipate different user responses and create appropriate handling paths. * **Include clear call-to-actions**: End calls with clear next steps or instructions for the recipient. ## Technical Considerations * **Test across different networks**: Ensure your calls perform well across various mobile networks and connection qualities. * **Monitor latency**: Keep response times low to maintain natural conversation flow. * **Implement proper error handling**: Create graceful fallbacks for when users provide unexpected responses. * **Limit concurrent calls**: For bulk campaigns, start with a smaller number of concurrent calls (5–10) and gradually increase based on performance. # Web Call Integration Source: https://docs.ringg.ai/get-started/best-practices/web-call-integration Follow these best practices to optimize your Web Call integration for better user experience and performance ## Browser Compatibility Information Ringg AI's Web Call integration is compatible with all modern browsers: * **Chrome** 55+ * **Firefox** 53+ * **Safari** 11+ * **Edge** 79+ * **Opera** 42+ ## For optimal performance: * Ensure the browser has permission to access the microphone * WebRTC capabilities must be enabled * JavaScript must be enabled * Mobile browsers are supported, but performance may vary based on device capabilities ## Placement and Visibility * **Consistent positioning**: Place the Web Call button in a consistent location across your site, typically in the bottom right corner. * **Visual contrast**: Ensure the button contrasts well with your website's background for better visibility. * **Attention indicators**: Consider using subtle animations like pulsing to draw attention to the feature without being distracting. * **Mobile optimization**: Ensure the button is appropriately sized and positioned on mobile devices. ## User Experience * **Clear instructions**: Provide brief instructions on how to interact with the assistant when the call begins. * **Introduction message**: Include a concise introduction explaining what the assistant can help with. * **Text alternatives**: Offer text-based interaction options for users who prefer not to use voice. * **Visual feedback**: Provide clear visual cues when the microphone is active or when the assistant is processing. ## Performance Optimization * **Asynchronous loading**: Load the Web Call script asynchronously to prevent blocking page rendering. * **Lazy loading**: Consider loading the Web Call component only when the user scrolls near it. * **Error handling**: Implement proper error handling to gracefully degrade if the service is unavailable. * **Bandwidth management**: Inform users about potential data usage for voice calls, especially on mobile connections. ## Integration Setup * **Domain whitelisting**: Add all domains where the assistant will be embedded to the whitelist. * **CDN permissions**: Ensure your Content Security Policy allows the required CDN resources. * **Cross-browser testing**: Test the integration across all major browsers and devices. * **Version pinning**: Consider pinning to a specific version of the SDK instead of using "latest" for production environments. ## Customization * **Brand alignment**: Customize button colors and styles to match your brand identity. * **Contextual variables**: Pass relevant page or user context to the assistant to provide more personalized responses. * **Custom button text**: Modify the button text to clearly communicate the purpose of the assistant. * **Responsive design**: Ensure the Web Call interface adapts appropriately to different screen sizes. # Analytics Source: https://docs.ringg.ai/get-started/guides/analytics Review call performance, connection rates, costs, and assistant results. Use **Analytics** to understand how calls are performing across your workspace. It helps business teams answer questions like: Are people picking up? Which assistant is working best? Are calls too short? Are costs aligned with results? *** ## Open Analytics 1. Click **Analytics** in the left sidebar. 2. Review the default date range. 3. Use the date picker or filters to narrow the report. *** ## Set the Date Range 1. Click the date range picker. 2. Choose the period you want to review. 3. Apply the date range. 4. Click the clear icon to reset when needed. Click **Filter** to narrow results by assistant, number, campaign, status, or other available fields. *** ## Read the Top Metrics The top cards summarize performance for the selected filters. | Metric | What It Means | | - | - | | **Total Calls** | All calls in the selected period | | **Calls Connected** | Calls where a person answered | | **Connectivity** | Connected calls divided by total calls | | **Avg. Duration** | Average call length | | **Total Cost** | Credits spent in the selected period | | **Registered** | Contacts who completed the tracked business action, if configured | | **Voicemail Detected** | Calls that reached voicemail | | **Workspace Numbers** | Active phone numbers in the workspace | *** ## Review Call Status Distribution The call status chart shows how calls ended. Common statuses include: * Completed. * Failed. * No answer. * Voicemail. Use this chart to spot delivery problems. For example, a high voicemail rate may mean you should change calling hours. *** ## Review Calls by Day The calls-by-day chart shows volume over time. Use it to find: * Peak calling days. * Drops in calling volume. * Campaign schedule problems. * The effect of changing numbers, prompts, or calling windows. *** ## Compare Assistants The assistant table shows performance by assistant. | Column | What It Means | | - | - | | **Agent Name** | Assistant name | | **Call Counts** | Total calls handled by that assistant | | **Total Connected** | Calls answered by a person | Sort the table to find assistants that need prompt changes, better numbers, or a different audience. *** ## What to Try Next | If You See | Try This | | - | - | | Low connectivity | Review caller numbers, calling hours, and audience quality | | High voicemail rate | Shift calls to hours when contacts are more likely to answer | | Very short calls | Listen to recordings and improve the assistant opening line | | High cost with low conversion | Improve targeting, prompt logic, or follow-up rules | | One assistant underperforms | Compare its prompt, voice, and knowledge base against better performers | *** ## Developer Handoff If engineers are building dashboards or investigating analytics, send them: | Item | Why They Need It | | - | - | | Date range and timezone | Ensures their report matches the dashboard | | Assistant name and `agent_id` | Filters analytics to one assistant | | Campaign name and `bulk_list_id` | Filters analytics to one campaign or uploaded list | | Status filters | Explains which calls should be included | | Business metric definition | Clarifies what counts as registered, qualified, booked, or converted | For live product dashboards, ask developers to combine analytics APIs with webhook events and call history exports. # Configure an Assistant Source: https://docs.ringg.ai/get-started/guides/configure-assistant Set up an assistant's script, voice, documents, call settings, and developer handoff. After creating an assistant, configure what it says, what it can look up, and how calls should behave. To open the configuration page, click **Assistants** in the left sidebar, then click the assistant you want to edit. *** ## Configuration Areas The left panel groups settings into three areas. | Area | What You Control | | - | - | | **Assistant Settings** | Prompt, voice, custom variables, and knowledge base | | **Call Settings** | Phone call behavior and webcall chat timing | | **Advanced Settings** | Website embed, keyword boosting, and post-call analysis | *** ## Prompt Click **Assistant Settings** and then **Prompt**. The prompt is the assistant's working script. It has three important parts. | Part | What to Write | | - | - | | **First Message** | The exact opening line the assistant says when the call connects | | **Objective** | The assistant's role, goal, and business context | | **Response Guidelines** | Rules for tone, language, answer length, objections, and handoff behavior | ### First Message Keep the first message short and clear. ```text theme={null} Hello, this is Ananya from Aakash Digital. Am I speaking with @{{callee_name}}? ``` Use `@{{variable_name}}` when the greeting should include a value from the calling list, such as the customer's name. The **Interruptible** setting controls whether the customer can speak before the first message finishes. ### Objective Write one short paragraph that tells the assistant what to achieve. ```text theme={null} You are Ananya, an academic counselor calling on behalf of Aakash Digital. Your goal is to understand the student's exam preparation status and book a demo class if they are interested. ``` ### Response Guidelines Use bullet points for rules the assistant must follow. ```text theme={null} - Keep answers under 40 words. - Be polite and direct. - Switch to Hindi if the customer starts speaking Hindi. - If the customer asks for pricing, use the attached knowledge base. - If the customer is upset, apologize once and end the call politely. ``` *** ## Voice Click **Assistant Settings** and then **Voice**. | Field | What It Means | | - | - | | **Primary Language** | The main language for the call | | **Secondary Language** | Optional backup language | | **Voice Character** | The voice customers will hear | Use **Most Used** or **Neutral** to filter voice options. Save the voice, then run a test call before using it in a campaign. *** ## Custom Variables Click **Assistant Settings** and then **Custom Variables**. Custom variables are placeholders that Ringg AI fills in for each call. They usually come from a campaign CSV or from your backend. | Variable | Example Value | Where You Might Use It | | - | - | - | | `callee_name` | `Vikram` | First message | | `loan_amount` | `120000` | Collections script | | `course_name` | `JEE Advanced` | Admissions or education script | Use the same spelling in the assistant prompt and in the CSV column name. For example, `@{{callee_name}}` needs a CSV column named `callee_name`. *** ## Knowledge Base Click **Assistant Settings** and then **Knowledge Base**. 1. Select an existing knowledge base. 2. Confirm it is trained and ready. 3. Click **Save**. Use a knowledge base when the assistant needs to answer questions from approved documents, such as FAQs, pricing, policy rules, product details, or eligibility criteria. See [Create a Knowledge Base](/get-started/guides/create-knowledge-base) if you need to create one first. *** ## Call Settings Click **Call Settings** and then **Call**. | Setting | Plain-English Meaning | | - | - | | **Maximum Call Duration** | The longest one call can last | | **Inactivity Duration** | How long silence can continue before the assistant reacts | | **Timezone** | The timezone used for call schedules and reporting | | **Noise Filtering** | Helps reduce background noise | | **Voicemail Detection** | Detects voicemail instead of a live person | | **Leave Voicemail Message** | Lets the assistant leave a voicemail message | | **Retry Call** | Tries again when voicemail is detected | | **Silence Callee During Introduction** | Prevents interruption during the opening line | | **Silence Callee When Assistant is Speaking** | Reduces cross-talk while the assistant speaks | | **Enable Background Audio** | Adds background sound for a more natural call | | **Enable Graceful Exit Warning** | Warns the customer before ending the call | For a first launch, keep settings simple. Set a reasonable maximum duration, choose the correct timezone, and test voicemail behavior before calling real contacts. *** ## Chat Settings Click **Call Settings** and then **Chat**. These settings apply to **Webcall** assistants. | Setting | What It Controls | | - | - | | **Maximum Call Length** | The total webcall session length | | **Idle Timeout Warning** | When the user is warned about inactivity | | **Idle Timeout End** | When the webcall ends after inactivity | *** ## Embed Click **Advanced Settings** and then **Embed**. Use this only for a **Webcall** assistant. 1. Choose the widget theme, size, feedback screen, and branding. 2. Select the SDK version. 3. Click **Preview** to check the widget. 4. Copy the generated code. 5. Send the code to the website owner or developer. Website teams should add the embed code to the website, not to internal documents or email templates. *** ## Keyword Boosting Click **Advanced Settings** and then **Keyword Boosting**. Add words the assistant must recognize correctly, such as brand names, course names, product names, city names, acronyms, or plan names. 1. Type one keyword. 2. Click **Add**. 3. Repeat for each important word. *** ## Custom Analysis Click **Advanced Settings** and then **Custom Analysis**. Custom analysis extracts structured results after each call. Use it when your team needs consistent reporting fields. Example fields: | Field | Type | Meaning | | - | - | - | | `interested` | Boolean | Whether the customer showed interest | | `preferred_course` | String | Course mentioned by the customer | | `objection` | String | Main reason the customer did not agree | Example prompt: ```text theme={null} From the transcript, extract whether the customer agreed to a demo booking, the preferred course, and the main objection if they declined. ``` Click **Save**, then **Test Analysis** before launch. *** ## Run a Test Call Click **Test call** in the top-right corner. Use a real phone number owned by your team. Check that: * The first message sounds right. * Variables such as customer name are filled correctly. * The assistant follows the objective. * The voice and language are appropriate. * The call ends politely. * The transcript and analysis are useful. *** ## Developer Handoff Send this information to the engineer or website owner before launch: | Item | Why It Matters | | - | - | | `agent_id` | Required for API calls, campaigns, webhooks, and webcall setup | | Custom variable names | Must match CSV columns or backend payload fields | | Knowledge base name or ID | Helps confirm the right documents are attached | | Embed code | Needed only for webcall website setup | | Webhook events needed | Examples: call status, recording, transcript, custom analysis, all processing completed | | Test call results | Gives the developer a real call to verify history, webhooks, and reporting | For production integrations, ask the developer to configure webhooks after the assistant is approved. See [Webhook setup](/webhooks/initial-setup). # Create an Assistant Source: https://docs.ringg.ai/get-started/guides/create-assistant Create a Ringg AI voice assistant from the dashboard. An assistant is the voice agent that speaks to your customers. Create one first, then connect it to a number, campaign, web widget, or API integration. *** ## Before You Start Decide these items before creating the assistant: | Decision | What to Prepare | | - | - | | Call direction | Outbound, inbound, or webcall | | Use case | Reminder, lead qualification, collections, support, onboarding, or another clear goal | | Language | Primary language and optional backup language | | Voice | The voice style you want customers to hear | | Handoff owner | The person who will configure API calls, webhooks, or website embeds if needed | *** ## Step 1 - Open Assistants 1. Log in to the Ringg AI dashboard. 2. Click **Assistants** in the left sidebar. 3. Click **+ Create Assistant**. The create assistant window opens. *** ## Step 2 - Choose the Call Type Choose how people will reach the assistant. | Call Type | Use It When | | - | - | | **Outbound** | Ringg AI should call customers, leads, students, borrowers, or applicants | | **Inbound** | Customers should call one of your Ringg AI numbers | | **Webcall** | Visitors should start a voice call from your website | Choose **Outbound** for campaigns. Choose **Webcall** only if your website team will add the Ringg AI widget. *** ## Step 3 - Choose a Template Pick the fastest starting point: | Option | Best For | | - | - | | **Industry template** | You want a ready-made starting script for logistics, healthcare, finance, education, HR, or ecommerce | | **Blank template** | You want to write the conversation from scratch | If you choose **Blank template**, select the conversation style: | Style | Best For | | - | - | | **Single Prompt** | Simple calls that follow one script | | **Multi Prompt** | Branching calls where the next step depends on the customer's answer | *** ## Step 4 - Fill in the Basics Enter the required setup fields. | Field | What to Enter | | - | - | | **Agent Name** | A clear name such as `Loan Collection - Hindi` or `Admissions Follow-up - English` | | **Primary Language** | The main language the assistant should speak | | **Secondary Language** | Optional backup language if callers switch languages | Use names your team can recognize later. Include the use case, call direction, and language when possible. *** ## Step 5 - Choose a Voice 1. In **Set up voice**, browse the available voices. 2. Use **Most Used** or **Neutral** to filter the list. 3. Click a voice card to select it. 4. Click **See more** if you want more options. Run test calls with two or three voices before launch. The best voice depends on the audience and use case. *** ## Step 6 - Continue to Configuration Click **Next**. If a required field is missing, Ringg AI highlights it. Fill in the missing value and click **Next** again. *** ## Developer Handoff If engineers will trigger calls, embed a widget, or receive call results, give them: | Item | Why They Need It | | - | - | | Assistant name | Helps them confirm they are using the right assistant | | `agent_id` | Required for API calls, campaigns, and webhook subscriptions | | Call type | Tells them whether to build outbound calls, inbound routing, or a webcall embed | | Custom variables you plan to use | Helps them send the right customer fields, such as `callee_name` or `loan_amount` | | Webhook requirement | Tell them whether your team needs transcripts, recordings, analysis results, or status updates in another system | If you do not see the `agent_id` in the dashboard, ask the developer to retrieve it from the assistant API using the assistant name. *** ## Next Steps Write the prompt, attach documents, and set call behavior. Add documents the assistant can use during calls. Choose the numbers your assistant or campaigns will use. Call many contacts with this assistant. # Create a Campaign Source: https://docs.ringg.ai/get-started/guides/create-campaign Run outbound calls to a contact list from the Ringg AI dashboard. A campaign calls many contacts using one assistant, one or more caller numbers, and a CSV calling list. *** ## Before You Start Make sure you have: An outbound assistant that has been tested At least one phone number in your workspace A CSV file with phone numbers and any fields used by the assistant Enough call credits for the campaign *** ## Step 1 - Open Campaigns 1. Click **Campaigns** in the left sidebar. 2. Click **+ Create Campaign**. *** ## Step 2 - Fill in Campaign Settings On the **Campaign Settings** tab, fill in: | Field | What to Choose | | - | - | | **Campaign Name** | A clear name such as `March Admissions Follow-up` | | **Assistant** | The assistant that should make the calls | | **Numbers** | One or more caller numbers | | **Campaign Start Date/Time** | When calling should begin | | **Campaign End Date/Time** | When calling must stop | | **Timezone** | The timezone for the schedule | | **Email Notifications** | People who should receive updates | Use a campaign name that includes the audience, month, and purpose. This makes history and analytics easier to find later. *** ## Step 3 - Upload the Calling List Click **Next** to open the **Calling List** tab. Upload a CSV file with one row per contact. Include: * A phone number column. * One column for each custom variable used in the assistant prompt. * Clear column names with no extra spaces. Example: ```csv theme={null} phone_number,callee_name,course_name +919994008915,Sarath,JEE Advanced +919731553396,Vikram,NEET +917404156687,Sahil,Class 10 Foundation ``` If the assistant prompt uses `@{{callee_name}}`, the CSV must include a `callee_name` column. *** ## Step 4 - Save and Start 1. Review the campaign settings. 2. Click **Save CSV**. 3. Click **Make Call** to activate the campaign. What happens next depends on the schedule: | Schedule | Campaign State | | - | - | | Start time is in the future | **Scheduled** | | Start time is now or already passed | **Ongoing** | *** ## Monitor a Campaign From the **Campaigns** page, use the **Actions** column to: * View campaign call history. * View campaign analytics. * Terminate a running campaign if needed. Use **History** for call-level details and **Analytics** for performance trends. *** ## Set Campaign Concurrency Concurrency controls how many calls can happen at the same time. 1. Click **Manage Concurrency** on the Campaigns page. 2. Use **Workspace Concurrency** to split capacity between API calls and campaign calls. 3. Use **Campaigns Concurrency** to allocate capacity across running campaigns. 4. Click **Save**. If you do not set campaign concurrency, Ringg AI distributes available call slots across running campaigns. *** ## Developer Handoff If engineers are starting campaigns by API or pulling campaign results into another system, send them: | Item | Why They Need It | | - | - | | Campaign name | Lets them confirm they are working with the right campaign | | `agent_id` | Identifies the assistant that should make the calls | | Caller number or `from_number_id` | Identifies which number should dial contacts | | CSV column names | Must match assistant custom variables | | `bulk_list_id` or list ID | Identifies the uploaded calling list for start, status, history, and analytics | | Webhook requirement | Tells them whether to send call results to CRM, sheets, data warehouse, or support tools | For the standard API flow, developers should save the campaign with `POST /campaign/save`, then start it with `POST /campaign/start`. For large campaigns with 5,000 or more rows, use the beta large-campaign flow: 1. `POST /campaign/upload-csv` 2. `GET /campaign/upload-status/{bulk_list_id}` 3. `POST /campaign/make-call-async` 4. `POST /campaign/check-balance/{bulk_list_id}` Ask developers to store the returned `bulk_list_id` because it is needed to check upload status, start calls, filter history, and reconcile results. # Create a Knowledge Base Source: https://docs.ringg.ai/get-started/guides/create-knowledge-base Upload approved documents that assistants can use during calls. A knowledge base lets an assistant answer from approved documents instead of guessing. Use it for FAQs, pricing, policies, eligibility rules, product details, and support scripts. *** ## Before You Start Prepare clean source files: | Requirement | Guidance | | - | - | | Source type | Upload files for document knowledge, use CSV for deterministic row-based data, or add FAQs/URLs when available in your workspace | | Supported file types | PDF, DOCX, TXT, CSV, JSON, and other text-readable files. Export spreadsheets to CSV when you need structured deterministic retrieval. | | File quality | Use text-based files when possible. Avoid scanned PDFs unless they have searchable text. | | File count | Up to 4 files per knowledge base | | File size | Up to 512 MB per file | | Source owner | Confirm the documents are approved for customer-facing answers | | Refresh plan | Decide who will retrain the knowledge base when documents change | *** ## Step 1 - Open Knowledge Base 1. Click **Knowledge Base** in the left sidebar. 2. Click **Create Knowledge Base**. Choose the knowledge base type. | Type | Use It When | | - | - | | **Deterministic KB** | You need structured, predictable answers from fields you define | | **Non Deterministic KB** | You have general documents such as FAQs, SOPs, or manuals | *** ## Create a Deterministic Knowledge Base Use this for structured information such as pricing tables, policy rules, eligibility fields, product catalogs, or plan comparisons. 1. Click **Deterministic KB**. 2. Enter a clear **KB Name**. 3. Upload a CSV or other structured text file. 4. Click **Edit Schema**. 5. Add the fields the assistant should retrieve, such as `product_name`, `price`, `policy_code`, or `eligibility_status`. 6. Choose the data type for each field. 7. Click **Train Knowledge Base**. Training can take a few minutes. Wait until the knowledge base is ready before attaching it to an assistant. *** ## Create a Non Deterministic Knowledge Base Use this for less structured documents such as FAQs, help articles, policy documents, SOPs, or product manuals. 1. Click **Non Deterministic KB**. 2. Enter a clear **KB Name**. 3. Upload source files such as PDFs, DOCX files, TXT files, CSVs, JSON files, or clean text-readable documents. 4. Click **Train Knowledge Base**. The assistant will search the uploaded content during calls and use the most relevant information it finds. *** ## Attach the Knowledge Base to an Assistant 1. Click **Assistants** in the left sidebar. 2. Open the assistant that should use the documents. 3. Click **Assistant Settings** and then **Knowledge Base**. 4. Select the trained knowledge base. 5. Click **Save**. Run a test call and ask questions that should use the knowledge base. Confirm the assistant answers from the right source. *** ## Tips for Better Answers Keep each knowledge base focused on one business topic. A focused pricing KB or FAQ KB is easier to test than one large mixed document set. * Use clear document titles and headings. * Remove old or conflicting information before upload. * For deterministic knowledge bases, make schema field names match your source columns. * Retrain after every source document update. * Test with real customer questions before launch. *** ## Developer Handoff If engineers use the knowledge base through APIs or need to verify production setup, send them: | Item | Why They Need It | | - | - | | Knowledge base name | Helps them confirm the right document set is attached | | Knowledge base type | Explains whether answers are schema-driven or document-search based | | Source document owner | Tells them who approves updates | | Assistant name and `agent_id` | Lets them confirm the assistant is attached to the correct knowledge base | | Test questions | Gives them sample cases for QA and support workflows | If an integration stores knowledge base IDs, ask the developer to retrieve and store the correct ID after the knowledge base is trained. # Embedding Widget Source: https://docs.ringg.ai/get-started/guides/embedding-widget Embed a Ringg AI voice or chat assistant on your website. Use this quickstart to add a Ringg AI web-call widget to a page. Start with the minimal snippet, verify it in staging, then add branding, chat mode, events, and production controls from the linked reference pages. Building a mobile app instead? The same widget ships natively for [React Native](/get-started/guides/widget-react-native) and [Flutter](/get-started/guides/widget-flutter), with the same conversation behavior and native views. Load options, variables, positioning, trigger styling, and feedback screens. Browser events the widget emits about its own state: open/close, conversation start/end, feedback. Text mode, chat-only embeds, prompt examples, and the legacy calendar and form widgets. Build cards, forms and pickers the agent shows in chat, from a plain-English description. API calls before and after render, page events, agent actions, bindings and parameters. Worked recipes: lead capture, live pricing, slot booking, brochure downloads. Restyle and script the widget through stable data-ringg attributes. Domain whitelisting, CSP, CDN pinning, browser QA, and launch checks. The same widget in a React Native or Expo app, with `@ringg/react-native`. The same widget in a Flutter app, with the `ringg_flutter` package. ## Prerequisites An active Ringg AI account. An assistant configured for Webcall in the Ringg AI dashboard. The assistant `agentId` and the webcall public key from the generated embed code (used as `authorization: "Bearer "`). Access to add JavaScript to your website HTML or tag manager. Each staging and production domain added to the assistant's Whitelist Domains list. The widget snippet runs in the browser and includes the webcall public key in an `authorization: "Bearer "` header. The key is scoped to a single assistant and its whitelisted domains, so use only the embed code generated for a web-call assistant, whitelist the exact domains where it can run, and never expose a broad backend integration key in public pages. Rotate the key from the dashboard if it is ever compromised. ## Quickstart Open the assistant in the Ringg AI dashboard, go to the WebCall settings, and add your website domain to **Whitelist Domains**. Add staging domains separately, such as `staging.example.com`, instead of using one broad production-only assumption. Paste this near the end of the page, preferably before the closing `` tag. Pick the bundle that matches your host page. Use `dv-agent.es.js` when the page is built with Vite, webpack, Next, or any other module-aware setup, or when the snippet runs inside ` ``` Use `dv-agent.umd.js` when the host page uses jQuery, an older CMS theme, or any plain ` ``` The ES bundle is only safe inside module-aware setups. Loading `dv-agent.es.js` as a plain ` ``` ```html theme={null} ``` Use `latest` while exploring in development. For production, pin the tested CDN version and update CSP entries to match the bundle (`dv-agent.es.js` or `dv-agent.umd.js`) you ship. ## Base configuration ```javascript theme={null} loadAgentsCdn("latest", function () { loadAgent({ agentId: "your-agent-id", authorization: "Bearer your-webcall-public-key", variables: { callee_name: "John", account_id: "ACC-42", }, defaultTab: "audio", hideTabSelector: false, title: "Talk to our assistant", description: "Ask a question or start a voice call.", buttons: { modalTrigger: { styles: { backgroundColor: "#4F46E5", color: "white", borderRadius: "50%", }, }, call: { textBeforeCall: "Start Call", textDuringCall: "End Call", }, }, widgetPosition: { triggerPlacement: "fixed", triggerAlignment: "bottom-right", hideTriggerOnExpand: true, widgetAlignment: "bottom-right", }, }); }); ``` ## Core options | Option | Type | Default | Description | | - | - | - | - | | `agentId` | `string` | Required | Assistant ID to load in the widget. | | `authorization` | `string` | Required | `Bearer `. The webcall public key is generated for the assistant in the dashboard embed code and can be rotated from there. | | `variables` | `object` | `{}` | Runtime variables available to the assistant. | | `defaultTab` | `"audio" \| "text"` | `"audio"` | Tab shown when the widget loads. Use `"text"` for chat mode. Supported from v1.0.8+. | | `hideTabSelector` | `boolean` | `false` | Pins the widget to `defaultTab` (single-mode start screen). Supported from v1.0.8+. | | `bypassStartScreen` | `boolean` | `false` | Skips the start screen and begins a call or chat immediately on trigger click. Uses `defaultTab`. | | `title` | `string` | Unset | Heading shown in the widget start screen. | | `description` | `string` | Unset | Supporting copy shown in the widget start screen. | | `logoUrl` | `string` | Unset | Logo image URL shown in the header and, when set, the launcher. | | `typingWords` | `string[]` | `["Thinking", "Reasoning", "Working on it", "Almost there"]` | Words cycled in the pending-reply indicator (shimmered, "Thinking…" style). | | `theme` | `object` | Unset | Widget color theme (see below). | | `buttons` | `object` | `{}` | Trigger and call button customization. | | `widgetPosition` | `object` | Fixed bottom-right | Placement rules for the trigger and expanded widget. | | `feedbackScreen` | `object` | Unset | Text and star colors for the post-conversation feedback screen. | ### Theme Pass `theme` to color the widget. Colors accept a solid value or a CSS gradient string. | Field | Description | | - | - | | `theme.primaryColor` | Accent for buttons, selected states, the launcher, and the shimmer. | | `theme.primaryTextColor` | Text on the primary color. | | `theme.backgroundColor` | Widget background. | | `theme.surfaceColor` | Cards, inputs, and the user message bubble. | | `theme.agentBubbleColor` | When set, agent messages render inside a bubble with this background (accepts a gradient). Unset = agent messages are bubble-less plain text. | | `theme.textColor` / `theme.mutedTextColor` | Body and secondary text. | | `theme.borderColor` | Borders and dividers. | | `theme.errorColor` / `theme.successColor` | Validation, danger, and success states. | | `theme.borderRadius` | Corner radius for the panel, cards, and inputs. | | `theme.buttonStyle` | `"pill"` / `"rounded"` / `"square"`. Button corner style. | ## Variables Use `variables` for page-specific context that the assistant prompt expects. ```javascript theme={null} loadAgent({ agentId: "your-agent-id", authorization: "Bearer your-webcall-public-key", variables: { callee_name: "John", account_id: "ACC-42", plan_name: "Enterprise", }, }); ``` Variables are sent from the browser. Do not put secrets, internal tokens, or sensitive data in the widget configuration. ## Mode controls ```javascript theme={null} loadAgent({ agentId: "your-agent-id", authorization: "Bearer your-webcall-public-key", defaultTab: "audio", hideTabSelector: false, }); ``` ```javascript theme={null} loadAgent({ agentId: "your-chat-agent-id", authorization: "Bearer your-webcall-public-key", defaultTab: "text", hideTabSelector: false, }); ``` ```javascript theme={null} loadAgent({ agentId: "your-chat-agent-id", authorization: "Bearer your-webcall-public-key", defaultTab: "text", hideTabSelector: true, }); ``` For chat setup, see [Chat Mode](/get-started/guides/embedding-widget-chat-widgets). ## Widget positioning Positioning controls are supported from v1.0.19+. Fixed mode is the default. The trigger floats over the page and is anchored to the browser viewport. ```javascript theme={null} loadAgent({ agentId: "your-agent-id", authorization: "Bearer your-webcall-public-key", widgetPosition: { triggerPlacement: "fixed", triggerAlignment: "bottom-right", hideTriggerOnExpand: true, widgetAlignment: "bottom-right", }, }); ``` Absolute mode embeds the widget inside a page container. The container must exist before `loadAgent` runs and should have an explicit height. ```html theme={null}
``` ```javascript theme={null} loadAgent({ agentId: "your-agent-id", authorization: "Bearer your-webcall-public-key", widgetPosition: { triggerPlacement: "absolute", triggerAlignment: "center", }, }); ```
| Option | Type | Default | Description | | - | - | - | - | | `triggerPlacement` | `string` | `"fixed"` | Use `"fixed"` for viewport placement or `"absolute"` for the `ringg_ai_container` container. | | `triggerAlignment` | `string` | `"bottom-right"` | Trigger button position. | | `hideTriggerOnExpand` | `boolean` | `true` | Hides the trigger button when the widget is open. | | `widgetAlignment` | `string` | `"bottom-right"` | Expanded widget position. | ## Trigger button customization Trigger button customization is supported from v1.0.19+. ```javascript theme={null} loadAgent({ agentId: "your-agent-id", authorization: "Bearer your-webcall-public-key", buttons: { modalTrigger: { styles: { backgroundColor: "#4F46E5", color: "white", width: 64, height: 64, borderRadius: "50%", }, icon: { url: "https://example.com/my-icon.svg", size: 24, }, }, }, }); ``` | Option | Type | Default | Description | | - | - | - | - | | `buttons.modalTrigger.styles` | `CSSProperties` | Unset | Button CSS styles, such as `width`, `height`, `backgroundColor`, `color`, and `borderRadius`. | | `buttons.modalTrigger.icon.url` | `string` | Ringg phone icon | Custom trigger icon URL. | | `buttons.modalTrigger.icon.size` | `number` | `20` | Icon size in pixels. | ## Call button labels ```javascript theme={null} loadAgent({ agentId: "your-agent-id", authorization: "Bearer your-webcall-public-key", buttons: { call: { textBeforeCall: "Start Call", textDuringCall: "End Call", }, }, }); ``` ## Feedback screen Use `feedbackScreen` to customize the post-conversation feedback copy. ```javascript theme={null} loadAgent({ agentId: "your-agent-id", authorization: "Bearer your-webcall-public-key", feedbackScreen: { title: "How was your chat?", description: "Your feedback helps us improve!", submitBtnCTA: "Submit", }, }); ``` | Option | Type | Description | | - | - | - | | `feedbackScreen.title` | `string` | Title shown on the feedback screen. | | `feedbackScreen.description` | `string` | Supporting feedback copy. | | `feedbackScreen.submitBtnCTA` | `string` | Text for the submit button. | # Widget Customization Source: https://docs.ringg.ai/get-started/guides/embedding-widget-customization Restyle and script the Ringg AI web widget using stable data-ringg attributes. Every notable element rendered by the widget carries a stable `data-ringg=""` attribute, and state-bearing elements carry additional `data-ringg-` attributes that update as the widget changes state. Use them as CSS selectors or JS query targets to restyle, hide, rearrange, or script the widget. Do not target the internal `ringg_ai-*` class names. They are minified output and change between releases. Style and script the widget through `data-ringg` attributes only. ## Quick example ```css theme={null} [data-ringg="trigger-button"] { background: #4F46E5; border-radius: 50%; } [data-ringg="message"][data-ringg-role="agent"] [data-ringg="message-bubble"] { font-style: italic; } ``` ```javascript theme={null} document.querySelector('[data-ringg="mute-button"]')?.click(); ``` ## State attributes State-bearing elements expose additional `data-ringg-` attributes. They update live, so you can drive CSS off them with attribute selectors or watch them with `MutationObserver`. | Attribute | Values | Emitted on | | - | - | - | | `data-ringg-role` | `"agent"` / `"user"` | `message` | | `data-ringg-muted` | `"true"` / `"false"` | `mute-button` | | `data-ringg-connecting` | `"true"` / `"false"` | `header-status-dot` | | `data-ringg-align` | `"center"` / `"end"` | `quick-replies` (centered in voice, right-aligned in chat) | | `data-ringg-style` | `"primary"` / `"secondary"` / `"outline"` / `"destructive"` | `quick-reply-button`, `option-row` | | `data-ringg-variant` | `"transcript"` | `feedback-screen` (present when the ended transcript stays readable) | | `data-ringg-active` | `"true"` / `"false"` | `slash-command-item` | | `data-ringg-lit` | `"true"` / `"false"` | `voice-animation-dot` | | `data-ringg-level` | `"info"` / `"error"` | `system-log` | | `data-ringg-step-active` | `"true"` / `"false"` | `flow-step` | | `data-ringg-step-completed` | `"true"` / `"false"` | `flow-step` | | `data-block-id` | authored id string | any Block Kit node with an author id | | `data-action-id` | action id string | `block-button` | Compound selector example: ```css theme={null} [data-ringg="mute-button"][data-ringg-muted="true"] { background: var(--brand-danger); } ``` Observer example: ```javascript theme={null} const muteButton = document.querySelector('[data-ringg="mute-button"]'); new MutationObserver(() => { console.log("muted?", muteButton.getAttribute("data-ringg-muted")); }).observe(muteButton, { attributes: true, attributeFilter: ["data-ringg-muted"], }); ``` ## Element reference Elements are grouped by where they appear in the widget. ### Top level | `data-ringg` | Element | | - | - | | `trigger-button` | Floating launcher button. Visible when the widget is closed. | | `trigger-icon` | The `` rendered inside the trigger button. | | `widget-root` | Outer widget container that wraps every other widget element. Top of the panel tree. | | `widget-body` | Inner flex column inside the widget. Wraps the panel and footer. | | `widget-panel` | Padded main panel. Header, body, and controls render here. | | `minimize-button` | Top-right minimize icon. Only present during a call. | | `close-button` | Top-right close icon. Aria label flips to `"End call"` during a call. | | `voice-animation-wrapper` | Container around the voice visualizer. Audio mode only. | | `body-spacer` | Empty placeholder that keeps controls anchored when the body is empty. | | `transcript` | Scrollable message area. | | `transcript-list` | Inner flex list of messages. | | `controls-bar` | Transparent bar anchoring the message input over the transcript (chat mode). The transcript scrolls underneath it. | | `attached-buttons` | Full-width wrapper for quick replies rendered directly below an agent message. | | `connecting-status` | Wrapper for the pre-call connecting state ("Connecting…" label + loading bar). | | `connecting-label` | The `"Connecting…"` `

` above the loading bar. | | `error-message` | Inline error text. | | `legal-disclaimer` | Pre-call legal `

`. | | `legal-link-privacy` | Privacy policy link inside the legal disclaimer. | | `legal-link-terms` | T\&C link inside the legal disclaimer. | ### Header | `data-ringg` | Element | | - | - | | `header` | In-call header band. **Only present during a call**, which integrators use to detect an active call (e.g. `:has([data-ringg="header"])`). Absolute-positioned frosted overlay. | | `intro` | Pre-call container. Centered logo/title/description block on the start screen (the pre-call counterpart to `header`). | | `header-logo` | Logo chip. Both pre-call (rounded square) and in-call. | | `header-logo-image` | The `` inside the logo chip. | | `header-text` | Text wrapper that holds the title and description. | | `header-title` | Title `

`. | | `header-description` | Description `

`. Shown pre-call and in-call. Truncated in-call (full text on hover via `title`). | | `header-status-dot` | Presence dot. In-call only. Carries `data-ringg-connecting`: muted and pulsing while connecting, success-colored once live. | | `header-status` | Screen-reader-only status `

`. In-call only; visible status is the dot. The pre-call connecting status moved to `connecting-label`. | ### Call controls (audio mode) Compact centered mute/end pair, no text labels, since icons carry the meaning. | `data-ringg` | Element | | - | - | | `call-controls` | Row container holding the call control buttons. | | `mute-button` | Mute toggle button (aria-label `"Mute"` / `"Unmute"`). Carries `data-ringg-muted`. | | `end-call-button` | End-call button (aria-label `"End call"`). | ### Action buttons (start screen) The start screen shows both buttons side by side (Chat left, Call right), each starting its mode directly. With `hideTabSelector: true` only the `defaultTab` mode's button renders, full-width. | `data-ringg` | Element | | - | - | | `start-actions` | Row wrapping the Chat + Call pair. Only when both buttons are shown. | | `start-call-button` | Starts a voice call. | | `start-chat-button` | Starts a chat. | ### Loading bar | `data-ringg` | Element | | - | - | | `loading-bar` | Loading bar container. | | `loading-bar-track` | Background track. | | `loading-bar-fill` | Animated fill. | ### Quick replies and options Quick-reply chips (`free` presentation) and boxed option lists rendered below an agent message. | `data-ringg` | Element | | - | - | | `quick-replies` | Chip row container. Carries `data-ringg-align` (`"center"` in voice, `"end"` in chat). | | `quick-reply-button` | Each pill chip. Carries `data-ringg-style`. | | `buttons-step-title` | Optional title `

` above the chips. | | `options-list` | Boxed single-choice list container (rows divided by hairlines). | | `option-row` | Each option row. Carries `data-ringg-style`. | | `option-radio` | Radio affordance inside an option row. | ### Typing indicator Shown while an agent reply is pending. Cycles through words (default: Thinking / Reasoning / Working on it / Almost there; override with the `typingWords` config) each rendered with a left→right text shimmer. | `data-ringg` | Element | | - | - | | `typing-indicator` | Outer row. | | `typing-indicator-word` | The shimmering current word ``. | ### Messages | `data-ringg` | Element | | - | - | | `message` | Outer message row. Carries `data-ringg-role="agent"` / `"user"`. | | `message-bubble` | The bubble inside a message row. Agent messages are bubble-less unless the theme sets `agentBubbleColor`. | | `message-content` | Inner column inside the bubble. | | `message-body` | Markdown-rendered message body. | | `message-source` | "Source:" link rendered below a message. | ### System log pill The system log pill renders the inline activity feed in the transcript. It only shows up when you opt in via `loadAgent({ eventLogs: { enabled: true } })`. See [Agent actions](/get-started/guides/embedding-widget-components-data#agent-actions) for details. | `data-ringg` | Element | | - | - | | `system-log` | Outer container. Carries `data-ringg-level="info"` / `"error"`. | | `system-log-pill` | Pill body. | | `system-log-dot` | Status dot. | | `system-log-label` | Label text. | | `system-log-meta` | Optional meta text. | ### Slash command menu | `data-ringg` | Element | | - | - | | `slash-command-menu` | Outer container. | | `slash-command-header` | Header bar with the title. | | `slash-command-heading` | "Commands" label. | | `slash-command-list` | Scrollable list of command items. | | `slash-command-item` | Each command button. Carries `data-ringg-active`. | | `slash-command-icon` | Icon square inside an item. | | `slash-command-text` | Text column inside an item. | | `slash-command-name` | Command display name. | | `slash-command-description` | Command description text. | ### Voice animation | `data-ringg` | Element | | - | - | | `voice-animation` | Visualizer root (set on the same element that receives `localTrack`/`remoteTrack`). | | `voice-animation-column` | One column of dots (22 columns per visualizer). | | `voice-animation-dot` | Individual dot. Carries `data-ringg-lit`, which flips per audio frame. | `data-ringg-lit` updates at audio rate. Keep CSS transitions on it lightweight, for example `transition: opacity 50ms`. Heavy transitions or expensive observers on this attribute will fire every frame. ### Interactive flow | `data-ringg` | Element | | - | - | | `interactive-flow` | Outer container. | | `flow-stepper` | Stepper header (shown only when multi-step). | | `flow-stepper-progress` | Row of step indicators. | | `flow-step` | Each step + connector pair. Carries `data-ringg-step-active` and `data-ringg-step-completed`. | | `flow-step-indicator` | Numbered/check circle for each step. | | `flow-step-connector` | Line between steps. | | `flow-step-title` | Current step title `

`. | | `flow-content` | Step body wrapper. | | `flow-back-button` | Back navigation button. | | `flow-submitted-selection` | Submitted-state wrapper. | | `flow-submitted-pill` | Pill showing the selected choice. | ### Message input (text mode) | `data-ringg` | Element | | - | - | | `message-input-form` | The `

` element. | | `message-input` | Outer pill container carrying the frosted-glass treatment; transparent gutters. Also wraps the slash menu when open (going solid). | | `message-input-row` | Row containing the input field + send button. | | `message-input-field` | The `` element. | | `message-send-button` | Send arrow button. | ### Feedback screen When the ended conversation has text messages, the transcript stays readable and the rating renders as a footer below it (`data-ringg-variant="transcript"`); tapping a star submits immediately. The legacy centered card (comment box + submit/skip) renders when there is no transcript. **Transcript variant** | `data-ringg` | Element | | - | - | | `feedback-screen` | Container. Carries `data-ringg-variant="transcript"`. | | `feedback-footer` | Divider + prompt + stars block below the read-only conversation. | | `conversation-ended` | "Conversation ended" hairline divider row. | | `feedback-prompt` | "Please rate your experience" `

`. | | `feedback-stars` | Star row. | | `feedback-star` | Each star button. Carries `data-ringg-filled`. | **Legacy centered card** | `data-ringg` | Element | | - | - | | `feedback-screen` | Container. | | `feedback-header` | Title + description block. | | `feedback-title` | Title `

`. | | `feedback-description` | Description `

`. | | `feedback-stars` | Star row. | | `feedback-star` | Each star button. | | `feedback-comment` | Comment `