Skip to main content

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:
EndpointUse when
POST /records/push-bulkPush 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 /recordsList a campaign’s records, filterable by status
GET /statusGet the campaign’s status + per-status record counts
The push endpoint returns a 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 the X-API-Key header:
X-API-Key: YOUR_API_KEY
The workspace is resolved from the API key itself — you do not pass a workspace header. The campaign in the path must belong to the same workspace as the API key, otherwise the request returns 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

ParameterTypeRequiredDescription
campaign_idstring (uuid)YesThe campaign to push records into

Header Parameters

ParameterTypeRequiredDescription
X-API-KeystringYesWorkspace-scoped API key
Content-TypestringYesMust be application/json

Request Body

{
  "records": [
    {
      "phone_number": "+919876543210",
      "variables": {
        "first_name": "Pankaj",
        "company": "Acme Inc."
      },
      "app_user_id": "user_12345",
      "app_session_id": "sess_abcdef"
    },
    {
      "phone_number": "+919876543211",
      "variables": { "first_name": "Riya" }
    }
  ]
}

Request Parameters

ParameterTypeRequiredDescription
recordsarrayYesOne or more records to push (use a 1-element array for a single record)
Each record in records:
FieldTypeRequiredDescription
phone_numberstringYesE.164 format recommended (+919876543210)
variablesobjectNoKey-value pairs matching the agent’s variable names. Sent into the agent’s prompt at call time
app_user_idstringNoYour system’s user id — a top-level correlation field (not inside variables). Returned top-level on the record and in webhooks
app_session_idstringNoYour 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 the records 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": 2,
  "rejected": 0,
  "results": [
    {
      "phone_number": "+919876543210",
      "accepted": true,
      "run_id": "00000000-0000-0000-0000-000000000001",
      "status": "queued",
      "error": null
    },
    {
      "phone_number": "+919876543211",
      "accepted": true,
      "run_id": "00000000-0000-0000-0000-000000000002",
      "status": "queued",
      "error": null
    }
  ]
}
Partial success (200 OK) Invalid records are rejected individually — the valid ones are still created. A rejected record has accepted: false, run_id: null, and an error message.
{
  "accepted": 1,
  "rejected": 1,
  "results": [
    {
      "phone_number": "+919876543210",
      "accepted": true,
      "run_id": "00000000-0000-0000-0000-000000000001",
      "status": "queued",
      "error": null
    },
    {
      "phone_number": "not-a-number",
      "accepted": false,
      "run_id": null,
      "status": null,
      "error": "Invalid Indian phone number: not-a-number"
    }
  ]
}

Response Parameters

ParameterTypeDescription
acceptednumberHow many records were inserted and queued for calling
rejectednumberHow many were rejected (e.g. invalid phone number)
resultsarrayPer-record outcome, in the same order as the submitted records. See fields below
Each entry in results:
FieldTypeDescription
phone_numberstringThe phone number you submitted for this record
acceptedbooleantrue if the record was created and queued, false if rejected
run_idstring (uuid) | nullThe created run id — present when accepted: true. Use it with Get Record Status
statusstring | nullInitial status (queued) when accepted, null when rejected
errorstring | nullWhy the record was rejected — present when accepted: false
Pushing a single record? Send a 1-element records array — you get that record’s run_id back in results[0].

cURL Example

curl -X POST \
  "https://staging-api.revrag.ai/v1/campaigns/{campaign_id}/records/push-bulk" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "records": [
      {
        "phone_number": "+919876543210",
        "variables": { "first_name": "Pankaj" }
      },
      {
        "phone_number": "+919876543211",
        "variables": { "first_name": "Riya" }
      }
    ]
  }'

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

ParameterTypeRequiredDescription
campaign_idstring (uuid)YesThe campaign the record belongs to
run_idstring (uuid)YesThe record’s run id (from the push response)

Header Parameters

ParameterTypeRequiredDescription
X-API-KeystringYesWorkspace-scoped API key

Response

