Company campaigns are workspace-wide automation flows stored as flows with accessLevel: COMPANY. Use them for outbound calling workflows: scheduling, interviews, interest checks, assessment reminders, and similar global campaigns—with IVR or AI call scripts, defined call times, and optional SMS.
Use these endpoints to create and update campaigns, inspect their public configuration, and add or remove leads (candidates on the campaign) using the same Bearer API key model as the rest of the Partner API.
Base path: /v1/partner/campaigns
Company sites (needed to create a campaign): /v1/partner/company-sites
Authentication: Authorization: Bearer YOUR_API_KEY (same as API keys)
Set purposeType and related fields to match the kind of campaign you are building (same concepts as creating a global / company campaign in the TapTalent app). Optional GET /campaigns query parameters let you filter by status or purposeType.
Concepts
| Term | Meaning |
|---|
| Campaign | A row in client_flow_details with accessLevel: COMPANY — what the product calls a global / company campaign. |
| Campaign id | Numeric id of the flow; use it as :campaignId in URLs. |
| Lead | A person on the campaign. The Partner API exposes leadId, which is the same talentId used in internal flow APIs (client_flow_talents / client_flow_candidates). |
| Sanitized responses | Responses intentionally omit raw internal blobs (full miscellaneous, recording URLs, transcripts, provider secrets). Only mapped fields in the sections below are returned. |
Typical integration flow
GET /v1/partner/company-sites → pick a companySiteId assigned to the API key user.
POST /v1/partner/campaigns → create a campaign with the appropriate purposeType and payload for that campaign.
POST /v1/partner/campaigns/:campaignId/leads → add one or many candidates.
GET /v1/partner/campaigns/:campaignId/leads → poll status labels until your automation is done.
List campaigns
GET /campaigns
Returns company-scoped campaigns (accessLevel: COMPANY) for the company tied to the API key. Results are ordered with newest campaign id first, then paginated.
Query parameters
| Parameter | Type | Description |
|---|
status | string | Exact match on campaign status (e.g. RUNNING). |
purposeType | string | Exact match on purposeType (e.g. ASSESSMENT_REMINDER, SCHEDULE). |
page | integer | Page number, default 1, minimum 1. |
limit | integer | Page size, default 20, maximum 100. |
Example: filter by purpose and paginate
curl -s -X GET \
"https://partner-api.taptalent.io/v1/partner/campaigns?purposeType=SCHEDULE&status=RUNNING&page=1&limit=20" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json"
Example response
{
"campaigns": [
{
"id": 101,
"title": "Assessment reminders — Q2",
"status": "RUNNING",
"purposeType": "ASSESSMENT_REMINDER",
"timezone": "America/New_York",
"companySiteId": 12,
"accessLevel": "COMPANY",
"createdAt": "2025-04-01T12:00:00.000Z",
"updatedAt": "2025-04-10T09:30:00.000Z",
"callSettings": { "callType": "IVR" },
"assessment": {
"assessmentTestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"assessmentName": "Technical screen",
"jobTitle": "Senior Engineer",
"autoAddInvitedCandidates": false,
"assessmentFirstReminderDelayHours": 24
}
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 1,
"totalPages": 1
}
}
Depending on purposeType, optional blocks such as assessment may appear in list items; callSettings and core fields are included when present in the mapped summary.
Get one campaign
GET /campaigns/:campaignId
Returns a sanitized detail object: high-level schedule, IVR/AI call settings (no secrets), opening/closing messages, and purpose-specific blocks when applicable (for example an assessment object for assessment-related campaigns). Does not return raw step miscellaneous, recording URLs, or full execution logs.
- 404 if the id is invalid, deleted, not in the API key’s company, or not a company (
COMPANY) campaign — this avoids leaking whether an id exists in another workspace.
Example request
curl -s -X GET \
"https://partner-api.taptalent.io/v1/partner/campaigns/101" \
-H "Authorization: Bearer YOUR_API_KEY"
Example response (truncated)
{
"campaign": {
"id": 101,
"title": "Assessment reminders — Q2",
"status": "RUNNING",
"purposeType": "ASSESSMENT_REMINDER",
"timezone": "America/New_York",
"companySiteId": 12,
"createdAt": "2025-04-01T12:00:00.000Z",
"updatedAt": "2025-04-10T09:30:00.000Z",
"callSettings": {
"callType": "IVR",
"aiCallScript": ""
},
"schedule": {
"callTimeDisplay": "Apr 15, 2025 10:00 AM",
"callSchedule": {
"timeBasis": "UTC",
"startTimeLocal": null,
"startTimeUtc": "2025-04-15T14:00:00.000Z"
},
"followUpRetries": [
{ "time": "2025-04-16T14:00:00.000Z", "delayDays": 1 }
]
},
"messages": {
"openingMessage": "Hi, this is a reminder from Acme about your assessment.",
"closingMessage": "Thank you. Goodbye."
},
"assessment": {
"assessmentTestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"assessmentName": "Technical screen",
"jobTitle": "Senior Engineer",
"autoAddInvitedCandidates": false,
"assessmentReminderSmsTemplate": "Reminder: complete your assessment.",
"assessmentPostCallSmsTemplate": "Thanks for taking the call.",
"assessmentFirstReminderDelayHours": 24
}
}
}
Create campaign
POST /campaigns
Creates a new company campaign. The request body is validated with strict keys (stripUnknown: true); extra properties are rejected.
Rules
purposeType identifies which campaign you are creating (for example scheduling, virtual interviews, interest checks, or assessment reminders). Payload requirements depend on the purpose—mirror the same fields you would use when creating that campaign type in the app (global / company campaign).
companySiteId must be a site linked to the API key user (use GET /company-sites first). The server applies the same checks as the in-app global campaign creator.
- Schedule: for campaign types that use bulk calling, supply enough data for a valid first-call schedule. Common patterns:
- UTC-based:
callStartTimeUtc (and optionally retryScheduleUtc) or
- Local display + retries:
callTime and/or followUpRetries (timezone-aware scheduling, same behavior as in the app).
Common body fields (always review validation responses for your chosen purposeType; required flags vary by type.)
| Field | Required | Description |
|---|
title | Yes | Campaign name (1–500 characters). |
timezone | Yes | IANA timezone string (e.g. America/Chicago). |
companySiteId | Yes | Integer or string; from GET /company-sites. |
phoneNumber | Yes | Outbound caller ID; must be a verified number on the company (same rules as product). |
openingMessage | Yes | IVR opening script (non-empty). |
closingMessage | Yes | IVR closing script (non-empty). |
purposeType | Yes | Campaign purpose (e.g. SCHEDULE, ONLINE_INTERVIEW, INTEREST_CHECK, ASSESSMENT_REMINDER). |
jobDetails | Varies | Object whose fields depend on purposeType (job copy, assessment ids, interview slots, meeting URLs, etc.—same as the in-app global campaign creator). |
callTime | Optional | Human-oriented call time string when using local schedule building. |
followUpRetries | Optional | Array of { "time": "<iso or display string>", "delayDays": 0 } objects. |
callStartTimeUtc | Optional | ISO UTC string for UTC-basis schedules. |
retryScheduleUtc | Optional | Optional array for UTC retry slots. |
callType | Optional | IVR or AICall (case-insensitive accepted). |
aiCallScript | Optional | Used when using AI call mode. |
questions | Optional | Optional IVR question list (array). |
status | Optional | Flow status if you need a non-default initial value. |
For campaign types that use bulk calling, include enough schedule data that a first execution time can be computed (typically callTime / followUpRetries and/or callStartTimeUtc / retryScheduleUtc, depending on how you configure the campaign—same rules as in the app). jobDetails is required when the chosen purposeType expects it.
Example jobDetails fields (assessment-oriented campaigns)
When purposeType is ASSESSMENT_REMINDER, jobDetails typically includes:
| Field | Required | Description |
|---|
assessmentTestId | Yes | Quiz / assessment test identifier (string or number). |
jobTitle | Yes | Role label shown in messaging. |
assessmentName | No | Friendly assessment name. |
assessmentReminderSmsTemplate | No | Max 300 characters. |
assessmentPostCallSmsTemplate | No | Max 300 characters. |
autoAddInvitedCandidates | No | Boolean. |
assessmentFirstReminderDelayHours | No | 0–168 (hours). |
You may also set assessmentTestId, SMS templates, autoAddInvitedCandidates, and assessmentFirstReminderDelayHours at the top level of the body (duplicates for convenience); jobDetails remains the canonical nested block for that shape.
Example: UTC-scheduled creation (ASSESSMENT_REMINDER)
curl -s -X POST "https://partner-api.taptalent.io/v1/partner/campaigns" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Q2 eng assessment reminders",
"timezone": "America/New_York",
"companySiteId": 12,
"phoneNumber": "+15551234567",
"purposeType": "ASSESSMENT_REMINDER",
"callType": "IVR",
"openingMessage": "Hi, this is Acme recruiting about your pending technical assessment.",
"closingMessage": "Thank you. You will receive a text with the link shortly. Goodbye.",
"callStartTimeUtc": "2025-06-01T15:00:00.000Z",
"jobDetails": {
"assessmentTestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"jobTitle": "Software Engineer",
"assessmentName": "Technical screen",
"assessmentFirstReminderDelayHours": 48,
"assessmentReminderSmsTemplate": "Reminder: your assessment link is ready.",
"autoAddInvitedCandidates": false
}
}'
Example: 201 response
{
"campaign": {
"id": 5501,
"title": "Q2 eng assessment reminders",
"status": "RUNNING",
"purposeType": "ASSESSMENT_REMINDER",
"timezone": "America/New_York",
"companySiteId": 12,
"callSettings": { "callType": "IVR", "aiCallScript": "" },
"schedule": {
"callTimeDisplay": "Jun 01, 2025 11:00 AM",
"callSchedule": {
"timeBasis": "UTC",
"startTimeUtc": "2025-06-01T15:00:00.000Z"
},
"followUpRetries": []
},
"messages": {
"openingMessage": "Hi, this is Acme recruiting about your pending technical assessment.",
"closingMessage": "Thank you. You will receive a text with the link shortly. Goodbye."
},
"assessment": {
"assessmentTestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"assessmentName": "Technical screen",
"jobTitle": "Software Engineer",
"autoAddInvitedCandidates": false,
"assessmentReminderSmsTemplate": "Reminder: your assessment link is ready.",
"assessmentPostCallSmsTemplate": "",
"assessmentFirstReminderDelayHours": 48
}
}
}
Update campaign
PATCH /campaigns/:campaignId
Updates editable fields for the campaign: title/name, job title, SMS templates, delay, verified phone number, call schedule (until first call starts), opening/closing messages, and call type / AI script—which fields apply depends on the campaign’s purpose and current state.
- The campaign must belong to the company and be a company campaign (404 otherwise).
Common body fields (all optional; only send what changes)
| Field | Description |
|---|
title / campaignName / header.title | Rename the campaign (aliases supported). |
jobName / jobTitle | Updates the job title on the flow where applicable. |
assessmentReminderSmsTemplate / assessmentPostCallSmsTemplate | Max 300 chars each. |
assessmentFirstReminderDelayHours | Non-negative number. |
phoneNumber | Must exist and be VERIFIED on the company. |
callTime / followUpRetries | Cannot change after the first outbound call attempt has started (server error). |
openingMessage / closingMessage | Also accepted as startMessage / endMessage. |
callType / aiCallScript | IVR vs AI call configuration. |
Example
curl -s -X PATCH "https://partner-api.taptalent.io/v1/partner/campaigns/5501" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Q2 eng reminders (updated)",
"assessmentReminderSmsTemplate": "Acme: finish your tech screen today.",
"openingMessage": "Hi, calling from Acme about your assessment."
}'
Example response
{
"status": "success",
"flowId": 5501,
"campaign": {
"id": 5501,
"title": "Q2 eng reminders (updated)",
"status": "RUNNING",
"purposeType": "ASSESSMENT_REMINDER",
"timezone": "America/New_York",
"companySiteId": 12,
"callSettings": { "callType": "IVR", "aiCallScript": "" },
"schedule": { "callTimeDisplay": "...", "callSchedule": null, "followUpRetries": [] },
"messages": {
"openingMessage": "Hi, calling from Acme about your assessment.",
"closingMessage": "Thank you. Goodbye."
},
"assessment": {
"assessmentTestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"jobTitle": "Software Engineer",
"assessmentReminderSmsTemplate": "Acme: finish your tech screen today.",
"assessmentPostCallSmsTemplate": "",
"assessmentFirstReminderDelayHours": 48
}
}
}
The campaign object is the full sanitized detail (same shape as Get one campaign), including createdAt / updatedAt when present.
Company sites
GET /company-sites
Returns sites the API key user may use when creating campaigns. Each entry includes companySiteId and optional site metadata (name, address, region).
Example response
{
"companySites": [
{
"companySiteId": 12,
"isPrimary": true,
"site": {
"id": 12,
"name": "HQ — New York",
"address": "1 Example Plaza",
"city": "New York",
"state": "NY",
"country": "US"
}
}
]
}
Leads
GET /campaigns/:campaignId/leads
Lists participants with sanitized fields (no raw transcripts, callSid, or execution payloads).
Query parameters
| Parameter | Description |
|---|
search | Case-insensitive substring match on first name, last name, or email. |
status | UI-oriented bucket: Interested, NotInterested, NoAnswer, Pending (maps internal execution statuses). |
page, limit | Same semantics as list campaigns (limit max 100). |
Example
curl -s -G "https://partner-api.taptalent.io/v1/partner/campaigns/5501/leads" \
--data-urlencode "search=ada" \
--data-urlencode "status=Pending" \
--data-urlencode "page=1" \
--data-urlencode "limit=50" \
-H "Authorization: Bearer YOUR_API_KEY"
Example row
{
"leads": [
{
"leadId": 987654,
"firstName": "Ada",
"lastName": "Lovelace",
"email": "ada@example.com",
"phone": "+15559876543",
"status": "Pending",
"flowStatus": "Pending",
"assessmentSubmitted": "Not submitted",
"addedAt": "2025-06-02T10:15:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 1,
"totalPages": 1
}
}
For campaigns that track assessment submission, assessmentSubmitted is Submitted or Not submitted; flowStatus may show Completed when the lead row completes even if the last dial outcome was pending/no-answer.
POST /campaigns/:campaignId/leads
Adds one or many leads in a single request. Only the simple candidate path is supported (no AI search or marketplace bulk import).
Body
| Field | Type | Description |
|---|
leads | array | Min length 1. Each item must include email. |
Each lead
| Field | Required | Description |
|---|
email | Yes | Valid email; primary dedupe key with internal rules. |
firstName, lastName | No | Empty string allowed. |
phoneNumber | No | E.164 or local format per company rules. |
linkedin | No | Profile URL or handle string. |
Idempotency: the API does not guarantee idempotent adds. Re-posting the same email may return skipped counts if the candidate is already on the flow or blocked by duplicate/contact rules. Treat added / skipped as best-effort telemetry and reconcile with GET .../leads if needed.
Example
curl -s -X POST "https://partner-api.taptalent.io/v1/partner/campaigns/5501/leads" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"leads": [
{
"email": "ada@example.com",
"firstName": "Ada",
"lastName": "Lovelace",
"phoneNumber": "+15559876543",
"linkedin": "https://www.linkedin.com/in/example"
},
{
"email": "grace@example.com",
"firstName": "Grace",
"lastName": "Hopper"
}
]
}'
Example response
{
"added": 2,
"skipped": 0
}
skipped increments when a row is not added because of duplicates, prior contact, or internal eligibility checks.
DELETE /campaigns/:campaignId/leads/:leadId
Removes a lead from the campaign. leadId is the leadId returned by the list endpoint (internal talentId).
curl -s -X DELETE \
"https://partner-api.taptalent.io/v1/partner/campaigns/5501/leads/987654" \
-H "Authorization: Bearer YOUR_API_KEY"
Example response
{
"status": "success",
"leadId": 987654
}
Errors
Partner routes normalize failures to JSON:
{
"error": {
"code": "INVALID_REQUEST",
"type": "validation_error",
"message": "One or more fields are invalid.",
"details": {
"jobDetails.jobTitle": "\"jobTitle\" is required"
}
}
}
| HTTP | code | When |
|---|
| 400 | INVALID_REQUEST | Invalid body fields; see message and per-field details. |
| 400 | PURPOSE_NOT_ALLOWED_FOR_PARTNER | The operation is not allowed for this campaign’s purpose or current configuration; see message. |
| 404 | NOT_FOUND | Campaign missing, wrong company, or not a company campaign. |
| 403 | FORBIDDEN | Client profile / company mismatch for the key (rare on create). |
Stack traces and SQL are never returned.
Operational notes
- Rate limiting: follows the same limits as other Partner API routes for your workspace.
- Voice (IVR): creating or updating IVR messages may trigger text-to-speech generation in the background, as in the product. Administrative or system-only operations are not exposed on the Partner API.