Skip to main content
The /campaign surface manages outbound calling campaigns: the campaign itself, the contacts you dial, the schedule and agent configurations that drive them, and the org-wide concurrency limit. Every route lives under the /campaign prefix on https://api.anyreach.ai. For the product walkthrough, see Campaigns. For credentials and the X-Anyreach-Org header, see Authentication.

Endpoints

Campaigns

MethodPathScopeDescription
POST/campaign/campaignscampaigns:manageCreate a campaign. Starts active.
GET/campaign/campaignscampaigns:readList campaigns. Cursor pagination.
GET/campaign/campaigns/{id}campaigns:readGet one campaign.
PATCH/campaign/campaigns/{id}campaigns:manageUpdate a campaign.
POST/campaign/campaigns/{id}/startcampaigns:manageStart or resume the campaign.
POST/campaign/campaigns/{id}/pausecampaigns:managePause a running campaign.
POST/campaign/campaigns/{id}/closecampaigns:manageClose the campaign permanently.

Contacts

MethodPathScopeDescription
POST/campaign/campaigns/{id}/contactscampaigns:manageUpsert up to 1000 contacts.
GET/campaign/campaigns/{id}/contactscampaigns:readList contacts with their attempts. Limit/offset pagination.
GET/campaign/campaigns/{id}/contacts/{contact_id}campaigns:readGet one contact.
DELETE/campaign/campaigns/{id}/contacts/{contact_id}campaigns:manageDelete a contact.

Stats

MethodPathScopeDescription
GET/campaign/campaigns/{id}/statscampaigns:readContact counts, attempt counts, and active-call count.

Configurations

MethodPathScopeDescription
POST/campaign/configurationscampaigns:manageCreate a configuration.
GET/campaign/configurationscampaigns:readList configurations.
GET/campaign/configurations/{config_id}campaigns:readGet one configuration.
PATCH/campaign/configurations/{config_id}campaigns:manageUpdate a configuration.
DELETE/campaign/configurations/{config_id}campaigns:manageDelete a configuration. Fails if a campaign references it.
GET/campaign/timezonesList valid IANA timezone identifiers.

Concurrency settings

MethodPathScopeDescription
GET/campaign/concurrency-settingsconcurrency:readGet the org concurrency limit and current active count.
PUT/campaign/concurrency-settingsconcurrency:manageSet the org concurrency limit.

Scopes

Read endpoints accept either campaigns:read or campaigns:manage. Mutating endpoints — create, update, start, pause, close, upsert, delete — require campaigns:manage. The concurrency endpoints have their own scopes: GET /campaign/concurrency-settings accepts campaigns:read, campaigns:manage, concurrency:read, or concurrency:manage; PUT accepts campaigns:manage or concurrency:manage. A 403 means the credential is valid but lacks the required scope. See Authentication for how scopes are granted.

Conventions

Resolving by external_id

Wherever a path takes a campaign {id} or a {contact_id}, you can pass either the resource’s UUID or the external_id you assigned on create. This applies to campaign, contact, start/pause/close, and stats routes — set external_id once and address the resource by your own key thereafter.
Pass default as the campaign {id} on the contacts routes to manage ad-hoc contacts that belong to no campaign. Contacts added under default must already carry valid E.164 phone numbers, since there is no configuration to supply a default country code.

Pagination

The two list endpoints paginate differently.
EndpointStyleParameters
GET /campaign/campaignsCursorcursor, limit
GET /campaign/campaigns/{id}/contactsOffsetlimit, offset
GET /campaign/campaigns also accepts name (substring filter) and status (repeatable) query parameters. GET .../contacts accepts a status filter. The contacts response echoes total, limit, and offset alongside the contacts array.

Limits

LimitValue
limit on either list endpointMax 200, default 50
Contacts per POST .../contacts requestMax 1000
Contacts inlined on POST / PATCH /campaign/campaignsMax 5000
Default concurrency limit (when unset)10

Stats response

GET /campaign/campaigns/{id}/stats returns contact counts by status, attempt totals, and live activity:
{
  "campaign_id": "…",
  "status": "active",
  "contacts": {
    "total": 0,
    "pending": 0,
    "in_progress": 0,
    "completed": 0,
    "exhausted": 0
  },
  "attempts": {
    "total": 0,
    "average_per_contact": 0.0
  },
  "active_calls": 0,
  "concurrency_limit": 10
}
The stats route resolves the campaign by UUID only.

Upsert response

POST /campaign/campaigns/{id}/contacts upserts: contacts are updated when their id or external_id matches an existing row, and inserted otherwise. It returns counts plus the resolved IDs:
{
  "inserted": 0,
  "updated": 0,
  "failed": [],
  "warnings": [],
  "contact_ids": []
}
Phone numbers are normalized to E.164 using the campaign configuration’s default_country_code (falling back to +1). Numbers that can’t be parsed return 422. You cannot add contacts to a campaign whose status is closed (400).

Example: bulk-add contacts

Upsert two contacts into a campaign addressed by its external_id. With an org API key (ak_) the organization is implicit; with a personal access token (pat_) add the X-Anyreach-Org header.
curl -X POST https://api.anyreach.ai/campaign/campaigns/spring-outreach/contacts \
  -H "Authorization: Bearer $ANYREACH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      {
        "external_id": "lead-1001",
        "phone_numbers": ["+14155550123"],
        "data": { "first_name": "Ada" }
      },
      {
        "external_id": "lead-1002",
        "phone_numbers": ["+14155550199"],
        "data": { "first_name": "Grace" }
      }
    ]
  }'

Campaigns

The product walkthrough for building and running outbound campaigns.

Authentication

Bearer credentials, the X-Anyreach-Org header, and scopes.