Success (200 OK) — the full campaign record:
{
  "id": "00000000-0000-0000-0000-000000000001",
  "campaign_id": "11111111-1111-1111-1111-111111111111",
  "workspace_id": "22222222-2222-2222-2222-222222222222",
  "phone_number": "+919876543210",
  "status": "completed",
  "variables": { "first_name": "Pankaj" },
  "app_user_id": "user_12345",
  "app_session_id": "sess_abcdef",
  "attempt_count": 1,
  "max_attempts": 3,
  "call_history": [{ "call_id": "...", "status": "completed" }],
  "next_attempt_at": null,
  "dnc_at": null,
  "dnc_reason": null,
  "created_at": "2026-05-27T03:00:00.000000+00:00",
  "updated_at": "2026-05-27T03:05:12.000000+00:00"
}
See Record Status Values for what each 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

curl -X GET \
  "https://staging-api.revrag.ai/v1/campaigns/{campaign_id}/records/{run_id}" \
  -H "X-API-Key: YOUR_API_KEY"

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

ParameterTypeRequiredDescription
statusstringNoFilter by record status (e.g. queued, completed, failed)
pagenumberNo1-based page number (default 1)
page_sizenumberNoRecords per page (default 50, max 200)

Response

Success (200 OK)
{
  "items": [
    {
      "id": "00000000-0000-0000-0000-000000000001",
      "phone_number": "+919876543210",
      "status": "completed",
      "attempt_count": 1,
      "max_attempts": 3
    }
  ],
  "total": 100,
  "has_more": true,
  "page": 1,
  "page_size": 50
}
Each item has the same fields as a single record (see Get Record Status).

cURL Example

curl -X GET \
  "https://staging-api.revrag.ai/v1/campaigns/{campaign_id}/records?status=completed&page=1&page_size=50" \
  -H "X-API-Key: YOUR_API_KEY"

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)
{
  "campaign_id": "11111111-1111-1111-1111-111111111111",
  "status": "running",
  "stats": {
    "total_records": 100,
    "queued": 18,
    "in_progress": 4,
    "completed": 70,
    "failed": 3,
    "dnc": 2,
    "rescheduled": 1,
    "retry_pending": 2,
    "follow_up_pending": 0
  }
}

Response Parameters

ParameterTypeDescription
campaign_idstring (uuid)The campaign
statusstringCampaign lifecycle status (running, paused, completed, cancelled, …)
statsobjectPer-status record counts (total_records, queued, in_progress, completed, failed, dnc, rescheduled, retry_pending, follow_up_pending)

cURL Example

curl -X GET \
  "https://staging-api.revrag.ai/v1/campaigns/{campaign_id}/status" \
  -H "X-API-Key: YOUR_API_KEY"

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):
GateEffect on your record
Outside the campaign’s daily calling windowStays 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 todayQueued until that day
Campaign’s max concurrency reachedQueued until a slot frees
Phone is in the workspace’s Do-Not-Call listMarked dnc, no call placed
When all gates are open, dispatch is typically within ~1 second of the push. See Record Status Values for what each status means in flight. If the campaign has Dial first attempt immediately enabled (a dashboard setting), the first attempt skips the first-attempt schedule gate and is dialed as soon as the record is pushed — but still only within the calling window and the concurrency/DNC gates. Retries and follow-ups (attempts 2+) follow all the gates above as normal. If you push to a campaign that has finished (past its end date) or has been cancelled/paused-and-stopped from the dashboard, the API returns 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

ParameterTypeRequiredDescription
call_idstring (uuid)YesThe call id, obtained from the webhook payload or from the dashboard

Header Parameters

ParameterTypeRequiredDescription
X-API-KeystringYesWorkspace-scoped API key

Response

Success (200 OK)
{
  "call_status": "completed",
  "call_id": "123e4567-e89b-12d3-a456-426614174000",
  "agent_id": "33333333-3333-3333-3333-333333333333",
  "from_number": "+911140000000",
  "to_number": "+919876543210",
  "summary": "Customer confirmed the appointment for Friday.",
  "start_time": "2026-05-27T03:05:00+00:00",
  "end_time": "2026-05-27T03:06:12+00:00",
  "duration": 72,
  "disconnection_reason": "agent_hangup",
  "recording_url": "https://.../recording.mp3",
  "transcription": {
    "messages": [
      { "role": "assistant", "content": "Hi Pankaj, calling about your appointment…" },
      { "role": "user", "content": "Yes, Friday works." }
    ]
  },
  "custom_variables": [
    { "key": "appointment_confirmed", "type": "boolean", "value": true }
  ],
  "variables_fields": { "first_name": "Pankaj" },
  "campaign_id": "11111111-1111-1111-1111-111111111111",
  "attempt_no": 1,
  "app_user_id": "user_12345",
  "app_session_id": "sess_abcdef"
}

