---
name: Ringg
description: Use when building voice calling integrations, configuring AI assistants for outbound/inbound/web calls, managing campaigns, setting up webhooks for real-time call events, or querying call history and analytics. Agents should reach for this skill when working with REST APIs to trigger calls, upload campaign CSVs, manage phone numbers, or integrate call results into backend systems.
metadata:
    mintlify-proj: ringg
    version: "1.0"
---

# Ringg AI Skill

## Product Summary

Ringg AI is a platform for building programmable voice agents that make outbound calls, receive inbound calls, embed in web applications, and run bulk campaigns. Agents use the REST API to initiate calls, upload campaign contact lists, manage phone numbers, subscribe to webhooks for real-time events, and retrieve call history and analytics. The platform is configured through the dashboard (assistants, prompts, knowledge bases, numbers) and triggered via API from your backend.

**Key files and commands:**
- Base URL: `https://prod-api.ringg.ai/ca/api/v0`
- Authentication: `X-API-KEY` header (server-side only)
- Core IDs to store: `agent_id`, `from_number_id`, `call_id`, `bulk_list_id`
- Primary docs: https://docs.ringg.ai

## When to Use

Reach for this skill when:

- **Building outbound call flows**: Triggering individual calls via `POST /calling/outbound/individual` with recipient, assistant, caller number, and custom variables
- **Running bulk campaigns**: Uploading CSV contact lists, mapping columns to assistant variables, starting campaigns with `POST /campaign/start`
- **Configuring assistants**: Setting up prompts, voices, custom variables, knowledge bases, call settings, and custom analysis fields
- **Managing phone numbers**: Buying numbers, assigning to campaigns, using `from_number_id` in API calls
- **Receiving real-time events**: Subscribing assistants to webhooks for `call_started`, `call_completed`, `recording_completed`, `platform_analysis_completed`, `client_analysis_completed`, or `all_processing_completed`
- **Querying call results**: Retrieving transcripts, recordings, classifications, and performance metrics via history APIs
- **Troubleshooting calls**: Debugging why calls don't start, variables aren't spoken, or webhooks aren't firing

## Quick Reference

### API Endpoints by Task

| Task | Endpoint | Method |
|------|----------|--------|
| Verify API key | `GET /workspace` | GET |
| List assistants | `GET /agent/all` | GET |
| Get assistant details | `GET /agent/{agent_id}` | GET |
| List phone numbers | `GET /workspace/numbers` | GET |
| Make one call | `POST /calling/outbound/individual` | POST |
| Upload campaign CSV | `POST /campaign/save` | POST |
| Start campaign | `POST /campaign/start` | POST |
| Get call history | `GET /calling/history` | GET |
| Get call details | `GET /calling/history/{call_id}` | GET |
| Subscribe to webhooks | `PATCH /agent/v1` (operation: edit_event_subscriptions) | PATCH |
| Get platform analytics | `GET /analytics/platform` | GET |

### Required Headers

```bash
X-API-KEY: your-workspace-api-key
Content-Type: application/json
```

For CSV uploads, use `multipart/form-data` and let your HTTP client set the boundary.

### Phone Number Format

Always use E.164 format with country code:
- ✅ `+919876543210` (India)
- ✅ `+14155552671` (USA)
- ❌ `9876543210` (missing country code)
- ❌ `+91 9876543210` (spaces)

### Custom Variables in Prompts

Reference variables with `@{{variable_name}}`:
```
Hello, this is Ananya from Aakash Digital. Am I speaking with @{{callee_name}}?
Your order @{{order_id}} is ready for pickup.
```

Match variable names exactly in:
- Prompt placeholders: `@{{callee_name}}`
- CSV column headers: `callee_name`
- API `custom_args_values`: `{"callee_name": "John"}`

### Webhook Event Types

| Event | When It Fires | Typical Use |
|-------|---------------|-------------|
| `call_started` | Call registered and queued (before dialing) | Mark call as queued in your system |
| `call_completed` | Call attempt finishes (any outcome) | Store transcript, duration, retry data |
| `recording_completed` | Recording processed and ready | Download and store recording (24-hour window) |
| `platform_analysis_completed` | Ringg AI analysis finishes | Store summary, classification, key points |
| `client_analysis_completed` | Custom analysis finishes | Store your configured analysis fields |
| `all_processing_completed` | All post-call processing done | Receive final consolidated payload with everything |

