List campaigns, newest first (cursor-paginated)
Archived campaigns are hidden by default; pass archived=true to see only those. There is deliberately no way to ask for both at once.
Requires the read scope. A key with less gets 403 insufficient_scope.
Authorization: Bearer tone_live_… or tone_test_…. The prefix IS the environment: a test key reaches only the sandbox, and no request field bridges the two.
In: header
Query Parameters
How many results to return. 1-100, defaulting to 25.
1 <= value <= 10025Opaque page cursor — pass meta.pagination.cursor from the previous response to fetch the next page. Its contents are an implementation detail; do not parse or construct one.
1 <= lengthOnly campaigns in this state. Open set — handle an unrecognised value rather than throwing. Today: draft, scheduled, running, paused, completed, stopped, failed.
Value in
- "draft"
- "scheduled"
- "running"
- "paused"
- "completed"
- "stopped"
- "failed"
Only campaigns running this agent.
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$uuidIgnored when you authenticate with an API key: the key prefix pins the environment.
Value in
- "live"
- "test"
Inclusive lower bound on when the campaign was created.
Exclusive upper bound on when the campaign was created.
true returns ONLY archived campaigns; the default returns only unarchived ones. There is deliberately no way to ask for both.
Value in
- "0"
- "1"
- "true"
- "false"
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/campaigns"{ "data": [ { "agent": { "id": "9f1c2d84-4e3a-4f6c-b902-7d1e8a33c451", "name": "Order confirmation" }, "archivedAt": null, "autoPauseBelowPaise": 50000, "completedAt": null, "createdAt": "2026-08-25T09:14:22Z", "environment": "live", "id": "9f1c2d84-4e3a-4f6c-b902-7d1e8a33c451", "launchedAt": "2026-09-01T04:00:00Z", "name": "COD confirmations — September", "number": { "e164": "+918045678901", "id": "4c8b1e77-3d2a-4f5b-9e6c-8a7b6c5d4e3f" }, "pacing": { "callsPerMinute": 10, "maxConcurrent": 4 }, "pausedReason": "operator", "preflight": { "callable": 0, "checks": [ { "outcome": "pass", "reason": "Outside the 09:00-21:00 IST window for promotional calls.", "type": "time_window" } ], "computedAt": "2026-09-01T03:58:12Z", "estimatedCostPaise": { "high": 480000, "low": 120000 }, "excluded": "invalid_number", "excludedE164s": {}, "total": 0, "walletBalancePaise": 500000 }, "progress": { "connected": 244, "dialed": 320, "excluded": 31, "spentPaise": 146400, "total": 500 }, "purpose": "transactional", "retries": { "attempts": 1, "backoff": "linear", "intervalMinutes": 60, "on": [ "no_answer", "busy" ] }, "schedule": { "endsAt": "2026-09-07T14:00:00Z", "startsAt": "2026-09-01T04:00:00Z", "weekdays": 31, "windowEndMinute": 1260, "windowStartMinute": 540 }, "status": "running", "updatedAt": "2026-08-25T09:14:22Z" } ]}Apply the pre-flight exclusions and start dialling (requires Idempotency-Key)
🔴 Idempotency-Key is REQUIRED — without it this returns 400. Launching twice would dial the whole list twice, which is exactly the complaint pattern TCCCPR punishes. Refused if the agent is still a draft, if the number routes to your own stack, or if any pre-flight check blocks. Scrubbing runs here and MUST succeed: a scrubber outage fails the launch rather than passing an unscrubbed list.
List a campaign's recipients and their outcomes
A recipient row names its LAST attempt. For every call the campaign placed, retries included, filter GET /v1/calls by campaign_id instead.