Campaigns API

These endpoints let you create and manage outbound calling campaigns, upload contacts, and track progress. For a step-by-step walkthrough, see the Outbound Campaigns guide.

All requests require an Authorization: Bearer YOUR_GUAVA_API_KEY header. See the API Overview for details.

Campaigns are addressed by their campaign code — a gcmp- prefixed identifier (e.g. gcmp-a1b2c3d4) returned when you create a campaign. Use it wherever an endpoint takes a {campaign_code}.

Every endpoint below is served under /v2 and is addressed by campaign code. The older /v1 paths — which addressed campaigns by their internal database id — still respond for backwards compatibility but are deprecated; switch to /v2.

Create a campaign

POST /v2/campaigns

Create a new outbound campaign. Campaign names must be unique within your organization.

Parameters

NameTypeRequiredDescription
namestringYesHuman-readable campaign name, unique within your organization. Max 200 characters.
origin_phone_numbersarrayYesPhone numbers to place calls from, E.164 format (e.g. +15551234567). Must be numbers your account owns.
start_datestringYesDate the campaign may begin dialing (YYYY-MM-DD).
calling_windowsarrayYesTime windows during which calls may be placed. See Calling windows.
max_attemptsintegerNoMaximum call attempts per contact. Defaults to 1.
max_concurrencyintegerNoMaximum simultaneous calls. Defaults to 1. Cannot exceed your organization-wide limit.
timezonestringNoIANA timezone used to interpret calling windows. Defaults to "America/Los_Angeles".
end_datestringNoDate after which no new calls are placed (YYYY-MM-DD).
descriptionstringNoFree-form description of the campaign.
Calling windows

Each entry in calling_windows is an object:

NameTypeRequiredDescription
daystring or integerYesDay of week — a name ("monday""sunday") or an integer (0 = Monday … 6 = Sunday).
start_timestringYesWindow start, 24-hour HH:MM (also accepts 9am, 9:00AM, etc.).
end_timestringYesWindow end, HH:MM.

The recommended calling window is 8:00AM–9:00PM. Windows outside that range are accepted but the response includes a warning.

Response

201 Created with the campaign object:

FieldTypeDescription
idstringInternal identifier. Prefer campaign_code for all requests.
campaign_codestringPublic gcmp- identifier used to address this campaign.
namestringCampaign name
origin_phone_numbersarrayNormalized E.164 origin numbers
start_datestringYYYY-MM-DD
end_datestring (nullable)YYYY-MM-DD, if set
calling_windowsarrayThe campaign's calling windows
max_attemptsintegerMaximum attempts per contact
max_concurrencyintegerMaximum simultaneous calls
timezonestringIANA timezone
descriptionstring (nullable)Campaign description, if set
created_datetimestringISO 8601 creation time
warningstringPresent only if a calling window falls outside the recommended range

Errors

StatusDescription
401Invalid authentication
403Outbound dialing not enabled for your organization, or an origin number is not owned by your account
400Invalid origin phone number, or max_concurrency exceeds your organization limit
409A campaign with this name already exists
422A required field (origin_phone_numbers, start_date, calling_windows) is missing

Example

curl -X POST https://api.goguava.ai/v2/campaigns \
  -H 'Authorization: Bearer YOUR_GUAVA_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Spring outreach",
    "origin_phone_numbers": ["+15551234567"],
    "start_date": "2026-06-01",
    "calling_windows": [
      {"day": "monday", "start_time": "09:00", "end_time": "17:00"}
    ],
    "max_attempts": 3,
    "max_concurrency": 2
  }'

Sample response:

{
  "id": "6064ab9663dc4eb0f1a2b3c4",
  "campaign_code": "gcmp-a1b2c3d4",
  "name": "Spring outreach",
  "origin_phone_numbers": ["+15551234567"],
  "start_date": "2026-06-01",
  "end_date": null,
  "calling_windows": [
    {"day": 0, "start_time": "09:00", "end_time": "17:00"}
  ],
  "max_attempts": 3,
  "max_concurrency": 2,
  "timezone": "America/Los_Angeles",
  "description": null,
  "created_datetime": "2026-05-20T18:04:00+00:00"
}

List campaigns

GET /v2/campaigns