Response Parameters

FieldTypeDescription
call_statusstringFinal call status (e.g. completed, failed)
call_idstring (uuid)The call this status is for
agent_idstring (uuid)The agent that placed the call
from_number / to_numberstringCaller / callee numbers
summarystringLLM-generated call summary (when a transcript exists)
start_time / end_timestring | nullISO-8601 timestamps
durationnumberCall duration in seconds
disconnection_reasonstring | nullNormalized hangup reason
recording_urlstring | nullPresigned recording URL (for transcribed calls)
transcriptionobject | nullTurn-by-turn messages
custom_variablesarrayPost-call variables extracted by the agent (key, type, value)
variables_fieldsobject | nullThe variables you sent on push (correlation IDs are surfaced top-level instead)
campaign_idstring (uuid) | nullCampaign the call belongs to (null for non-campaign calls)
attempt_nonumber | nullWhich attempt this call was
app_user_id / app_session_idstring | nullYour correlation IDs (top-level), if you sent them

cURL Example

curl -X GET \
  "https://staging-api.revrag.ai/v1/campaigns/trigger/status/123e4567-e89b-12d3-a456-426614174000" \
  -H "X-API-Key: YOUR_API_KEY"

Webhook Notifications

Instead of polling for status, configure a webhook URL to receive a POST 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:
HeaderPurpose
X-Webhook-EventEvent type (call.ended)
X-Webhook-TimestampUnix timestamp (seconds) the webhook was sent
X-Webhook-Signaturet=<timestamp>,v1=<hmac_sha256_hex>
X-Webhook-IDUnique id for deduplication
See Webhook Security for the full verification steps and Python / Node.js examples.

Payload

The webhook body is the same JSON shape as the Get Call Status response. For calls placed from a campaign it also carries campaign_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).
{
  "call_status": "completed",
  "call_id": "123e4567-e89b-12d3-a456-426614174000",
  "agent_id": "33333333-3333-3333-3333-333333333333",
  "from_number": "+911140000000",
  "to_number": "+919876543210",
  "summary": "Customer confirmed the appointment for Friday.",
  "start_time": "2026-05-27T03:05:00+00:00",
  "end_time": "2026-05-27T03:06:12+00:00",
  "duration": 72,
  "disconnection_reason": "agent_hangup",
  "recording_url": "https://.../recording.mp3",
  "transcription": {
    "messages": [{ "role": "assistant", "content": "Hello…" }]
  },
  "custom_variables": [
    { "key": "appointment_confirmed", "type": "boolean", "value": true }
  ],
  "variables_fields": { "first_name": "Pankaj" },
  "campaign_id": "11111111-1111-1111-1111-111111111111",
  "attempt_no": 1,
  "app_user_id": "user_12345",
  "app_session_id": "sess_abcdef"
}

Record Status Values

StatusDescription
queuedAccepted, waiting for the runner to pick it up
in_progressCall is being placed or is live
completedCall finished — see call_history on the record for details
failedCall attempt failed (e.g. telephony error). Will retry if attempts remain and retry conditions match
retry_pendingWaiting for the next retry attempt at next_attempt_at
follow_up_pendingWaiting for a follow-up attempt scheduled by post-call logic
rescheduledCaller requested a callback — will dispatch at the requested time
dncPhone added to Do-Not-Call list, no further attempts

Common Errors

StatusWhen
400 Bad RequestCampaign 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 UnauthorizedMissing or invalid X-API-Key header
404 Not Foundcampaign_id doesn’t exist in the API key’s workspace, or campaign_id isn’t a valid UUID
422 Unprocessable EntityRequest body doesn’t match the schema (missing phone_number, malformed JSON, etc.)
Example error body
{
  "detail": "Cannot push records: campaign is completed."
}

Support

For API keys, campaign setup, or any technical issue, contact contact@revrag.ai.