Overview
A campaign in RevRag is a workspace-scoped definition that bundles an agent, a schedule, retry/follow-up rules, and concurrency limits. This page documents the endpoints you use to push records into an already-running campaign and to track their status:| Endpoint | Use when |
|---|---|
POST /records/push-bulk | Push one or more records into the campaign (a single record goes as a 1-element list) |
GET /records/{run_id} | Poll the status of a record you pushed (by the run_id returned on push) |
GET /records | List a campaign’s records, filterable by status |
GET /status | Get the campaign’s status + per-status record counts |
run_id for every record so you can correlate and poll each one.
The campaign itself — name, agent, schedule, end date, retry rules, concurrency — is configured and launched in the RevRag dashboard. By the time you call these APIs, the campaign should already be running. The dashboard’s Campaign → Settings tab shows a copy-pasteable curl with your campaign’s id pre-filled.
Base URLs
- Production:
https://api.revrag.ai - Staging:
https://staging-api.revrag.ai
Authentication
All requests require a workspace-scoped API key in theX-API-Key header:
404 Not Found.
Before You Push
The campaign is fully created, configured, and started from the RevRag dashboard. From the API caller’s side you only need:- The
campaign_id— copy it from the dashboard’s Campaign → Settings tab (it’s also in the URL of the campaign detail page). - Your
X-API-Key— issued for your workspace. - The agent’s variable names, if the agent expects per-call variables. Variable names are visible on the campaign’s Settings tab.
Endpoints
1. Push Records
POST/v1/campaigns/{campaign_id}/records/push-bulk
Queue one or more records for calling. Send a single record as a 1-element records array. Each record is treated independently — the runner picks them up on its next polling cycle (typically within ~1 second) and dispatches each call subject to the campaign’s daily time-window, attempt schedule, and concurrency cap. Invalid records are rejected individually (partial success), all in a single 200 OK.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
campaign_id | string (uuid) | Yes | The campaign to push records into |
Header Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Workspace-scoped API key |
Content-Type | string | Yes | Must be application/json |
Request Body
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
records | array | Yes | One or more records to push (use a 1-element array for a single record) |
records:
| Field | Type | Required | Description |
|---|---|---|---|
phone_number | string | Yes | E.164 format recommended (+919876543210) |
variables | object | No | Key-value pairs matching the agent’s variable names. Sent into the agent’s prompt at call time |
app_user_id | string | No | Your system’s user id — a top-level correlation field (not inside variables). Returned top-level on the record and in webhooks |
app_session_id | string | No | Your system’s session id — a top-level correlation field (not inside variables). Returned top-level on the record and in webhooks |
Response
The response returns a per-record result for every record you submitted, in the same order as therecords array (results[i] corresponds to records[i]). Each accepted record carries its own run_id so you can correlate every record to its created run and poll its status later (see Get Record Status).
Success (200 OK)
accepted: false, run_id: null, and an error message.
Response Parameters
| Parameter | Type | Description |
|---|---|---|
accepted | number | How many records were inserted and queued for calling |
rejected | number | How many were rejected (e.g. invalid phone number) |
results | array | Per-record outcome, in the same order as the submitted records. See fields below |
results:
| Field | Type | Description |
|---|---|---|
phone_number | string | The phone number you submitted for this record |
accepted | boolean | true if the record was created and queued, false if rejected |
run_id | string (uuid) | null | The created run id — present when accepted: true. Use it with Get Record Status |
status | string | null | Initial status (queued) when accepted, null when rejected |
error | string | null | Why the record was rejected — present when accepted: false |
Pushing a single record? Send a 1-elementrecordsarray — you get that record’srun_idback inresults[0].
cURL Example
2. Get Record Status
GET/v1/campaigns/{campaign_id}/records/{run_id}
Fetch the current status and details of a pushed record, using the run_id you got back from the push (results[].run_id).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
campaign_id | string (uuid) | Yes | The campaign the record belongs to |
run_id | string (uuid) | Yes | The record’s run id (from the push response) |
Header Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Workspace-scoped API key |
Response
Success (200 OK) — the full campaign record:status means. The call_history array holds one entry per attempt, including the per-call call_id you can pass to Get Call Status for the transcript and recording.
cURL Example
3. List Records
GET/v1/campaigns/{campaign_id}/records
List the campaign’s records, optionally filtered by status — useful for polling everything in a given state (e.g. all queued, or all completed).
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | Filter by record status (e.g. queued, completed, failed) |
page | number | No | 1-based page number (default 1) |
page_size | number | No | Records per page (default 50, max 200) |
Response
Success (200 OK)cURL Example
4. Get Campaign Status
GET/v1/campaigns/{campaign_id}/status
Get the campaign’s lifecycle status plus aggregate per-status record counts — a quick way to track overall progress without listing every record.
Response
Success (200 OK)Response Parameters
| Parameter | Type | Description |
|---|---|---|
campaign_id | string (uuid) | The campaign |
status | string | Campaign lifecycle status (running, paused, completed, cancelled, …) |
stats | object | Per-status record counts (total_records, queued, in_progress, completed, failed, dnc, rescheduled, retry_pending, follow_up_pending) |
cURL Example
How Records are Called
Pushing a record does not always trigger an immediate dial. After your push is accepted, the campaign runner picks up queued records each cycle and applies the campaign’s configured gates (all set in the dashboard):| Gate | Effect on your record |
|---|---|
| Outside the campaign’s daily calling window | Stays queued until the window opens |
| Day not in the campaign’s active days (e.g. weekend on a Mon-Fri campaign) | Queued until the next active day’s window |
| First-attempt schedule is later than today | Queued until that day |
| Campaign’s max concurrency reached | Queued until a slot frees |
| Phone is in the workspace’s Do-Not-Call list | Marked dnc, no call placed |
400. The campaign must be in an active state on the dashboard to accept pushes.
Get Call Status
GET/v1/campaigns/trigger/status/{call_id}
Fetch the status, transcript, recording URL, summary, and extracted variables for a specific call. The call_id for a pushed record is available in the record’s call_history (via Get Record Status), delivered via webhook (see below), or visible on the campaign’s Records tab in the dashboard. The push response itself returns the record’s run_id (not the per-call call_id) — the call is placed asynchronously by the campaign runner, so poll the record (or wait for the webhook) to get the call_id.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
call_id | string (uuid) | Yes | The call id, obtained from the webhook payload or from the dashboard |
Header Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Workspace-scoped API key |
Response
Success (200 OK)Response Parameters
| Field | Type | Description |
|---|---|---|
call_status | string | Final call status (e.g. completed, failed) |
call_id | string (uuid) | The call this status is for |
agent_id | string (uuid) | The agent that placed the call |
from_number / to_number | string | Caller / callee numbers |
summary | string | LLM-generated call summary (when a transcript exists) |
start_time / end_time | string | null | ISO-8601 timestamps |
duration | number | Call duration in seconds |
disconnection_reason | string | null | Normalized hangup reason |
recording_url | string | null | Presigned recording URL (for transcribed calls) |
transcription | object | null | Turn-by-turn messages |
custom_variables | array | Post-call variables extracted by the agent (key, type, value) |
variables_fields | object | null | The variables you sent on push (correlation IDs are surfaced top-level instead) |
campaign_id | string (uuid) | null | Campaign the call belongs to (null for non-campaign calls) |
attempt_no | number | null | Which attempt this call was |
app_user_id / app_session_id | string | null | Your correlation IDs (top-level), if you sent them |
cURL Example
Webhook Notifications
Instead of polling for status, configure a webhook URL to receive aPOST notification when each call ends. Webhooks fire for every call placed by the agent — including calls dispatched from campaigns pushed via this API.
Configuration
Contact contact@revrag.ai to configure your webhook URL and signing secret.Security & Headers
Campaign webhooks use the same signing scheme as every RevRag webhook — HMAC-SHA256 computed over"{timestamp}.{raw_body}" with your shared secret. Each request carries:
| Header | Purpose |
|---|---|
X-Webhook-Event | Event type (call.ended) |
X-Webhook-Timestamp | Unix timestamp (seconds) the webhook was sent |
X-Webhook-Signature | t=<timestamp>,v1=<hmac_sha256_hex> |
X-Webhook-ID | Unique id for deduplication |
Payload
The webhook body is the same JSON shape as the Get Call Status response. For calls placed from a campaign it also carriescampaign_id, attempt_no, and your top-level correlation IDs app_user_id / app_session_id. The variables you sent are echoed back as variables_fields (with the correlation IDs kept out of it).
Record Status Values
| Status | Description |
|---|---|
queued | Accepted, waiting for the runner to pick it up |
in_progress | Call is being placed or is live |
completed | Call finished — see call_history on the record for details |
failed | Call attempt failed (e.g. telephony error). Will retry if attempts remain and retry conditions match |
retry_pending | Waiting for the next retry attempt at next_attempt_at |
follow_up_pending | Waiting for a follow-up attempt scheduled by post-call logic |
rescheduled | Caller requested a callback — will dispatch at the requested time |
dnc | Phone added to Do-Not-Call list, no further attempts |
Common Errors
| Status | When |
|---|---|
400 Bad Request | Campaign is not currently accepting pushes (e.g. already finished or cancelled on the dashboard). A malformed phone_number is not a request-level error — it’s rejected per-record in results (still 200) |
401 Unauthorized | Missing or invalid X-API-Key header |
404 Not Found | campaign_id doesn’t exist in the API key’s workspace, or campaign_id isn’t a valid UUID |
422 Unprocessable Entity | Request body doesn’t match the schema (missing phone_number, malformed JSON, etc.) |