**Recommendation**: Start with `all_processing_completed` for production integrations. Add earlier events only if your UI needs live progress updates.

### Call Status and Sub-Status

| Status | Meaning |
|--------|---------|
| `registered` | Call queued for dialing (not placed yet) |
| `ongoing` | Call connected and in progress |
| `completed` | User picked up and conversation happened |
| `failed` | Retries exhausted, call didn't succeed |
| `error` | Terminal error, call never placed |
| `cancelled` | Call ended before connecting |

Sub-status refines the status (e.g., `ACCEPTED`, `busy line`, `no answer`, `not_able_to_call`).

## Decision Guidance

### When to Use Individual Call vs Campaign API

| Scenario | Use Individual Call | Use Campaign |
|----------|-------------------|--------------|
| One user action triggers one call | ✅ | ❌ |
| Bulk calling 100+ contacts | ❌ | ✅ |
| Transactional calls (order confirmation, reminder) | ✅ | ❌ |
| Scheduled outreach to a list | ❌ | ✅ |
| Need to pass dynamic data per call | ✅ | ✅ (via CSV) |
| Need retry logic | ✅ | ✅ |

### When to Use `from_number_id` vs `from_number`

| Approach | When to Use | Tradeoff |
|----------|------------|----------|
| `from_number_id` | Always, when available | Stable across number formatting changes |
| `from_number` | Only when `from_number_id` not available | Brittle if number format changes |

**Rule**: Provide exactly one, never both.

### When to Use Deterministic vs Non-Deterministic Knowledge Base

| Type | Best For | Setup Effort |
|------|----------|--------------|
| Deterministic KB | Pricing tables, policy fields, product catalogs, eligibility rules | More setup, more predictable |
| Non-Deterministic KB | FAQs, articles, manuals, SOPs | Faster setup, needs more testing |

### When to Use Standard Campaign vs Large Campaign Flow

| Flow | CSV Size | Upload Method | Polling Required |
|------|----------|---------------|------------------|
| Standard | < 5,000 rows | `POST /campaign/save` | No |
| Large (beta) | ≥ 5,000 rows | `POST /campaign/upload-csv` | Yes, poll upload status |

## Workflow

### Making Your First Outbound Call

1. **Verify authentication**: Call `GET /workspace` with your API key to confirm access and check available credits.

2. **Select an assistant**: Call `GET /agent/all` and choose an assistant configured for outbound calls. Save the `agent_id`.

3. **Select a caller number**: Call `GET /workspace/numbers` and choose a number. Save the `from_number_id` (preferred) or `from_number`.

4. **Prepare the recipient**: Validate the phone number is in E.164 format with country code (e.g., `+919876543210`).

5. **Prepare custom variables**: Create a JSON object with any variables your prompt uses (e.g., `{"callee_name": "John", "order_id": "ORD-42"}`).

6. **Initiate the call**: POST to `/calling/outbound/individual` with recipient, assistant, caller number, and variables.

7. **Store the call ID**: Save the returned `call_id` for webhook deduplication and history lookup.

8. **Receive results**: Either subscribe to webhooks for real-time events or poll `GET /calling/history` for batch reporting.

### Running a Campaign

1. **Prepare the CSV**: Create a file with columns for phone number and any custom variables. Download the template from the dashboard for your agent.

2. **Validate the CSV**: Ensure phone numbers have country codes, headers match assistant variable names, and no extra spaces.

3. **Upload the CSV**: POST to `/campaign/save` with the CSV file, agent ID, campaign name, and call configuration (timing, retries, timezone).

4. **Save the list ID**: Store the returned `list_id` from the upload response.

5. **Configure campaign settings**: Set start/end times, timezone, caller numbers, and email notifications.

6. **Start the campaign**: POST to `/campaign/start` with the `list_id` and selected caller numbers.

