Graine AI
API referenceCampaigns

Get a campaign's live progress

Everything needed to render a campaign's progress, computed on read.

Everything needed to render a campaign's progress, computed on read.

outcome_counts is the set to render. Its four buckets are mutually exclusive and always sum to total, and completed is sticky: a contact that answered on any attempt stays completed even if a later follow-up fails, so the number only ever goes up.

Three numbers that are routinely misread:

  • contacts_dialled counts DISTINCT contacts dialled at least once. It is not the first-attempt call count, which double-counts any contact re-queued with a fresh retry budget — that is how "2,745 dialled" appears on a 2,504-contact list.
  • call_counters.voicemail_calls is a SUBSET of no_answer_calls, not a peer of it. Adding them together double-counts. It is the "how much of this campaign is hitting an answering machine" dimension, and a high number means the calling window is wrong.
  • retry_breakdown counts calls per retry depth and EXCLUDES follow-ups, which are reported separately as follow_up_attempts. Duplicate legs of a call that was already counted are excluded everywhere, so these totals agree with the call list.

Rate limit: 1000 requests per minute per organization (bucket default). Exceeding it returns 429 with Retry-After; the X-RateLimit-* response headers report your remaining allowance on every call.

GET
/v2/campaigns/{campaign_id}/stats
/v2/campaigns/31ff3ea9-8bb5-433f-868f-286ac3c31328/stats

The Authorization access token

Authorization

Authorization
Required
Bearer <token>

Your Graine API key. Create one in the dashboard under Developers, or via POST /v2/api-keys. Send it as Authorization: Bearer <key>.

In: header

Path Parameters

campaign_id
Required
Campaign Id

Campaign identifier.

Query Parameters

organization_idOrganization Id

Must match the organisation the API key belongs to.

Response Body

200

Live contact, batch and call numbers for this campaign.

campaign_id
Required
Campaign Id

Campaign identifier.

status
Required
Status

The campaign's status at the moment of the read.

timezoneTimezone

IANA timezone the windows are evaluated in.

Default: "UTC"

working_hours_enforcedWorking Hours Enforced

Whether dialling is confined to the windows.

Default: false

start_timeStart Time | null

ISO-8601 UTC.

end_timeEnd Time | null

ISO-8601 UTC.

total_contactsTotal Contacts

Contacts across every batch, counted live.

Default: 0

contacts_dialledContacts Dialled | null

DISTINCT contacts dialled at least once. Never inferred from the first-attempt call bucket, which double-counts a contact that was re-queued with a fresh retry budget.

in_flight_contactsIn Flight Contacts

Contacts dispatching, ringing or talking now.

Default: 0

outcome_counts
Required
Outcome Counts

The authoritative progress numbers.

contact_countsContact Counts

Live per-status contact histogram, for drill-downs. Statuses overlap the buckets above.

batch_countsBatch Counts

How many batches sit in each batch status.

call_counters
Required
Call Counters

Stored per-call counters.

retry_breakdownRetry Breakdown | null

Calls placed at each retry depth: '0' is first attempts, '1' the first retry, and so on. Null when the histogram could not be computed for this campaign.

follow_up_attemptsFollow Up Attempts | null

Follow-up calls placed, excluded from retry_breakdown. Null when unavailable.

total_call_attemptsTotal Call Attempts | null

Every dial placed, retries and follow-ups included. Duplicate legs excluded. Null when unavailable.

retry_policy
Required
Retry Policy

The policy these numbers ran under.

400

1000 — malformed or contradictory input: an unknown timezone, a working-hours window that is not 24-hour HH:MM, an end_time at or before start_time, or an empty patch body. 1002 — a required parameter is missing.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

401

1100 — missing, unknown or inactive API key. 1101 — a browser session token was presented.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

403

1102 — the key is valid but lacks the scope this endpoint requires, or names another organisation. GET /v2/scopes reports which scopes the key holds.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

404

1200 — no such campaign, or no such agent, in this organisation. A campaign belonging to another organisation answers 404, never 403, so ids cannot be probed.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

422

1001 — the body or query failed validation; the message names the first offending field.

error
Required
integer

Stable integer code from the error table. Branch on this, not on the message.

message
Required
string

One human-readable sentence. Wording may change; the code will not.

429

1300 — per-organisation rate limit exceeded. Carries Retry-After.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

503

1501 — the agent service is unreachable or returned a 5xx.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

504

1502 — the agent service did not respond in time.

error
Required
Error

Stable integer code from the /v2 error table. Branch on this.

message
Required
Message

One human-readable sentence. Wording may change; the code will not.

curl -X GET "https://api.graine.ai/v2/campaigns/31ff3ea9-8bb5-433f-868f-286ac3c31328/stats?organization_id=string" \
  -H "Authorization: Bearer <token>"

Live contact, batch and call numbers for this campaign.

{
  "campaign_id": "31ff3ea9-8bb5-433f-868f-286ac3c31328",
  "status": "paused",
  "timezone": "Asia/Kolkata",
  "working_hours_enforced": true,
  "start_time": "2027-03-02T05:30:00.000Z",
  "end_time": "2027-03-09T11:00:00.000Z",
  "total_contacts": 3000,
  "contacts_dialled": 892,
  "in_flight_contacts": 12,
  "outcome_counts": {
    "completed": 780,
    "failed": 108,
    "in_flight": 12,
    "pending": 2100,
    "total": 3000
  },
  "contact_counts": {
    "pending": 2100,
    "in_progress": 12,
    "completed": 806,
    "failed": 82
  },
  "batch_counts": {
    "running": 1
  },
  "call_counters": {
    "completed_calls": 451,
    "failed_calls": 88,
    "busy_calls": 37,
    "no_answer_calls": 120,
    "voicemail_calls": 14,
    "follow_up_calls": 0
  },
  "retry_breakdown": {
    "0": 888,
    "1": 219,
    "2": 100
  },
  "follow_up_attempts": 0,
  "total_call_attempts": 1207,
  "retry_policy": {
    "max_retries": 5,
    "strategy": "fixed_delay",
    "cooldown_minutes": 45
  }
}