20 operations. Call each with POST https://app.chirply.io/api/v1/actions/<name> and a bearer token; the response is { "data": { "action", "summary", "result" } }. A read badge means the operation changes nothing; write requires the credential’s write scope.
Add a number to a pool
call_tracking.add_number_to_poolwriteconfirmadmin only
Add one of the organization's phone numbers to a DNI pool. It becomes a rotating tracking number: the DNI script hands it to a visitor, and a call to it is attributed to that visitor's source. THIS REPOINTS A LIVE BUSINESS PHONE LINE — the number's inbound routing switches to the campaign engine, so it stops reaching whoever answers it today, and it starts being shown to strangers on a public web page. If the number is already assigned elsewhere in call tracking, this silently moves it. Provision the number first with the telephony tools.
Marked confirm: this operation is irreversible, reaches real people, or spends money. Holding a credential is itself the confirmation for API and MCP callers — call it only when you mean it. The in-app assistant refuses to run it without a human approving first.
Over MCP the same operation is the tool call_tracking_add_number_to_pool at https://app.chirply.io/api/mcp, same bearer token, same input.
Archive a campaign
call_tracking.archive_campaignwriteconfirmadmin only
Archive a call-tracking campaign. Its tracking numbers stop routing to it (calls fall through to the team bridge) and it drops out of the active list. The call history is kept. Reversible by setting status back to active.
Marked confirm: this operation is irreversible, reaches real people, or spends money. Holding a credential is itself the confirmation for API and MCP callers — call it only when you mean it. The in-app assistant refuses to run it without a human approving first.
Over MCP the same operation is the tool call_tracking_archive_campaign at https://app.chirply.io/api/mcp, same bearer token, same input.
Make a number a tracking number
call_tracking.assign_numberwriteconfirmadmin only
Point one of the organization's existing phone numbers at a call-tracking campaign. THIS REPOINTS A LIVE BUSINESS PHONE LINE: it switches that number's inbound routing away from whatever answers it today (the team, an IVR, an AI receptionist) to the campaign engine, so the very next real caller is routed by the campaign's destination list instead. If the number is already assigned elsewhere in call tracking, this silently re-points it. Does not buy a number — provision one first with the telephony tools, then assign it here.
Marked confirm: this operation is irreversible, reaches real people, or spends money. Holding a credential is itself the confirmation for API and MCP callers — call it only when you mean it. The in-app assistant refuses to run it without a human approving first.
Parameters
Field
Type
Required
Description
phone_number_id
string (uuid)
required
The phone_numbers row to use as a tracking number.
campaign_id
string (uuid)
required
The campaign this number should route to.
label
string
optional
A name for this number in reports, e.g. 'Billboard I-35'.
Over MCP the same operation is the tool call_tracking_assign_number at https://app.chirply.io/api/mcp, same bearer token, same input.
Call-tracking stats
call_tracking.call_statsread
Headline numbers over a recent window: total tracked calls, how many were answered, how many converted, and the running revenue / payout / margin. Optionally scoped to one campaign. Read-only.
Over MCP the same operation is the tool call_tracking_call_stats at https://app.chirply.io/api/mcp, same bearer token, same input.
Create call-tracking campaign
call_tracking.create_campaignwriteadmin only
Create a call-tracking campaign. Set the ordered list of destinations calls should route to (`route_to`), how a call counts as a conversion, and any geo / repeat-caller filters. Creating a campaign costs nothing and places no calls; it starts in 'draft' unless you set a status. Point a tracking number at it with call_tracking.assign_number to go live.
Parameters
Field
Type
Required
Description
name
string
required
What to call this campaign, e.g. 'Roofing — Google Ads'.
status
"draft" | "active" | "paused" | "archived"
optional
'active' routes live calls; 'draft'/'paused' don't. Default: "draft"
route_to
object[]
optional
Ordered destinations to ring. The engine waterfalls through them: each is tried in turn when the previous doesn't answer.
route_to[].e164
string
required
Destination phone number to ring, in E.164 (e.g. +14045551234).
route_to[].label
string
optional
A name for this destination, shown in reports.
route_to[].timeout
integer
optional
Seconds to ring this destination before trying the next one (5–120).
overflow_e164
string
optional
Fallback number dialed when every destination fails. Blank = play a goodbye.
ring_timeout_seconds
integer
optional
Default seconds to ring each destination before moving on (5–120). Default: 20
conversion_type
"duration" | "webhook" | "manual"
optional
'duration' converts a call that stays connected past `conversion_seconds`; 'webhook' waits for a signed POST to /api/ct/conversion; 'manual' waits for someone to mark it. Default: "duration"
conversion_seconds
integer
optional
For duration conversions: connected seconds that count as a conversion. Default: 60
recording_enabled
boolean
optional
Record calls on this campaign (dual-channel, stored to the tenant's R2). Recording real callers without consent is regulated in many US states — pair it with recording_announce. Default: true
recording_announce
boolean
optional
Play 'this call may be recorded' to the caller before connecting. Default: false
geo_mode
"allow" | "block"
optional
'allow' = only listed areas; 'block' = all but listed.
geo_states
string[]
optional
US state codes for the geo filter, e.g. ['CA','TX'].
geo_area_codes
string[]
optional
Area codes for the geo filter.
geo_countries
string[]
optional
ISO country codes for the geo filter.
dedupe_window_seconds
integer
optional
Treat a repeat call from the same number within this window as a duplicate (0 = off). Default: 0
Over MCP the same operation is the tool call_tracking_create_campaign at https://app.chirply.io/api/mcp, same bearer token, same input.
Create a number pool
call_tracking.create_poolwriteadmin only
Create a DNI number pool for a campaign and mint its public embed key. Add tracking numbers to it with call_tracking.add_number_to_pool, then paste the returned snippet on the page. Creating a pool costs nothing; the numbers you add are real Twilio numbers the tenant already pays for.
Parameters
Field
Type
Required
Description
campaign_id
string (uuid)
required
The campaign calls to this pool's numbers belong to.
name
string
required
What to call this pool, e.g. 'Homepage — paid search'.
target_size
integer
optional
How many numbers the pool should hold (size to peak concurrent visitors). Too few and two visitors share a number, which mis-attributes their calls. Default: 10
sticky_ttl_seconds
integer
optional
How long a visitor keeps the same number (seconds). Default: 1800
allowed_origins
string[]
optional
Website addresses allowed to request a number. Empty = any origin.
Over MCP the same operation is the tool call_tracking_create_pool at https://app.chirply.io/api/mcp, same bearer token, same input.
Open a tracked call
call_tracking.get_callread
Fetch one tracked call by its ct_calls id, with full attribution, routing outcome, and conversion + money fields. The embedded `call` is the call-log row, whose `kind` says what handled the call once it arrived — `call_tracking`, or `ai_agent`/`queue` when an AI agent or a call queue took it.
Over MCP the same operation is the tool call_tracking_get_call at https://app.chirply.io/api/mcp, same bearer token, same input.
Open a call-tracking campaign
call_tracking.get_campaignread
Fetch one call-tracking campaign by id, with its full routing list, geo filter, conversion rule, and the signing secret for its external conversion webhook.
Over MCP the same operation is the tool call_tracking_get_campaign at https://app.chirply.io/api/mcp, same bearer token, same input.
Copy DNI snippet
call_tracking.get_dni_snippetread
Return the one-line <script> tag that enables dynamic number insertion for a pool. Paste it on the page whose phone numbers should swap per visitor; mark the numbers with data-ct-number.
Over MCP the same operation is the tool call_tracking_get_pool at https://app.chirply.io/api/mcp, same bearer token, same input.
List tracked calls
call_tracking.list_callsread
List calls that came through tracking numbers, newest first, with their attribution (campaign, source/UTM/keyword, caller state) and outcome (answered, duration, conversion). The embedded `call` is the call-log row, whose `kind` says what handled the call once it arrived — `call_tracking` for a straight tracked call, or `ai_agent`/`queue` when an AI agent or a call queue took it. Filter by campaign, conversion status, or a date window.
Over MCP the same operation is the tool call_tracking_list_calls at https://app.chirply.io/api/mcp, same bearer token, same input.
List call-tracking campaigns
call_tracking.list_campaignsread
List this organization's call-tracking campaigns, newest first. A campaign ties tracking numbers to a routing plan and a conversion rule. Returns each campaign's status, conversion rule, and routing settings — not its call log.
Over MCP the same operation is the tool call_tracking_list_numbers at https://app.chirply.io/api/mcp, same bearer token, same input.
List number pools
call_tracking.list_poolsread
List DNI number pools, optionally for one campaign. A pool rotates a set of tracking numbers so each web visitor sees a unique number keyed to their source.
Over MCP the same operation is the tool call_tracking_list_pools at https://app.chirply.io/api/mcp, same bearer token, same input.
Mark a call converted
call_tracking.mark_conversionwriteconfirmadmin only
Manually mark a tracked call as converted (or rejected). Records a conversion audit entry and — once the pay-per-call money layer is live — is what bills the buyer and credits the publisher for that call. Use for campaigns whose conversion is decided by a human, or to correct an automatic decision.
Marked confirm: this operation is irreversible, reaches real people, or spends money. Holding a credential is itself the confirmation for API and MCP callers — call it only when you mean it. The in-app assistant refuses to run it without a human approving first.
Parameters
Field
Type
Required
Description
ct_call_id
string (uuid)
required
The tracked call to mark (ct_calls.id).
converted
boolean
optional
true = converted; false = rejected. Default: true
value_cents
integer
optional
Optional conversion value in cents (for value-based revenue).
Over MCP the same operation is the tool call_tracking_pause_campaign at https://app.chirply.io/api/mcp, same bearer token, same input.
Stop tracking on a number
call_tracking.release_numberwriteconfirmadmin only
Detach a tracking number from its campaign or pool and return it to normal team routing. THIS REPOINTS A LIVE BUSINESS PHONE LINE — the next real caller reaches the team instead of the campaign's destinations — and if the number is in a DNI pool, every web visitor currently holding it loses their attribution. The number is not released from Twilio; it just stops being a tracking number. Past calls ARE kept in full: ct_calls rows reference the campaign and the phone number, not this assignment, so reports and recordings survive. What does NOT survive is the tracking-number record itself — its report label ('Billboard I-35') and its publisher attribution are hard-deleted with no undo, and re-assigning the number creates a fresh one.
Marked confirm: this operation is irreversible, reaches real people, or spends money. Holding a credential is itself the confirmation for API and MCP callers — call it only when you mean it. The in-app assistant refuses to run it without a human approving first.
Over MCP the same operation is the tool call_tracking_release_number at https://app.chirply.io/api/mcp, same bearer token, same input.
Edit call-tracking campaign
call_tracking.update_campaignwriteconfirmadmin only
Edit a call-tracking campaign — its routing list, conversion rule, filters, recording, or status. Omitted fields are left alone, INCLUDING the four geo fields: sending only geo_states leaves the stored area codes, countries and mode as they were. Passing `route_to` REPLACES the whole destination list, and this campaign may be answering live calls right now: repointing it sends every subsequent caller somewhere else, and setting status to 'paused' stops the campaign's tracking numbers connecting anyone at all.
Marked confirm: this operation is irreversible, reaches real people, or spends money. Holding a credential is itself the confirmation for API and MCP callers — call it only when you mean it. The in-app assistant refuses to run it without a human approving first.
Parameters
Field
Type
Required
Description
id
string (uuid)
required
The campaign to edit.
name
string
optional
New name.
status
"draft" | "active" | "paused" | "archived"
optional
'active' routes live calls; 'paused' doesn't.
route_to
object[]
optional
Replacement ordered destination list (replaces the whole list).
route_to[].e164
string
required
Destination phone number to ring, in E.164 (e.g. +14045551234).
route_to[].label
string
optional
A name for this destination, shown in reports.
route_to[].timeout
integer
optional
Seconds to ring this destination before trying the next one (5–120).
overflow_e164
string
optional
Fallback number when every destination fails.
ring_timeout_seconds
integer
optional
Default seconds to ring each destination before moving on (5–120).
conversion_type
"duration" | "webhook" | "manual"
optional
'duration' converts a call that stays connected past `conversion_seconds`; 'webhook' waits for a signed POST to /api/ct/conversion; 'manual' waits for someone to mark it.
conversion_seconds
integer
optional
For duration conversions: connected seconds that count as a conversion.
recording_enabled
boolean
optional
Record calls on this campaign (dual-channel, stored to the tenant's R2). Recording real callers without consent is regulated in many US states — pair it with recording_announce.
recording_announce
boolean
optional
Play 'this call may be recorded' to the caller before connecting.
routing_strategy
"priority" | "round_robin" | "weighted"
optional
How destinations in the same tier are chosen (used with the Layer 3 ring plan).
require_call_confirmation
boolean
optional
Require a destination to press 1 to accept a call (anti-voicemail).
geo_mode
"allow" | "block"
optional
'allow' = only listed areas; 'block' = all but listed. Omit to keep the campaign's current mode.
geo_states
string[]
optional
Replacement list of US state codes, e.g. ['CA','TX']. Omit to leave the stored states alone; send [] to clear them.
geo_area_codes
string[]
optional
Replacement list of area codes. Omit to leave the stored ones alone; send [] to clear them.
geo_countries
string[]
optional
Replacement list of ISO country codes. Omit to leave the stored ones alone; send [] to clear them.
dedupe_window_seconds
integer
optional
Treat a repeat call from the same number within this window as a duplicate (0 = off).
Over MCP the same operation is the tool call_tracking_update_campaign at https://app.chirply.io/api/mcp, same bearer token, same input.
Edit a number pool
call_tracking.update_poolwriteadmin only
Edit a DNI number pool — its name, status, target size, stickiness, or allowed origins. Omitted fields are left alone. This pool is feeding a live public web page: setting status to 'paused' stops handing out numbers, so visitors fall back to whatever static number the page shows and their calls stop being attributed.
Parameters
Field
Type
Required
Description
id
string (uuid)
required
The pool to edit.
name
string
optional
What to call this pool, e.g. 'Homepage — paid search'.
status
"active" | "paused"
optional
'paused' stops handing out numbers.
target_size
integer
optional
How many numbers the pool should hold (size to peak concurrent visitors). Too few and two visitors share a number, which mis-attributes their calls.
sticky_ttl_seconds
integer
optional
How long a visitor keeps the same number (seconds).
allowed_origins
string[]
optional
Replacement allow-list of website addresses (replaces the whole list).