7. **Monitor progress**: Use `GET /campaign/all` to check status, or subscribe to webhooks for per-call events.

### Setting Up Webhooks

1. **Choose events**: Decide which events your system needs (typically `all_processing_completed` for production).

2. **Prepare your endpoint**: Create an HTTPS endpoint that accepts POST requests, validates the event, stores it idempotently (using `call_id` + `event_type` as dedupe key), and returns `2xx` quickly.

3. **Configure subscriptions**: PATCH `/agent/v1` with `operation: "edit_event_subscriptions"`, providing the event types, callback URL, and optional authentication headers.

4. **Test the webhook**: Make a test call and verify your endpoint receives the event.

5. **Make handlers idempotent**: Store `call_id` + `event_type` to avoid duplicate processing if Ringg retries the webhook.

6. **Do heavy work asynchronously**: Return `2xx` immediately, then process the event in your own job queue.

## Common Gotchas

- **API key in client code**: Never put `X-API-KEY` in browser or mobile app source code unless using the managed web widget flow. Keep it server-side only.

- **Phone number format**: Missing country code is the #1 cause of "call does not start." Always validate E.164 format before sending.

- **Variable name mismatch**: If the prompt says `@{{callee_name}}` but your CSV has a column named `name`, the variable won't be filled. Match names exactly across prompt, CSV, and API payloads.

- **Both `from_number_id` and `from_number`**: The API rejects requests with both fields. Provide exactly one.

- **Webhook endpoint not returning 2xx**: Ringg will retry the webhook if you don't return a `2xx` status quickly. Return 204 or 200 immediately, then do heavy processing asynchronously.

- **Recording URL expires in 24 hours**: If you need to keep recordings, download them within 24 hours of the `recording_completed` event.

- **Campaign CSV headers with spaces**: `"Mobile Number"` (with space) is correct; `"MobileNumber"` (no space) will fail. Download the template to get the exact format.

- **Calling window timezone mismatch**: If you set `call_start_time: "09:00"` and `timezone: "Asia/Kolkata"` but the recipient is in a different timezone, calls may not go out when expected. Confirm timezone with the business owner.

- **Forgetting to store call IDs**: Without `call_id`, you can't match webhook events to your internal records or debug support issues. Always store it.

- **Not deduping webhook events**: If your handler processes the same event twice, you'll double-count calls or create duplicate records. Use `call_id` + `event_type` as the dedupe key.

- **Polling history instead of webhooks**: For production, webhooks are faster and more reliable than polling. Use history APIs only for dashboards and reconciliation.

- **Custom analysis without testing**: Configure custom analysis fields, then run a test call before launching. Verify the extracted fields are useful.

## Verification Checklist

Before submitting work with Ringg AI:

- [ ] API key is stored in server-side secrets, not in code or logs
- [ ] Phone numbers are validated in E.164 format with country code
- [ ] Custom variable names match exactly in prompt, CSV, and API payloads
- [ ] Exactly one of `from_number_id` or `from_number` is provided (not both)
- [ ] `call_id` is stored for every call initiated
- [ ] Webhook endpoint returns `2xx` within a reasonable time
- [ ] Webhook handler is idempotent (dedupes on `call_id` + `event_type`)
- [ ] Heavy webhook processing is done asynchronously, not in the response handler
- [ ] Campaign CSV headers match the template format (e.g., "Mobile Number" with space)
- [ ] Calling window timezone is confirmed with the business owner
- [ ] Test call was made and transcript/analysis/recording were verified
- [ ] Recording URLs are downloaded within 24 hours if retention is needed
- [ ] Error handling covers `401 Unauthorized`, `400 Bad Request`, and `429 Too Many Requests`

## Resources

- **Full page navigation**: https://docs.ringg.ai/llms.txt
- **Quick Start Guide**: https://docs.ringg.ai/api-reference/quick-start/guide
- **API Overview**: https://docs.ringg.ai/api-reference/quick-start/api-overview
- **Webhook Setup**: https://docs.ringg.ai/webhooks/initial-setup

---

> For additional documentation and navigation, see: https://docs.ringg.ai/llms.txt