List your organization's active (non-deleted) campaigns.

Response

A JSON array of campaign objects, each in the same shape returned by Get a campaign.

Errors

StatusDescription
401Invalid authentication
403Outbound dialing not enabled for your organization

Example

curl -H 'Authorization: Bearer YOUR_GUAVA_API_KEY' \
  https://api.goguava.ai/v2/campaigns

Get a campaign

GET /v2/campaigns/{campaign_code}

Retrieve a single campaign by its campaign code.

Parameters

NameTypeRequiredDescription
campaign_codestringYesThe gcmp- code of the campaign

Response

The campaign object, in the same shape returned by Create a campaign.

Errors

StatusDescription
401Invalid authentication
403Outbound dialing not enabled for your organization
404No campaign with this code exists

Example

curl -H 'Authorization: Bearer YOUR_GUAVA_API_KEY' \
  https://api.goguava.ai/v2/campaigns/gcmp-a1b2c3d4

Update a campaign

PATCH /v2/campaigns/{campaign_code}

Update one or more fields of an existing campaign. Only the fields you include are changed. Changing schedule-affecting fields (calling_windows, timezone, start_date, end_date) or origin_phone_numbers reschedules the campaign's pending contacts.

Parameters

NameTypeRequiredDescription
campaign_codestringYesThe gcmp- code of the campaign
enabledbooleanNoPause (false) or resume (true) the campaign
namestringNoNew campaign name
origin_phone_numbersarrayNoReplacement origin numbers (E.164, must be owned by your account)
start_datestringNoYYYY-MM-DD
end_datestringNoYYYY-MM-DD
calling_windowsarrayNoReplacement calling windows. See Calling windows.
max_attemptsintegerNoMaximum attempts per contact
max_concurrencyintegerNoMaximum simultaneous calls (cannot exceed your organization limit)
timezonestringNoIANA timezone
descriptionstringNoCampaign description

Response

The updated campaign object. Includes a warning field if a supplied calling window is outside the recommended range.

Errors

StatusDescription
401Invalid authentication
403Outbound dialing not enabled, or an origin number is not owned by your account
400No fields supplied, invalid origin phone number, or max_concurrency exceeds your organization limit
404No campaign with this code exists

Example

curl -X PATCH https://api.goguava.ai/v2/campaigns/gcmp-a1b2c3d4 \
  -H 'Authorization: Bearer YOUR_GUAVA_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"enabled": false}'

Delete a campaign

DELETE /v2/campaigns/{campaign_code}

Soft-delete a campaign. Deleted campaigns no longer place calls and stop appearing in List campaigns.

Parameters

NameTypeRequiredDescription
campaign_codestringYesThe gcmp- code of the campaign

Response

{ "ok": true }

Errors

StatusDescription
401Invalid authentication
403Outbound dialing not enabled for your organization
404No campaign with this code exists

Example

curl -X DELETE https://api.goguava.ai/v2/campaigns/gcmp-a1b2c3d4 \
  -H 'Authorization: Bearer YOUR_GUAVA_API_KEY'

Get campaign status

GET /v2/campaigns/{campaign_code}/status

Retrieve a breakdown of contact statuses for a campaign — how many contacts are still being tried, completed, failed, etc.

Parameters

NameTypeRequiredDescription
campaign_codestringYesThe gcmp- code of the campaign

Response

FieldTypeDescription
campaignstringThe campaign's name
status_countsobjectMap of contact status → count. Statuses: TRYING, COMPLETED, PARTIALLY_COMPLETED, FAILED.

Errors

StatusDescription
401Invalid authentication
403Outbound dialing not enabled for your organization
404No campaign with this code exists

Example

curl -H 'Authorization: Bearer YOUR_GUAVA_API_KEY' \
  https://api.goguava.ai/v2/campaigns/gcmp-a1b2c3d4/status

Sample response:

{
  "campaign": "Spring outreach",
  "status_counts": {
    "TRYING": 120,
    "COMPLETED": 55,
    "PARTIALLY_COMPLETED": 3,
    "FAILED": 22
  }
}

Check for callable contacts

GET /v2/campaigns/{campaign_code}/has-callable-contacts

Report whether the campaign currently has any contacts eligible to be called. Useful for deciding whether to keep a worker running.

Parameters

NameTypeRequiredDescription
campaign_codestringYesThe gcmp- code of the campaign

Response

FieldTypeDescription
has_callable_contactsbooleantrue if at least one contact is eligible to be called

Errors

StatusDescription
401Invalid authentication
403Outbound dialing not enabled for your organization
404No campaign with this code exists

Example

curl -H 'Authorization: Bearer YOUR_GUAVA_API_KEY' \
  https://api.goguava.ai/v2/campaigns/gcmp-a1b2c3d4/has-callable-contacts

Upload contacts

POST /v2/campaigns/{campaign_code}/contacts

Add contacts to a campaign. Phone numbers are validated and normalized to E.164, checked against your organization's Do Not Call list, and de-duplicated within the campaign. Up to 10,000 contacts may be uploaded per request. If any contact is rejected, the entire request is rejected.

Parameters

NameTypeRequiredDescription
campaign_codestringYesThe gcmp- code of the campaign (path)
accepted_terms_of_servicebooleanYesMust be true. Pass as a query parameter.
allow_duplicatesbooleanNoIf true, skip the in-campaign duplicate check. Query parameter, defaults to false.
contactsarrayYesThe contacts to add (request body). See below.

Each contact object:

NameTypeRequiredDescription
phone_numberstringYesContact's phone number (E.164 preferred).
dataobjectNoArbitrary key/value data merged into the agent's context for this contact. Max 16 KB serialized.
outreach_modalitiesarrayNoAgentic-tenacity modalities to use for this contact, e.g. ["sms"].

Response

200 OK on success:

FieldTypeDescription
createdintegerNumber of contacts added

If any contact is rejected, 400 is returned and no contacts are created:

FieldTypeDescription
createdintegerAlways 0
rejectedintegerNumber of rejected contacts
rejected_entriesarrayPer-contact { phone_number, reason } objects

Errors

StatusDescription
401Invalid authentication
403Outbound dialing not enabled for your organization
400accepted_terms_of_service not passed, or one or more contacts were rejected
404No campaign with this code exists

Example

curl -X POST 'https://api.goguava.ai/v2/campaigns/gcmp-a1b2c3d4/contacts?accepted_terms_of_service=true' \
  -H 'Authorization: Bearer YOUR_GUAVA_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "contacts": [
      {"phone_number": "+15551230001", "data": {"first_name": "Alex"}},
      {"phone_number": "+15551230002"}
    ]
  }'

Sample response:

{ "created": 2 }

List contacts

GET /v2/contacts

List contacts across your campaigns, newest first. Filter by campaign, status, contact data, or attempt time.

Parameters

NameTypeRequiredDescription
campaign_codestringNoOnly return contacts in this campaign (gcmp- code).
statusstringNoOnly return contacts with this status. Repeat the parameter to match several. One of TRYING, COMPLETED, PARTIALLY_COMPLETED, FAILED.
datastringNoJSON object of exact-match filters on contact data, e.g. {"first_name":"Alex"}.
attempted_afterstringNoOnly contacts last attempted at or after this time (ISO 8601).
attempted_beforestringNoOnly contacts last attempted at or before this time (ISO 8601).
limitintegerNoMaximum contacts to return, 1–1000. Defaults to 100.
afterstringNoPagination cursor. Pass the next_cursor from the previous response.

Response

FieldTypeDescription
contactsarrayThe matching contacts
next_cursorstring (nullable)Pass as after to fetch the next page. null when there are no more results.
has_morebooleantrue if more contacts match than were returned

Errors

StatusDescription
400Invalid limit, after cursor, status, data, or date value
401Invalid authentication
403Outbound dialing not enabled for your organization
404No campaign with the supplied code exists

Example

curl -G https://api.goguava.ai/v2/contacts \
  -H 'Authorization: Bearer YOUR_GUAVA_API_KEY' \
  --data-urlencode 'campaign_code=gcmp-a1b2c3d4' \
  --data-urlencode 'status=TRYING'

The deprecated /v1/contacts endpoint takes a campaign_id query parameter — your campaign's internal database id — in place of campaign_code. It still works for backwards compatibility, but new integrations should use /v2/contacts with campaign_code.

Questions? hi@goguava.ai