Skip to main content

Developer documentation · REST & MCP

API & MCP documentation

Build with Campaign Commander. One organization credential drives a versioned HTTP API and a stateless Model Context Protocol server. Any HTTP client or compatible MCP host can use it: no particular model, vendor SDK or agent platform is required.

Give this link to your agent

Give your agent this documentation link. If its host can make HTTP requests and supports adding an MCP connection with OAuth, it can read the machine bootstrap at /llms.txt and start connecting. Use OAuth for the supported self service MCP flow; you do not need to manually mint an API key. You sign in, choose your organization, and approve the requested scopes. This page is documentation, not an active connection, and reading it does not authenticate anything by itself.

Documentation linkhttps://www.campaigncommanderapp.com/docs/api
MCP server URLhttps://www.campaigncommanderapp.com/api/mcp

These are ordinary same-host links: resolve them against the host you actually retrieved this page from. The canonical production MCP address is https://www.campaigncommanderapp.com/api/mcp, a label for the reference, not an override of a noncanonical connection.

An agent host without connection or HTTP capabilities cannot gain them from a documentation link. It must report that limitation rather than claim to connect or execute tools. Some hosts require their own connection UI. No particular model, screenshot, private setup instructions or vendor configuration is required by this protocol.

Connect through a host that supports remote MCP and OAuth 2.1. Sign in, choose your organization, and approve the requested scopes. After initialization and tool discovery, call get_capabilities to confirm your organization, granted scopes, and setup state. Configure the host connection once; tool access depends on your current role and granted scopes.

154REST operations
134MCP tools
18workflows

Build with Campaign Commander

Campaign Commander exposes the same operations your team uses through a versioned Agent API (REST) and a Model Context Protocol server. A script, a service or an MCP host can run a supported job end to end. The credential is organization-bound: tool and route arguments never carry an organization id, because isolation comes from the key itself.

What this page is

Reference documentation. Examples are read-only or clearly marked illustrative, and nothing on this page executes a request, holds a key or opens a live connection.

Both surfaces call the same handlers. 134 MCP tools cover 154 REST operations, derived from the live definitions rather than hand-counted. See coverage & status for available agent operations and dashboard workflows.

The five-step shape of an agent job

  1. Connect and authorize: use the supported MCP OAuth flow, or an existing API key stored in a masked secret store, then confirm the granted capabilities.
  2. Discover: read scopes and pick the tools or routes for the job.
  3. Prepare: resolve the audience and preflight cost and blockers.
  4. Execute: do the write or send. Tools that declare a confirmation gate require an explicit confirm before they run.
  5. Verify: read the real result back: status, recipients, events, outcomes.

See workflow recipes for each job written out.

Quickstart

Connect the supported way first: the MCP OAuth flow. The user signs in, chooses the organization the credential is bound to, and approves the requested scopes on a consent screen. This server publishes protected-resource metadata at the MCP origin, supports dynamic client registration, and requires the authorization-code grant with PKCE S256 as a public client (token_endpoint_auth_method=none), so no manually supplied client secret is needed. A raw OAuth access token is an MCP credential and does not authenticate the direct REST API.

OpenAI setup

Choose the setup path for your OpenAI client. Campaign Commander also works with other compatible MCP hosts.

ChatGPT Workspace Agents

Have the agent owner add the connection in a workspace with Workspace Agents and the required apps enabled.

  1. Open Agents in the left sidebar, select your agent, and choose Edit agent to open the builder.
  2. In Tools, select + Add tool and add a custom MCP connection.
  3. Name the connection Campaign Commander and enter the MCP server URL: https://www.campaigncommanderapp.com/api/mcp. If the connection form asks for an authentication method, choose OAuth. Campaign Commander supports public-client registration and PKCE S256; no manually supplied client secret or API key is needed for this flow.
  4. Choose End-user account so each person running the agent connects with their own Campaign Commander account. Complete the Campaign Commander sign-in prompt, choose your organization, and approve the requested scopes.
  5. For an existing live agent, select Update to save your changes. Open Preview and ask: "Call get_capabilities and summarize my organization, granted scopes, and setup state." The host handles MCP initialization and tool discovery as part of the connection.

Tool access follows your Campaign Commander role and granted scopes. End-user account uses each person's own connection; Agent-owned account uses a shared connection. Use End-user account for this setup.

Regular ChatGPT chats

To use Campaign Commander as an app in regular ChatGPT chats, follow this separate setup path on ChatGPT web with developer mode access authorized for your workspace and account.

  1. Enable Developer mode in Settings → Apps → Advanced Settings when available to your authorized account. Workspace admins and owners can also begin from Workspace settings → Apps → Create.
  2. In Settings → Apps → Create, name the app Campaign Commander, enter https://www.campaigncommanderapp.com/api/mcp as the MCP server URL, and choose OAuth.
  3. Select Scan Tools. Complete Campaign Commander sign-in, choose your organization, approve the requested scopes, and wait for the tool scan to finish. Select Create.
  4. Open a chat, select the app from the tools menu, and ask it to call get_capabilities to summarize your organization, granted scopes, and setup state.

Your ChatGPT plan and workspace permissions determine which app actions are available.

Workspace Agents setup guide

ChatGPT MCP app setup guide

Connect Claude

Add Campaign Commander as a remote MCP custom connector in Claude.

  1. Open Customize → Connectors. Select + Add, then Add custom connector.
  2. Name the connector Campaign Commander and enter this remote MCP server URL: https://www.campaigncommanderapp.com/api/mcp. Select Continue, review the detected OAuth authentication settings, then select Continue.
  3. Under Authentication, choose Sign in now. Under OAuth client, choose Register automatically. Campaign Commander uses public-client registration with PKCE S256. You do not need to supply a client ID, client secret, or Request headers API key for this OAuth setup.
  4. Select Add, then connect the connector and complete browser sign-in with your own Campaign Commander account. Choose your organization and approve the requested scopes.
  5. In your conversation, open + → Connectors and enable Campaign Commander. Ask: "Call get_capabilities and summarize my organization, granted scopes, and setup state."

Tool access follows your Campaign Commander role and granted scopes.

Team and Enterprise workspaces

Have a workspace owner add the connector from Organization settings → Connectors → Add → Custom → Web, using Campaign Commander, the same MCP server URL, Sign in now, and Register automatically. Each member then opens Customize → Connectors, selects the connector, and chooses Connect to sign in with their own Campaign Commander account. Enable the connector for the conversation and run the capability check above.

Claude custom connector guide

Connect Grok Bot

Add Campaign Commander as a custom remote MCP server through Grok Bot chat.

  1. Open a conversation with your bot and send: "Add a custom MCP server called Campaign Commander at https://www.campaigncommanderapp.com/api/mcp. Use OAuth sign-in."
  2. Confirm the server name and URL, then complete the connection's browser sign-in with your own Campaign Commander account. Choose your organization and approve the requested scopes.
  3. In the next message, type @ and attach Campaign Commander to the task. Ask: "Call get_capabilities and summarize my organization, granted scopes, and setup state."

Campaign Commander uses a public HTTPS Streamable HTTP endpoint. Use browser sign-in for authorization; do not paste passwords, API keys, or OAuth tokens into chat.

Tool access follows your Campaign Commander role and granted scopes. Your team's connector policy also applies. If your organization uses an MCP allowlist, ask an administrator to permit the Campaign Commander server URL.

Grok Bot custom connector setup

Grok Bot connected apps guide

Grok Bot team connector policy

The examples below are alternate API-key examples for a host that already holds an organization key. They are not a prerequisite for the OAuth flow. Each reads scopes and prices and sends nothing or charges nothing. The discovery call can record a routine audit row (see readback); it changes no business or ledger state. The key comes from an environment variable (CC_API_KEY), never from source.

Read your granted scopes and the current customer prices over HTTP. The credential is the only authorization; session cookies are not accepted on the versioned API.

cURLread-only
# Read-only: reads the key's granted scopes. Sends nothing.
# Populate CC_API_KEY from your secret manager; never type a key into a shell.
: "${CC_API_KEY:?export CC_API_KEY from your secret manager first}"

curl -fSs https://www.campaigncommanderapp.com/api/v1/agent/capabilities \
  -H "Authorization: Bearer $CC_API_KEY"

The key's response lists the scopes that credential holds plus current calling prices. A missing scope is recovered differently by credential, and never by a silent widening: see scopes & permissions. Existing grants are frozen; an older key keeps only the scopes it originally had.

Authentication & keys

Direct work on the REST API is API-key only. An owner or admin creates a named key in Account → Settings → Agent API keys; the secret is shown once. Send it as Authorization: Bearer $CC_API_KEY.

A raw OAuth access token does not authenticate the direct REST API: OAuth 2.1 is the supported self-service credential for MCP hosts, not merely a workaround for hosts that cannot send a custom header. The MCP server publishes protected-resource metadata at the MCP origin, supports dynamic client registration, and requires the authorization-code grant with PKCE S256 as a public client (token_endpoint_auth_method=none), so no manually supplied client secret is needed. An OAuth token reaches the versioned handlers only through trusted in-process delegation during an MCP call, which is not the same as sending an OAuth token to /api/v1 yourself.

  • A missing or invalid key returns 401.
  • A valid key without the required scope returns 403, and the action does not run.
  • A key reaches only the organization that owns it, and only the channels that organization has set up.

Credential hygiene

Store the key in your secret manager or the client's masked prompt. Never paste it into agent chat, source control, a public URL or an example command you share.

Setup & readiness

A key only reaches channels the organization has finished setting up. The API reflects current readiness instead of guessing from stale state.

  • Email: the From domain must be verified before a send is accepted.
  • Text & picture messages: start at get_sms_readiness; it reports readiness and blockers in plain language.
  • Transactional email: one-to-one system mail, with a new-organization daily cap and per-minute rate until an administrator raises them.
  • Voice: one-to-one calls and the dialer bridge connect only to the key owner's already verified operator phone. An agent cannot supply an arbitrary bridge destination.
  • Balance: paid actions check the organization balance and place holds the same way the product does.

Workflows and tools disclose their own preconditions. Nothing here asserts that a live deployment is production-ready.

Client setup (optional)

The HTTP API and the MCP endpoint work from any compatible client. The configurations below are optional, source-checked starting points for specific hosts. They are not a claim of tested live compatibility, and no client is required to use Campaign Commander.

Generic MCP host

  • Add an HTTP (Streamable HTTP) MCP server with URL https://www.campaigncommanderapp.com/api/mcp.
  • Use OAuth 2.1 for the supported self-service MCP flow, or configure an existing organization API key in the host's masked secret settings as an alternate bearer credential.
  • Set Accept: application/json, text/event-stream. Use POST only; GET and DELETE return 405.
  • Call get_capabilities first to confirm scopes. Hosts without resource or prompt support can read the public HTTP documents instead.

Claude Code

HTTP MCP server with environment-variable interpolation in the Authorization header.

  • Merge the block into the project's .mcp.json without replacing other servers.
  • Set the environment variable through your own secret manager before starting the client.
claude.mcp.json
{
  "mcpServers": {
    "campaign-commander": {
      "type": "http",
      "url": "https://www.campaigncommanderapp.com/api/mcp",
      "headers": { "Authorization": "Bearer ${CC_API_KEY}" }
    }
  }
}

The literal ${CC_API_KEY} is expanded from your environment by the client; never commit a real value.

Codex CLI (and local clients sharing its config)

Registers an HTTP MCP server whose bearer token is read from an environment variable NAME.

  • bearer_token_env_var takes the variable NAME (CC_API_KEY), not its value.
  • Successful registration is not a successful authenticated tool call. call get_capabilities to confirm.
codex.config.toml
[mcp_servers.campaign-commander]
url = "https://www.campaigncommanderapp.com/api/mcp"
bearer_token_env_var = "CC_API_KEY"

A local client config does not configure a hosted web product; supported clients and workspace settings differ.

Visual Studio Code

Uses a top-level servers block and a masked input prompt for the bearer credential.

  • VS Code uses top-level servers, not a mcpServers block.
  • The masked prompt keeps the credential out of the file itself.
.vscode/mcp.json
{
  "inputs": [
    { "id": "cc-key", "type": "promptString", "description": "Campaign Commander API key", "password": true }
  ],
  "servers": {
    "campaign-commander": {
      "type": "http",
      "url": "https://www.campaigncommanderapp.com/api/mcp",
      "headers": { "Authorization": "Bearer ${input:cc-key}" }
    }
  }
}

Servers that require interactive input variables are not forwarded into every host surface; for those, use a documented noninteractive or OAuth setup instead.

API overview

The Agent API is JSON over HTTPS under /api/v1. Every response is scoped to the key's organization.

Base URLhttps://www.campaigncommanderapp.com/api/v1
AuthAuthorization: Bearer $CC_API_KEY
IdempotencyAn operation that can charge or send declares an Idempotency-Key header in its own schema. Send it, and reuse the same value when retrying the same attempt. The accepted length and character set differ per route.
ErrorsA missing scope is refused and the action does not run; an unknown provider outcome is neither retried blindly nor billed as success.

GET /agent/capabilities is the read-only discovery call. GET /agent/openapi returns the machine-readable document, which is also public at /openapi.json.

Endpoint reference

154 operations, derived from the OpenAPI document. Every operation lists its method, path, required scopes, parameters, request body and response statuses without opening the raw JSON.

Agent 8

GET/api/v1/agent/capabilitiesRead scopes, endpoints, and prices for this key

Use this first. Returns only what this key is allowed to do, plus customer prices. Paid actions run directly when the key has the scope. Legacy spend approvals are optional. Ask the account owner before spending or sending unless they already said to.

getAgentCapabilities

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

GET/api/v1/agent/openapiRead the public API documentno credential

Same JSON as https://www.campaigncommanderapp.com/openapi.json. No API key is required.

getAgentOpenApiDocument

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

GET/api/v1/agent/runsList this key's work runsagent:runs

Owner-visible runs started by this key. Scope agent:runs.

listAgentRuns

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/agent/runsStart a work runagent:runs

Records an objective the account owner can see. Does not send or spend by itself. Scope agent:runs.

createAgentRun

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · AgentRunCreate

objectiverequired
stringminLength=3, maxLength=500
summary
stringmaxLength=2000
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/agent/runs/{id}Read one work runagent:runs

Only a run created by this key. Scope agent:runs.

getAgentRun

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

PATCH/api/v1/agent/runs/{id}Update a work runagent:runs

Set status or a short progress summary. Scope agent:runs.

updateAgentRun

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · AgentRunUpdate

status
stringone of active, waiting_for_master, needs_input, completed, cancelled
summary
stringmaxLength=2000
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/agent/approvalsList legacy spend approvals for this key

Optional. Paid actions do not wait on an approval. Use this only when the caller supplied an approval id.

listSpendApprovals

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/agent/approvalsRequest an optional legacy spend approval

Optional. Omit this and call the send or schedule route directly when the key has the spend scope. If this key has both a per-run limit and a daily limit, a request within both is approved in this response and approved_by is standing limit. The key id is api_key_id. A request over either limit stays pending. Limits do not grant scopes. A supplied approval id must match a valid single-use approval for this key.

requestSpendApproval

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · ApprovalRequest

actionrequired
stringminLength=1, maxLength=120example "email_campaign.send"
maxCents
integermin=1example 500
resourceType
string
resourceId
string
agentRunId
stringmaxLength=200
brand
BrandPreviewRequest BrandPreviewRequest
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Contacts 16

GET/api/v1/contacts/fieldsList the authorized organization's contact-field registrycontacts:read

Scope contacts:read. Returns the fields that have an explicit key/label/type definition unioned with the keys that already appear in contacts' stored custom values, whose type is inferred from those values. The organization is the one that owns the credential, never a request selector. Each field is key (verbatim, including spaces and case), label and type; the response carries no contact values, contact ids, or contacts. This is a bounded, read-only result returning the full registry and total count, not a single page. Read-only: records one routine API audit row and changes no business state. It does not define, convert, or remove any field.

listContactFields

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

PUT/api/v1/contacts/fieldsSave one contact-field definitioncontacts:write

Scope contacts:write. Upserts one explicit key/label/type definition keyed by the field key. The key is preserved verbatim; the label is stored trimmed; the stored row is read back and returned in field. This is a metadata save only: it does NOT convert, clear, or repair any contact's existing value, and it does NOT change a stored value's type; a value that no longer matches the new type keeps its stored text and the app reports a type change when a filter no longer matches. A repeated identical save settles the row on that key/label/type; it spends nothing and sends nothing. A body that names a tenant or user selector is refused, not stripped. When the save committed but the stored row could not be read back, confirmed is false; that is not a refusal, and it must not be replayed blindly.

upsertContactField

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · ContactFieldWriteRequest

keyrequired
stringminLength=1, maxLength=120Field key, preserved verbatim. At most 120 characters.
labelrequired
stringminLength=1, maxLength=120Human-readable label, stored trimmed. At most 120 characters.
typerequired
stringone of text, number, date, boolean
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/contactsSearch contactscontacts:read

Search or list contacts, or look up one contact by exact email or phone. Scope contacts:read. In list mode q, tag, page, limit, sortBy, sortOrder, and filterType apply; sortBy/sortOrder order the page and filterType keeps only contacts whose named field is not NULL (not a claim of deliverability or verification, and a blank value still counts). An exact email or phone does not apply the list options and returns one contact, but supplied enum selectors are still validated. Omit selectors for defaults; explicit empty selectors are invalid. The pagination total and hasMore are null when the database did not return an exact count; unknown is not an end-of-list assertion. Each contact includes its mailing address (address, city, state, zip); address verification internals are never returned.

listContacts

Request, parameters and responses

Parameters

page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. At most 50.
q
string · querySearch name, email, or phone.
email
string · queryExact email address. Returns one contact; an exact lookup ignores q, tag, page, limit, sortBy, sortOrder, and filterType.
phone
string · queryExact U.S. phone number, normalized to E.164. Returns one contact; an exact lookup ignores q, tag, page, limit, sortBy, sortOrder, and filterType.
tag
string · queryOnly contacts that carry this tag.
sortBy
string · queryone of created_at, first_name, last_name, email, phoneSort field for the paginated list. Ignored in exact email/phone mode.
sortOrder
string · queryone of asc, descSort direction for the paginated list. Ignored in exact email/phone mode.
filterType
string · queryone of all, email, phone, addressKeep only contacts whose named field is present (not NULL). all applies no filter. Ignored in exact email/phone mode.

Request body

No request body.

Responses

POST/api/v1/contactsCreate a contactcontacts:write

Provide at least a name, email, phone, or mailing-address field. A duplicate email returns 409 with the existing contact. A suppressed email returns 409 unless overrideSuppression is true and overrideNote is at least 3 characters. Consent blocks cannot be bypassed. Mailing-address fields are address, city, state, and zip only; verification fields are refused. Scope contacts:write.

createContact

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · ContactWrite

firstName
string | nullmaxLength=120, nullable
first_name
string | nullmaxLength=120, nullable
lastName
string | nullmaxLength=120, nullable
last_name
string | nullmaxLength=120, nullable
email
string | nullformat=email, nullable
phone
string | nullnullable
address
string | nullnullableStreet address. Trimmed. Omit to leave unchanged; null or an empty string clears it. A partial address is stored as-is; it is never reported as verified or deliverable.
city
string | nullnullableCity. Trimmed. Omit to leave unchanged; null or an empty string clears it.
state
string | nullnullableState. Trimmed and upper-cased. Omit to leave unchanged; null or an empty string clears it.
zip
string | nullnullableZIP code as text; a leading zero is kept. Omit to leave unchanged; null or an empty string clears it.
notes
string | nullnullable
tags
array<string>maxItems=25
customFields
object<string, string>additionalProperties: string
custom_fields
object<string, string>additionalProperties: string
overrideSuppression
booleanRequired, with overrideNote, to add a suppressed email that the product allows an override for.
overrideNote
stringminLength=3
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/contacts/{id}Read one contactcontacts:read

Scope contacts:read. Includes the mailing address (address, city, state, zip) and never the address verification internals.

getContact

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

PATCH/api/v1/contacts/{id}Update a contactcontacts:write

Name, email, phone, notes, tags, mailing address, or custom fields. Scope contacts:write. Only the fields you send are changed; a changed mailing address invalidates any prior verification and is fenced on the row version, so a concurrent address edit returns 409 rather than storing a stale address hash.

updateContact

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · ContactWrite

firstName
string | nullmaxLength=120, nullable
first_name
string | nullmaxLength=120, nullable
lastName
string | nullmaxLength=120, nullable
last_name
string | nullmaxLength=120, nullable
email
string | nullformat=email, nullable
phone
string | nullnullable
address
string | nullnullableStreet address. Trimmed. Omit to leave unchanged; null or an empty string clears it. A partial address is stored as-is; it is never reported as verified or deliverable.
city
string | nullnullableCity. Trimmed. Omit to leave unchanged; null or an empty string clears it.
state
string | nullnullableState. Trimmed and upper-cased. Omit to leave unchanged; null or an empty string clears it.
zip
string | nullnullableZIP code as text; a leading zero is kept. Omit to leave unchanged; null or an empty string clears it.
notes
string | nullnullable
tags
array<string>maxItems=25
customFields
object<string, string>additionalProperties: string
custom_fields
object<string, string>additionalProperties: string
overrideSuppression
booleanRequired, with overrideNote, to add a suppressed email that the product allows an override for.
overrideNote
stringminLength=3
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/contacts/{id}/tagsAdd tags to a contactcontacts:write

Scope contacts:write.

addContactTags

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · TagWrite

tagsrequired
array<string>minItems=1, maxItems=25
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

DELETE/api/v1/contacts/{id}/tagsRemove tags from a contactcontacts:write

Scope contacts:write.

removeContactTags

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · TagWrite

tagsrequired
array<string>minItems=1, maxItems=25
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

PATCH/api/v1/contacts/{id}/consentSet channel consentcontacts:write

Set email opt-out, text opt-out, or do-not-contact. Clearing do-not-contact is refused. Scope contacts:write.

updateContactConsent

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · ConsentWrite

emailOptOut
boolean
smsOptOut
boolean
doNotContact
booleanfalse is refused.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/contacts/import/previewPreview a contact or suppression importcontacts:read

Multipart form with one or more CSV/XLSX files. Parses the files, classifies the tabs, matches this organization's suppression ledger and returns the exact counts, unresolved metadata decisions and a signed previewToken to commit. Scope contacts:read. It writes preview evidence only, changes no contacts, and charges nothing. Pass plan, tags and reviewChoices to carry the operator's per-tab decisions; pass metadataToken to reuse a frozen classification.

previewContactImport

Request, parameters and responses

Parameters

No parameters.

Request body

multipart/form-data · ContactImportPreviewForm

filerequired
array<string>One or more CSV or XLSX files.
plan
stringJSON array of per-tab decisions: name, key, role (contacts|suppression|ignore), channels, and column mapping. Omit to accept the automatic classification.
tags
stringComma-separated tags applied to every imported contact.
metadataToken
stringA prior preview token, to reuse the frozen classification instead of re-running the classifier.
reviewChoices
stringJSON object of metadata answers, keyed '<evidenceId>', each 'suppress' or 'none'.
cleanEmails
booleanAsk to clean imported emails later. Only enforced at commit.
cleanAddresses
booleanAsk to clean imported addresses later. Only enforced at commit.
smsConsentAttested
booleanOperator attests the file carries SMS consent for its phone numbers.
voiceConsentAttested
booleanOperator attests the file carries voice-call consent for its phone numbers.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/contacts/importCommit a previewed importcontacts:writeemail:verifyaddress:verify

Multipart form with the same files and options as the preview plus previewToken. Scope contacts:write; cleaned emails additionally require email:verify and cleaned addresses require address:verify, refused before any contact write when absent. The commit saves contacts and charges nothing, and does not clean inline: cleaning exactly this import's contacts runs as a SEPARATE paid step, cleanImportCohort, keyed by the cohortId the response carries. The response reports requested cleaning as requested and not performed by this commit. Re-sending an unchanged commit with the same previewToken replays the stored receipt without importing twice.

commitContactImport

Request, parameters and responses

Parameters

No parameters.

Request body

multipart/form-data · ContactImportCommitForm

filerequired
array<string>The same CSV/XLSX files that were previewed.
previewTokenrequired
stringThe signed token returned by the preview.
plan
stringJSON array of per-tab decisions, unchanged from the preview.
tags
stringComma-separated tags, unchanged from the preview.
reviewChoices
stringJSON metadata answers, unchanged from the preview.
cleanEmails
booleanRequest email cleaning. Scope email:verify required. The commit saves contacts only and charges nothing, and does not clean inline: cleaning exactly this import's contacts runs as a separate cohort-scoped paid step keyed by the cohortId the commit returns, so the response reports it as requested and not performed by the commit.
cleanAddresses
booleanRequest address cleaning. Scope address:verify required. The commit saves contacts only and charges nothing, and does not clean inline: cleaning exactly this import's contacts runs as a separate cohort-scoped paid step keyed by the cohortId the commit returns, so the response reports it as requested and not performed by the commit.
smsConsentAttested
boolean
voiceConsentAttested
boolean
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/contacts/importsList this organization's importscontacts:read

Newest first, bounded page with an honest continuation. Returns counts per import only, never per-row outcomes. Scope contacts:read. A missing migration is reported as an error, not an empty list.

listContactImports

Request, parameters and responses

Parameters

offset
integer · queryHow many newest entries to skip.
limit
integer · queryPage size. The server caps this.

Request body

No request body.

Responses

GET/api/v1/contacts/imports/{id}/outcomesRead per-row import outcomescontacts:read

Read the persisted per-row outcomes of one import in this organization. Bounded page with a keyset cursor and an honest continuation that advances by actual rows, so a server page cap never truncates the evidence. category filters to create, merge, suppress or skip. Scope contacts:read. format=csv returns the full set as CSV. A foreign import or a missing table is an error, never empty success.

getContactImportOutcomes

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
limit
integer · queryPage size. The server caps this.
cursor
string · queryKeyset cursor from a prior response's next_cursor.
category
string · queryone of create, merge, suppress, skipLimit import outcomes to one kind.
format
string · queryone of json, csvExport format.

Request body

No request body.

Responses

GET/api/v1/contacts/imports/cohorts/{cohortId}Read an import identity cohortcontacts:read

Read the safe metadata of one frozen import identity cohort by its id (returned as cohortId by the commit when the commit was preview-backed): id, preview and job references, snapshot version/fingerprint, requested cleaning channels, CAPTURED UNIQUE identity counts, a capture state and whether the separate cohort-scoped paid cleaning step is available. Never the raw email/address keys, never a billable-unit or pending-check count, and never a cleaning execution status. Scope contacts:read. A foreign or absent cohort is 404; a missing table is an error, never empty success.

getImportCleaningCohort

Request, parameters and responses

Parameters

cohortIdrequired
string · pathThe id of one import identity cohort.

Request body

No request body.

Responses

POST/api/v1/contacts/import/cohorts/{cohortId}/cleanClean one import identity cohortemail:verifyaddress:verify

Spends balance and cleans EXACTLY the frozen cohort's identities: the contacts matching the cohort's captured email keys and complete-address hashes, in this organization. It never runs a whole-organization verification and never accepts a caller-supplied key list. Scope email:verify and address:verify. Requires confirm true and a unique idempotency key. Nothing is charged when no cohort identity needs cleaning.

cleanImportCohort

Request, parameters and responses

Parameters

cohortIdrequired
string · pathThe id of one import identity cohort.

Request body

application/json · ContactImportCohortClean

channelsrequired
array<string>Which identities to clean. At least one.
confirmrequired
booleanMust be true.
idempotency_keyrequired
stringUnique 16 to 128 character key.
approval_id
stringOptional approved operator spend approval id for this exact cohort.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/contacts/import/stagedStage a large contact-import upload in chunkscontacts:write

Begin or extend a staged upload for a contact file too large to inline in one call. The first call omits stagingId and returns a staging id; later calls append a chunk with that id, and final true marks the last chunk. Stores bytes only: nothing is parsed, no contact is written and nothing is charged. The staging id is the durable reference a later import commit uses for this file. Scope contacts:write.

stageContactImportUpload

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · ContactImportStagedUpload

filenamerequired
stringFile name for the whole upload.
content_base64required
stringThis chunk's bytes, base64-encoded.
staging_id
stringThe id returned by the first chunk. Omit on the first call.
final
booleanSet true on the last chunk.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Lists 10

GET/api/v1/listsList saved audienceslists:read

Saved lists for this organization. Scope lists:read.

listLists

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/listsCreate a saved listlists:write

Name is required. Filters use the same fields as the product. Scope lists:write.

createList

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · ListWrite

name
stringmaxLength=120
description
stringmaxLength=1000
filters
ListFilters ListFilters
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/lists/{id}Read one saved listlists:read

Scope lists:read.

getList

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

PATCH/api/v1/lists/{id}Edit a saved listlists:write

Name, description, or filters. Scope lists:write.

updateList

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · ListWrite

name
stringmaxLength=120
description
stringmaxLength=1000
filters
ListFilters ListFilters
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

DELETE/api/v1/lists/{id}Delete a saved listlists:write

Refuses a locked list or one still in use. Scope lists:write.

deleteList

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

POST/api/v1/lists/{id}/membersAdd contacts to a static listlists:write

Up to 100 contact ids. Only static tag lists. Scope lists:write.

addListMembers

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · MemberIds

contactIdsrequired
array<string>maxItems=100
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

DELETE/api/v1/lists/{id}/membersRemove contacts from a static listlists:write

Up to 100 contact ids. Scope lists:write.

removeListMembers

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · MemberIds

contactIdsrequired
array<string>maxItems=100
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/lists/{id}/usageCount campaigns that use a listlists:read

How many email, text, mail, and calling campaigns reference this list. Scope lists:read.

getListUsage

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

GET/api/v1/lists/resolveResolve an audience from plain languagelists:read

Returns one list or candidates to confirm. Scope lists:read.

resolveList

Request, parameters and responses

Parameters

queryrequired
string · queryAudience description in plain language.

Request body

No request body.

Responses

POST/api/v1/lists/previewCount a prospective listlists:read

Returns a count, not the contacts. Scope lists:read.

previewList

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · ListPreview

filtersrequired
ListFilters ListFilters
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Suppressions 4

GET/api/v1/suppressionsList suppression recordssuppression:read

Scope suppression:read.

listSuppressions

Request, parameters and responses

Parameters

page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. The server caps this.
channel
string · queryone of email, sms, voice, allLimit suppression rows to one channel.

Request body

No request body.

Responses

POST/api/v1/suppressionsRecord a suppressionsuppression:write

Email, phone, or both. Reason is manual, recipient_blocks_sender, unsubscribe, or legal_request. Note is required. Scope suppression:write.

createSuppression

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · SuppressionWrite

email
stringformat=email
phone
string
reasonrequired
stringone of manual, recipient_blocks_sender, unsubscribe, legal_request
noterequired
stringminLength=3, maxLength=1000
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

PATCH/api/v1/suppressions/{id}Bypass an overridable suppressionsuppression:write

The row is kept. Note explains why. Scope suppression:write.

bypassSuppression

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · SuppressionBypass

noterequired
stringminLength=3, maxLength=1000
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

DELETE/api/v1/suppressions/{id}Withdraw a suppression bypasssuppression:write

Puts the suppression back in force. Does not delete the row. Scope suppression:write.

withdrawSuppressionBypass

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

Email 30

POST/api/v1/email/campaigns/previewPreview an email audience and costemail:draft

Does not send or charge. Audience may be all, segment, selected, or people who opened or clicked a prior email. excludeCampaignIds drops people already on those campaigns, counted once per contact. resendToNonOpenersAfterHours may be 24, true, false, or null. Scope email:draft. Price is $1 per 1,000, minimum 1 cent. accountSuppressedCount is how many otherwise-mailable addresses are already blocked for this account.

previewEmailCampaign

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · EmailDraft

name
string
subject
string
message
stringHTML body. html or body are accepted aliases.
html
string
body
string
fromName
string
fromEmail
stringformat=email
replyToEmail
stringformat=email
recipientType
stringone of all, segment, selected, campaign_engagement
segmentId
stringformat=uuid
segmentIds
array<string>
selectedContactIds
array<string>
sourceCampaignId
stringformat=uuid
engagement
stringone of opened, clicked
engagementInclude
stringone of human, all
excludeCampaignIds
array<string>Prior email campaigns. People on them are left out, once per contact.
resendToNonOpenersAfterHours
any24 or true turns on a next-day send to people who did not open. false or null leaves it off.
firstNameFallback
string | nullnullableGreeting used when a contact has no first name and the message has no inline {first_name|...} fallback. Trimmed and capped at 60 characters. Omit to use Friend. Null or blank stores Friend. An inline tag still wins.
scheduledAt
stringformat=date-timeOptional. Also schedules the new draft. Requires email:send and Idempotency-Key.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/email/campaignsList email campaignsemail:read

Newest first. limit defaults to 20 and is capped at 100; page starts at 1. opened_count is unique recipients with any recorded open (including Apple MPP prefetches and machine scanners), the same number as opens.raw from /email/campaigns/{id}/clicks; it is not total open hits. metricDefinitions explains each count. Scope email:read.

listEmailCampaigns

Request, parameters and responses

Parameters

page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. The server caps this.

Request body

No request body.

Responses

POST/api/v1/email/campaignsCreate an email draftemail:draftIdempotency-Key

Creates a draft. Include scheduledAt only when this call should also schedule it. That also needs scope email:send and an Idempotency-Key. scheduledAt is ISO-8601 with a numeric offset or Z, at least 5 minutes ahead and no more than 366 days out. Scope email:draft.

createEmailCampaign

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · EmailDraft

name
string
subject
string
message
stringHTML body. html or body are accepted aliases.
html
string
body
string
fromName
string
fromEmail
stringformat=email
replyToEmail
stringformat=email
recipientType
stringone of all, segment, selected, campaign_engagement
segmentId
stringformat=uuid
segmentIds
array<string>
selectedContactIds
array<string>
sourceCampaignId
stringformat=uuid
engagement
stringone of opened, clicked
engagementInclude
stringone of human, all
excludeCampaignIds
array<string>Prior email campaigns. People on them are left out, once per contact.
resendToNonOpenersAfterHours
any24 or true turns on a next-day send to people who did not open. false or null leaves it off.
firstNameFallback
string | nullnullableGreeting used when a contact has no first name and the message has no inline {first_name|...} fallback. Trimmed and capped at 60 characters. Omit to use Friend. Null or blank stores Friend. An inline tag still wins.
scheduledAt
stringformat=date-timeOptional. Also schedules the new draft. Requires email:send and Idempotency-Key.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/email/campaigns/{id}Read an email campaignemail:read

Includes stored content, status, and scheduled time. Scope email:read.

getEmailCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

PATCH/api/v1/email/campaigns/{id}Revise an email draftemail:draft

Unscheduled drafts only. Does not change the audience. Scope email:draft.

updateEmailCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · EmailDraftPatch

name
string
subject
string
message
string
html
string
body
string
fromName
string
fromEmail
stringformat=email
replyToEmail
stringformat=email
firstNameFallback
string | nullnullableGreeting used when a contact has no first name and the message has no inline {first_name|...} fallback. Trimmed and capped at 60 characters. Omit to leave the saved value. Null or blank clears it back to Friend. An inline tag still wins.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

DELETE/api/v1/email/campaigns/{id}Delete an unsent email draftemail:draft

Only an unsent, unscheduled draft. Sent campaigns are kept. Scope email:draft.

deleteEmailCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

PATCH/api/v1/email/campaigns/{id}/audienceReplace a draft audienceemail:draft

Replaces the audience and rebuilds the recipient snapshot. Scope email:draft.

replaceEmailAudience

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · EmailDraft

name
string
subject
string
message
stringHTML body. html or body are accepted aliases.
html
string
body
string
fromName
string
fromEmail
stringformat=email
replyToEmail
stringformat=email
recipientType
stringone of all, segment, selected, campaign_engagement
segmentId
stringformat=uuid
segmentIds
array<string>
selectedContactIds
array<string>
sourceCampaignId
stringformat=uuid
engagement
stringone of opened, clicked
engagementInclude
stringone of human, all
excludeCampaignIds
array<string>Prior email campaigns. People on them are left out, once per contact.
resendToNonOpenersAfterHours
any24 or true turns on a next-day send to people who did not open. false or null leaves it off.
firstNameFallback
string | nullnullableGreeting used when a contact has no first name and the message has no inline {first_name|...} fallback. Trimmed and capped at 60 characters. Omit to use Friend. Null or blank stores Friend. An inline tag still wins.
scheduledAt
stringformat=date-timeOptional. Also schedules the new draft. Requires email:send and Idempotency-Key.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/email/campaigns/{id}/recipients/refreshRebuild a draft recipient snapshotemail:draft

Uses the audience already saved on the draft. Scope email:draft.

refreshEmailRecipients

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

POST/api/v1/email/campaigns/{id}/testSend a test of a stored email draftemail:testIdempotency-Key

Sends to the key owner, an active organization member, or a verified test recipient. to or testEmails accepts up to 5 addresses. More than one recipient needs an Idempotency-Key of 16 to 128 letters, numbers, underscores, or hyphens. Scope email:test. Tests are charged.

sendEmailTest

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · EmailTest

to
anyOne address or a list of up to 5. Each must be the key owner, an active member, or a verified test recipient.
testEmails
array<string>maxItems=5
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/email/test-recipientsList test recipientsemail:test

Addresses allowed to receive email test sends after they confirm. Pending addresses are not valid test destinations yet. Scope email:test. Does not return confirmation links.

listTestRecipients

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/email/test-recipientsAdd a test recipientemail:test

Sends one verification email. A verified address is not emailed again. A pending address is not emailed again within ten minutes. The address cannot receive a test until it confirms. Scope email:test. Does not send a campaign or charge.

addTestRecipient

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · TestRecipientWrite

emailrequired
stringformat=email
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

DELETE/api/v1/email/test-recipients/{id}Remove a test recipientemail:test

The address can no longer receive test sends unless it is the key owner or an active member. Scope email:test. Does not send a message or change the balance.

removeTestRecipient

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

POST/api/v1/email/campaigns/{id}/sendStart a live email campaignemail:send

Spends balance and starts delivery. Scope email:send. $1 per 1,000 recipients, minimum 1 cent. Do not retry an uncertain result blindly.

sendEmailCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · ApprovalOptional

approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/email/campaigns/{id}/scheduleSchedule an email draftemail:sendIdempotency-Key

Does not send or charge until the scheduled time. Requires Idempotency-Key and scope email:send. scheduledAt is ISO-8601 with an offset or Z.

scheduleEmailCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · ScheduleBody

scheduledAtrequired
stringformat=date-timeISO-8601 with a numeric offset or Z. At least 5 minutes ahead and no more than 366 days out.
approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/email/campaigns/{id}/unscheduleReturn a scheduled email to draftemail:sendIdempotency-Key

Refuses a campaign that is already sending or sent. Requires Idempotency-Key and scope email:send.

unscheduleEmailCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

No request body.

Responses

GET/api/v1/email/transactionalList transactional emailsemail:transactional

System mail for this organization. Scope email:transactional.

listTransactionalEmails

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/email/transactionalSend a transactional emailemail:transactionalIdempotency-Key

One-to-one system mail. No marketing footer. Hard bounces and complaints suppress later mail. Accepts the message and returns 202 with id and status queued before the provider call. A response in the 200 range that has id and no error is success. A replay of a completed send inside 24 hours returns 200 with id. An Idempotency-Key of 8 to 255 characters dedupes per organization for 24 hours. Scope email:transactional. Default price matches campaign email. A new organization is limited to 10 sends per minute and 200 recipients per day until those limits are changed.

sendTransactionalEmail

Request, parameters and responses

Parameters

Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · TransactionalSend

torequired
anyRequired. One address or a list. Combined to, cc, and bcc must be 1 to 50.
cc
any
bcc
any
from
string
reply_to
string
subject
stringmaxLength=998
html
string
text
string
template_id
stringformat=uuid
variables
objectadditionalProperties: allowed
headers
object<string, string>additionalProperties: string
tags
array<string>maxItems=10
tracking
boolean
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/email/transactional/{id}Read one transactional emailemail:transactional

Status, attempt_count, next_attempt_at, and recipients. queued means the row is still waiting. The rendered body is not included. Scope email:transactional.

getTransactionalEmail

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

GET/api/v1/email/transactional/templatesList transactional templatesemail:transactional

Scope email:transactional.

listTransactionalTemplates

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/email/transactional/templatesCreate a transactional templateemail:transactional

Placeholders use double curly braces. Scope email:transactional.

createTransactionalTemplate

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · TransactionalTemplateWrite

namerequired
stringminLength=1, maxLength=120
subjectrequired
stringminLength=1, maxLength=200
htmlrequired
stringminLength=1
text
string
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/email/transactional/templates/{id}Read a transactional templateemail:transactional

Scope email:transactional.

getTransactionalTemplate

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

PATCH/api/v1/email/transactional/templates/{id}Update a transactional templateemail:transactional

Scope email:transactional.

updateTransactionalTemplate

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · TransactionalTemplateWrite

namerequired
stringminLength=1, maxLength=120
subjectrequired
stringminLength=1, maxLength=200
htmlrequired
stringminLength=1
text
string
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

DELETE/api/v1/email/transactional/templates/{id}Delete a transactional templateemail:transactional

Scope email:transactional.

deleteTransactionalTemplate

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

GET/api/v1/email/transactional/webhooksList transactional webhook endpointsemail:transactional

Https endpoints for delivered, bounced, and failed. The secret is not returned. Scope email:transactional.

listTransactionalWebhooks

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/email/transactional/webhooksCreate a transactional webhook endpointemail:transactional

Https url only. The secret is returned once. Scope email:transactional.

createTransactionalWebhook

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · TransactionalWebhookWrite

urlrequired
stringformat=uri
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

PATCH/api/v1/email/transactional/webhooks/{id}Enable or disable a transactional webhookemail:transactional

Does not rotate the secret. Scope email:transactional.

updateTransactionalWebhook

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · TransactionalWebhookUpdate

enabledrequired
boolean
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

DELETE/api/v1/email/transactional/webhooks/{id}Delete a transactional webhookemail:transactional

Scope email:transactional.

deleteTransactionalWebhook

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

GET/api/v1/email/campaigns/{id}/recipientsRead email recipient outcomeslogs:read

Scope logs:read.

listEmailRecipients

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. The server caps this.

Request body

No request body.

Responses

GET/api/v1/email/campaigns/{id}/eventsRead email delivery eventslogs:read

Scope logs:read.

listEmailEvents

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. The server caps this.

Request body

No request body.

Responses

GET/api/v1/email/campaigns/{id}/clicksRead email opens and grouped clicksemail:read

Human, Apple MPP, and machine opens for this email campaign, plus human and raw clicks. Human events are not machine and not Apple MPP, so a proxied mail fetch counts as human. An unclassified click counts as human. Apple MPP is its own bucket and is an open, so it does not reduce click counts. Machine events are the stored machine classification. opens.raw is unique recipients with any recorded open (one stored open per recipient) and equals the campaign opened_count. Click raw is every recorded click event. definitions explains each count. group_by=url, the default, groups by the normalized link: scheme and host, with the query string, the fragment, and per-recipient path tokens removed. A readable slug stays. group_by=utm_content groups by that parameter, and a click without it is null. A click stored without a link is null in either grouping. Any other group_by is rejected. Scope email:read. The campaign must belong to the key's organization.

getEmailCampaignClicks

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
group_by
string · queryone of url, utm_contentHow to group clicks. url is the normalized link. utm_content groups by that parameter. Defaults to url.

Request body

No request body.

Responses

Transactional email 3

GET/api/v1/emailsList transactional emails (alias)email:transactional

Same JSON as GET /email/transactional. Scope email:transactional.

listEmailsAlias

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/emailsSend a transactional email (alias)email:transactional

Same JSON as POST /email/transactional. A new send returns 202. A response in the 200 range that has id and no error is success. Scope email:transactional.

sendEmailAlias

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · TransactionalSend

torequired
anyRequired. One address or a list. Combined to, cc, and bcc must be 1 to 50.
cc
any
bcc
any
from
string
reply_to
string
subject
stringmaxLength=998
html
string
text
string
template_id
stringformat=uuid
variables
objectadditionalProperties: allowed
headers
object<string, string>additionalProperties: string
tags
array<string>maxItems=10
tracking
boolean
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/emails/{id}Read one transactional email (alias)email:transactional

Same JSON as GET /email/transactional/{id}. Scope email:transactional.

getEmailAlias

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

Text (SMS & MMS) 15

GET/api/v1/sms/readinessRead texting readinesssms:read

Whether the organization can text, plus blockers in plain language. Scope sms:read.

getSmsReadiness

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/sms/campaigns/previewPreview a text audience and costsms:draft

Does not send or charge. Short texts are 3 cents. Longer texts and pictures are 6 cents. Scope sms:draft.

previewSmsCampaign

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · SmsDraft

type
stringone of sms, mms
name
stringmaxLength=120
message
stringmaxLength=1600
recipientType
stringone of all, segment, custom
segmentId
stringformat=uuid
segmentIds
array<string>
filters
ListFilters ListFilters
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/sms/campaignsList text campaignssms:read

Scope sms:read.

listSmsCampaigns

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/sms/campaignsCreate a text draftsms:draft

JSON for a plain text. A picture message must be multipart with an image file named image. scheduledAt is rejected here. Schedule with the schedule route. Scope sms:draft.

createSmsCampaign

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · SmsDraft

type
stringone of sms, mms
name
stringmaxLength=120
message
stringmaxLength=1600
recipientType
stringone of all, segment, custom
segmentId
stringformat=uuid
segmentIds
array<string>
filters
ListFilters ListFilters
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/sms/campaigns/{id}Read one text campaignsms:read

Scope sms:read. Picture messages report hasMedia, not a file URL.

getSmsCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

PATCH/api/v1/sms/campaigns/{id}Revise a text draftsms:draft

Name, message, or type. Audience changes use the audience route. Scope sms:draft.

updateSmsCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · SmsDraft

type
stringone of sms, mms
name
stringmaxLength=120
message
stringmaxLength=1600
recipientType
stringone of all, segment, custom
segmentId
stringformat=uuid
segmentIds
array<string>
filters
ListFilters ListFilters
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

PATCH/api/v1/sms/campaigns/{id}/audienceReplace a text draft audiencesms:draft

Replaces the audience and rebuilds the recipient snapshot for an unscheduled draft. Recalculates the recipient count and cost estimate. Does not send, schedule, or charge. A campaign that is no longer a draft is refused. Scope sms:draft.

replaceSmsAudience

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · SmsDraft

type
stringone of sms, mms
name
stringmaxLength=120
message
stringmaxLength=1600
recipientType
stringone of all, segment, custom
segmentId
stringformat=uuid
segmentIds
array<string>
filters
ListFilters ListFilters
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/sms/campaigns/{id}/testSend a text testsms:testIdempotency-Key

Sends the stored draft to the key owner's verified phone. Requires Idempotency-Key and scope sms:test. Charged like a live text.

sendSmsTest

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · ApprovalOptional

approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/sms/campaigns/{id}/sendStart text deliverysms:sendIdempotency-Key

Spends balance and starts delivery. Requires Idempotency-Key and scope sms:send.

sendSmsCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · ApprovalOptional

approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/sms/campaigns/{id}/scheduleSchedule a text draftsms:sendIdempotency-Key

Does not text or charge until the scheduled time. Requires Idempotency-Key and scope sms:send.

scheduleSmsCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · ScheduleBody

scheduledAtrequired
stringformat=date-timeISO-8601 with a numeric offset or Z. At least 5 minutes ahead and no more than 366 days out.
approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/sms/campaigns/{id}/unscheduleReturn a scheduled text to draftsms:sendIdempotency-Key

Refuses a campaign that is already sending or sent. Requires Idempotency-Key and scope sms:send.

unscheduleSmsCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

No request body.

Responses

GET/api/v1/sms/campaigns/{id}/recipientsRead text recipient outcomessms:readlogs:read

Needs both sms:read and logs:read.

listSmsRecipients

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. The server caps this.

Request body

No request body.

Responses

GET/api/v1/sms/campaigns/{id}/eventsRead text delivery eventssms:readlogs:read

Needs both sms:read and logs:read.

listSmsEvents

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. The server caps this.
status
string · queryone of queued, sending, sent, delivered, failedFilter delivery events by status.

Request body

No request body.

Responses

GET/api/v1/sms/campaigns/{id}/clicksRead per-link text clickssms:read

Clicks for each tracked link on this text campaign. Each row is the link id, the https destination, the human tap count, and the raw tap count. Human excludes a scanner. Raw includes a scanner and a second tap. A link with no taps is included with zero. Redirect tokens are not returned. Scope sms:read. The campaign must belong to the key's organization.

getSmsCampaignClicks

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

GET/api/v1/sms/campaigns/{id}/outcomesRead text failure counts by reasonsms:readlogs:read

Needs both sms:read and logs:read. sampleError is plain language.

getSmsOutcomes

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

Physical mail 5

POST/api/v1/mail/campaigns/previewPreview a postcard or lettermail:read

Does not reserve funds or print. Scope mail:read. Postcard 4x6 is $1.19, 6x9 is $1.35, 6x11 is $1.69. A letter is $1.59. Printing cannot be recalled.

previewMailCampaign

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · MailPreviewRequest

mailTyperequired
stringone of postcard, letter
postcardSize
stringone of 4x6, 6x9, 6x11
recipientTyperequired
stringone of all, segment
segmentId
stringformat=uuid
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/mail/campaignsList postcard and letter campaignsmail:read

Scope mail:read.

listMailCampaigns

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/mail/campaignsCreate a postcard or letter draftmail:draftIdempotency-Key

Multipart form. mailType is postcard or letter. postcardSize is 4x6, 6x9, or 6x11. frontCreative is required. Holds balance. Requires Idempotency-Key and scope mail:draft.

createMailCampaign

Request, parameters and responses

Parameters

Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

multipart/form-data · MailCreateForm

namerequired
stringminLength=1, maxLength=120
mailTyperequired
stringone of postcard, letter
postcardSize
stringone of 4x6, 6x9, 6x11
listId
stringformat=uuid
frontCreativerequired
stringformat=binary
backCreative
stringformat=binary
letterCreative
stringformat=binary
includePartialAddresses
stringone of true, false
oneMailPerAddress
stringone of true, false
isTest
stringone of true, falseHidden. true keeps the campaign out of ordinary lists.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/mail/campaigns/{id}Read a postcard or letter campaignmail:read

Configuration and progress. Creative file URLs are omitted. Scope mail:read.

getMailCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

POST/api/v1/mail/campaigns/{id}/launchSubmit postcards or letters for printingmail:sendIdempotency-Key

Spends the hold and cannot be recalled. Requires Idempotency-Key and scope mail:send.

launchMailCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · ApprovalOptional

approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Voice & dialer 19

GET/api/v1/voice/numbersList voice caller idsvoice:read

Active voice-enabled numbers for this organization. Scope voice:read.

listVoiceNumbers

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

GET/api/v1/voice/numbers/searchSearch available phone numberssettings:read

Owner or admin. Ask the carrier marketplace for numbers this organization can buy: toll-free inventory by default, or local inventory for an areaCode and optional state. type is toll-free or local. Each result carries the one-time setup price and the monthly rental. Read-only: it reserves no funds, orders nothing, and assigns nothing; one routine API audit row is recorded. Buy a result with POST /voice/numbers/purchase. Scope settings:read.

searchPhoneNumbers

Request, parameters and responses

Parameters

areaCode
string · queryUS area code for a local phone-number search. Ignored for a toll-free search.
state
string · queryTwo-letter US state for a local phone-number search. Ignored for a toll-free search.
type
string · queryone of toll-free, localWhich phone-number inventory to search. Defaults to toll-free.

Request body

No request body.

Responses

POST/api/v1/voice/numbers/purchaseBuy a toll-free phone numbersettings:writeIdempotency-Key

Owner or admin. Buy one toll-free number for this organization and charge the one-time setup fee from the organization balance. phoneNumber must be a toll-free number returned by GET /voice/numbers/search. Requires confirm true, a bounded Idempotency-Key header, and scope settings:write. A retry with the same key reuses one reservation and never orders a second number. The monthly rental is billed later by the rental job. Pass approvalId only when an operator approved this exact purchase.

purchasePhoneNumber

Request, parameters and responses

Parameters

Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · PhoneNumberPurchaseRequest

phoneNumberrequired
stringThe toll-free number to buy, in E.164 form.
confirmrequired
booleanMust be true. A purchase spends the setup fee and cannot be undone.
approvalId
stringOptional operator approval id for this exact purchase.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/voice/numbers/{id}/defaultSet the default caller idsettings:write

Owner or admin. Set one active number in this organization as the default caller id. The number is the path id. It changes settings only: it moves no money and orders nothing. Scope settings:write.

setDefaultPhoneNumber

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

POST/api/v1/voice/assetsUpload a voicemail recordingvoice:draft

Multipart file field. MP3 or WAV, up to 10 MB. Returns an asset token to use when creating a voicemail draft. Scope voice:draft.

uploadVoiceAsset

Request, parameters and responses

Parameters

No parameters.

Request body

multipart/form-data · VoiceAssetUpload

filerequired
stringformat=binaryaudio/mpeg or audio/wav
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/voice/campaignsList call, voicemail, and robocall draftsvoice:read

Scope voice:read.

listVoiceCampaigns

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/voice/campaignsCreate a call, voicemail, or robocall draftvoice:draft

type is call, voicemail, or robocall. A call needs message. A voicemail or robocall needs audioAssetToken and audioDuration. Scheduling is not accepted here. Scope voice:draft. Calls, voicemail, and robocalls are 6 cents per connected started minute. Ringing is free.

createVoiceCampaign

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · VoiceDraft

typerequired
stringone of call, voicemail
namerequired
stringmaxLength=160
message
stringRequired when type is call.
ccNumberIdrequired
string
recipientTyperequired
stringone of all, segment, custom
segmentId
stringformat=uuid
contactIds
array<string>
audioAssetToken
stringRequired for voicemail. From the upload route.
audioDuration
integermin=1, max=300
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/voice/campaigns/{id}Read a voice campaignvoice:read

Scope voice:read.

getVoiceCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

GET/api/v1/voice/campaigns/{id}/recipientsRead voice recipient outcomesvoice:readlogs:read

Needs both voice:read and logs:read.

listVoiceRecipients

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

POST/api/v1/voice/campaigns/{id}/launchLaunch voicemail deliveryvoice:sendIdempotency-Key

Spends balance. Requires Idempotency-Key and scope voice:send. A drop reserves 42 cents.

launchVoiceCampaign

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · ApprovalOptional

approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/voice/campaigns/{id}/recording-testPlay a robocall draft recording on the key owner's registered phonevoice:sendIdempotency-Key

Plays this draft's saved recording to the API key owner's registered phone. The draft is not launched and the list is not dialed. Requires Idempotency-Key and scope voice:send.

testVoiceRobocallDraft

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.
Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · ApprovalOptional

approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/voice/robocall/testPlace a personal robocall testvoice:sendIdempotency-Key

Places one standalone robocall of an organization-owned recording to the API key owner's registered phone. Never attaches to a campaign. Requires Idempotency-Key and scope voice:send.

testVoiceRobocall

Request, parameters and responses

Parameters

Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · VoiceRobocallTestRequest

audioUrlrequired
stringformat=uri
audioAssetTokenrequired
stringOpaque token from the voice asset upload.
audioDurationrequired
integermin=1, max=300
ccNumberId
string
approvalId
string
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/voice/callsPlace a one-to-one callvoice:sendIdempotency-Key

contactId is required. The operator is dialed first. If the operator does not answer, the contact is not dialed. Requires Idempotency-Key and scope voice:send.

placeVoiceCall

Request, parameters and responses

Parameters

Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · VoiceCallCreate

contactIdrequired
stringformat=uuid
approvalId
string
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/voice/calls/activeRead the active call for this key's ownervoice:read

Scope voice:read.

getActiveVoiceCall

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

GET/api/v1/voice/calls/{id}Read a call sessionvoice:read

Scope voice:read. Carrier call ids are not included.

getVoiceCall

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

GET/api/v1/voice/power-dialer/sessionsList power dialer sessionsvoice:read

Sessions for this key's owner. Scope voice:read.

listPowerDialerSessions

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/voice/power-dialer/sessionsOpen or resume a power dialer sessionvoice:draft

Body is campaignId. The operator cannot set a bridge phone. Scope voice:draft. 6 cents per operator-connected started minute, up to $14.40.

openPowerDialerSession

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · PowerDialerOpen

campaignIdrequired
stringformat=uuid
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/voice/power-dialer/sessions/{sessionId}Read a power dialer sessionvoice:read

Scope voice:read.

getPowerDialerSession

Request, parameters and responses

Parameters

sessionIdrequired
string · pathPower dialer session id.

Request body

No request body.

Responses

POST/api/v1/voice/power-dialer/sessions/{sessionId}/nextDial the next power dialer contactvoice:sendIdempotency-Key

Hangs up the current contact only. Requires Idempotency-Key and scope voice:send.

dialNextPowerDialerContact

Request, parameters and responses

Parameters

sessionIdrequired
string · pathPower dialer session id.
Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

No request body.

Responses

Verification 4

GET/api/v1/verification/emailQuote an email verification runemail:verify

Returns how many unique addresses would be checked and the cost. Does not return the addresses. Scope email:verify.

quoteEmailVerification

Request, parameters and responses

Parameters

recipientType
string · queryone of all, segmentWhose addresses to quote. Defaults to all contacts.
segmentId
string · querySaved list id when recipientType is segment.

Request body

No request body.

Responses

POST/api/v1/verification/emailRun email verificationemail:verify

Spends balance and checks the quoted addresses. Scope email:verify.

runEmailVerification

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · ApprovalOptional

approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/verification/addressQuote a postal address verification runaddress:verify

All mailing contacts. Returns a quote, not the addresses. Scope address:verify.

quoteAddressVerification

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/verification/addressRun postal address verificationaddress:verify

Spends balance. Scope address:verify.

runAddressVerification

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · ApprovalOptional

approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Conversions 3

POST/api/v1/conversionsRecord an attributed conversionconversions:write

From an external form, site, or payment system. Scope conversions:write. campaignId, event, and externalId are required.

recordConversion

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · ConversionWrite

campaignIdrequired
stringformat=uuid
eventrequired
stringpattern=^[a-z][a-z0-9_-]{0,79}$
externalIdrequired
string
valueCents
integermin=0
occurredAt
stringformat=date-time
metadata
objectadditionalProperties: allowed
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/conversions/sourcesList conversion sourcesconversions:write

Donation, sign-up, and RSVP sources for the key's organization. The token is not returned. Scope conversions:write.

listConversionSources

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/conversions/sourcesCreate a conversion sourceconversions:write

Returns the token and webhook URL once. A donation source uses the Anedot donation_completed signature. A sign-up or RSVP source also has a pixel URL. Scope conversions:write.

createConversionSource

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · ConversionSourceWrite

kindrequired
stringone of donation, signup, rsvp
parserrequired
stringone of anedot, generic
signingSecret
string
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Inbox 2

GET/api/v1/inbox/conversationsList inbox conversationsinbox:read

Triage metadata only. Delivery addresses are omitted. Sending a reply is not available. Scope inbox:read.

listInboxConversations

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

GET/api/v1/inbox/conversations/{id}Read one inbox conversationinbox:read

Content for triage. No delivery addresses and no send. Scope inbox:read.

getInboxConversation

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

Organization 2

GET/api/v1/organization/settingsRead organization settingssettings:read

Committee name, paid-for-by line, mailing address, From name and address, Reply-To, entity type, EIN, legal name, website, and setup completion with the exact missing fields. Verification tokens and provider identifiers are never returned. Scope settings:read.

getOrganizationSettings

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/organization/settingsSave organization settingssettings:write

Owner or admin only. Replaces the whole settings form; send the same required fields as Account, Organization settings. Omitted street2, optional contact, EIN, and default phone are cleared; the legal name defaults to the committee name and the website falls back to the optional contact. A saved token mask leaves the stored verification token unchanged. Does not send, register, or charge. Scope settings:write.

updateOrganizationSettings

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · OrganizationSettingsUpdate

committeeNamerequired
string
authorizationLinerequired
string
physicalAddressStreetrequired
string
physicalAddressStreet2
string
physicalAddressCityrequired
string
physicalAddressStaterequired
string
physicalAddressZiprequired
string
optionalContact
string
replyToEmailrequired
string
emailFromNamerequired
string
emailFromAddressrequired
string
organizationTyperequired
stringone of candidate, pac, party, other_527, 501c3, 501c4, 501c5, 501c6
ein
string
legalBusinessName
string
website
string
defaultCampaignPhoneId
string
campaignVerifyToken
string
campaignVerifyEmailToken
string
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Communications 4

GET/api/v1/communications/settingsRead sender and compliance settingssettings:read

From name, from address, reply-to, the public compliance block, and the sending domain's authentication state with the exact DNS records it requires. Domain status and records are read from the provider for an owned domain and are reported not linked otherwise. Scope settings:read.

getCommunicationSettings

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

GET/api/v1/communications/sending-domainRead the sending domain and its DNS recordssettings:read

The credential organization's owned sending-domain state and the exact CNAME records to publish, read from the provider for an owned domain. profile defaults to campaign; campaign and transactional may infer the saved domain, registry requires an explicit domain. A domain this organization does not own is reported not linked without asking the provider, so no other organization's domain is disclosed. Read-only. Scope settings:read.

getSendingDomain

Request, parameters and responses

Parameters

domain
string · queryA sending domain to read. Registry profile requires it.
profile
string · queryone of campaign, transactional, registryWhich saved domain profile to read. Defaults to campaign.

Request body

No request body.

Responses

POST/api/v1/communications/sending-domainAuthenticate a sending domainsettings:write

ensure creates the domain identity and returns the records to publish, verify rechecks an existing identity, and recover resumes a partially completed configuration. Only an active owner or admin in the credential's organization may run it, and it works during an incomplete setup so an owner can finish the From domain. It never sends, charges, turns on a channel, or changes a price, rate, pause, or account state. No confirmation flag is required. It takes no organization or user selector, no raw records, no URL, and no local path. Scope settings:write.

configureSendingDomain

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · SendingDomainConfigureRequest

actionrequired
stringone of ensure, verify, recover
profile
stringone of campaign, transactional, registry
domain
string
from_email
string
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/communications/sending-domain/previewPreview a sending-domain actionsettings:read

Reports the proposed domain, whether an ensure, verify, or recover action would be eligible, the blockers, and its side effects. It claims nothing, calls no provider, and saves nothing, and it never inspects an unattached provider identity. It takes no organization or user selector, no raw records, no URL, and no local path. Scope settings:read.

previewSendingDomain

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · SendingDomainPreviewRequest

domain
string
from_email
string
profile
stringone of campaign, transactional, registry
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Exports 1

GET/api/v1/exports/contactsExport contactsexports:read

JSON or CSV, paged. Scope exports:read.

exportContacts

Request, parameters and responses

Parameters

format
string · queryone of json, csvExport format.
page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. The server caps this.

Request body

No request body.

Responses

Texting registration 7

GET/api/v1/registration/brandRead texting brand-registration statusregistration:read

This organization's stored 10DLC brand filing state, the one-time brand filing fee, the organization balance, and whether the credential is the active, fully-set-up owner (role-and-setup eligibility only; not spending authority). It is the locally stored state, not a live carrier reconciliation, and never returns carrier identifiers, raw payloads, verification tokens, or a full EIN. Paid brand submission is available through POST /api/v1/registration/brand when the credential holds registration:submit and the active organization owner has completed setup; owner_and_setup_eligible here is role-and-setup eligibility only, not a credential grant. Files nothing, charges nothing, creates no profile, assigns no number; one routine API audit row is recorded. Scope registration:read.

getBrandRegistration

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/registration/brandFile a texting brand registrationregistration:submitIdempotency-Key

Owner-only 10DLC brand filing. Only the active, fully-set-up organization owner may file; an admin cannot file. It charges the non-refundable one-time brand filing fee from the server (never the caller), builds the exact packet from the saved identity and the credential owner's own representative fallbacks, and requires confirm-equivalent fee_acknowledged, a bounded Idempotency-Key header, and scope registration:submit. A repeat with the same packet and key is already on file and charges nothing; an uncertain carrier outcome is never retried blindly. Send the same brand fields to POST /agent/approvals when this key requires an operator approval, then pass the returned id as approvalId.

submitBrandRegistration

Request, parameters and responses

Parameters

Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · BrandSubmitRequest

legal_business_name
stringLegal business name. Omit to use the saved value.
ein
stringNine-digit EIN. Omit to use the saved value.
street_address
string
street_address2
string
city
string
state
string
postal_code
string
website
stringSend an empty string to clear it; omit to use the saved value.
authorized_rep_name
string
authorized_rep_email
stringformat=email
authorized_rep_phone
string
fee_acknowledgedrequired
booleanMust be true: acknowledges the non-refundable one-time brand filing fee.
approvalId
stringOptional spend approval id for a key that requires an operator to approve each filing.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/registration/brand/previewPreview texting brand-registration validationregistration:read

Validate would-be brand filing details against the saved settings and return the required fixes and the authoritative filing fee, exactly like the dashboard's business-information step. Omitted fields fall back to the saved value or the credential owner's own details; an empty string clears a value. Validation only: it reserves nothing, writes no business or billing state, charges nothing, and guarantees no carrier acceptance; one routine API audit row is recorded. The response's `ready` flag means the packet passed field validation only, not that the organization is already filed, permitted, or funded. Paid submission is available through POST /api/v1/registration/brand. Scope registration:read.

previewBrandRegistration

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · BrandPreviewRequest

legal_business_name
stringLegal business name. Omit to use the saved value.
ein
stringNine-digit EIN. Omit to use the saved value.
street_address
string
street_address2
string
city
string
state
string
postal_code
string
website
stringSend an empty string to clear it; omit to use the saved value.
authorized_rep_name
string
authorized_rep_email
stringformat=email
authorized_rep_phone
string
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/registration/campaignRead texting campaign-registration readinessregistration:read

Owner or admin only, matching the dashboard's campaign surface. This organization's stored 10DLC campaign-registration readiness: the current filing status, rejection and retry notes, the frozen filed packet, the resumable draft, the persisted free site-check history, the authoritative campaign review fee, and whether setup is complete. It is the locally stored state, not a live carrier reconciliation, and never returns carrier identifiers, raw provider payloads, verification tokens, or the raw registration row; your own brand names, URLs, and copy are preserved verbatim. already_filed means a carrier campaign reference is recorded, not approval or delivery, and a missing reference does not prove no filing occurred; confirmation_required or submitting mean an existing attempt must not be filed again, and none of these flags establish whether a fee was charged. Paid campaign filing is available through submit_texting_campaign_registration (POST /api/v1/registration/campaign/submit) when the credential holds registration:submit. It files nothing, charges nothing, creates no profile, assigns no number; one routine API audit row is recorded. Scope registration:read.

getCampaignRegistration

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/registration/campaign/site-checkRun the free campaign website preflightregistration:prepare

Owner or admin only, and the organization must be fully set up. Free website-compliance preflight for this organization's campaign: validate opt_in_url, privacy_policy_url, terms_url (optional opt_in_screenshot_url), fetch the live public pages, return the same carrier checklist the paid submit enforces, and append one immutable history row stamped with the organization and check time. It makes outbound reads of your public pages and appends history, so a repeat is a new timestamped record rather than a no-op. A failed history write is surfaced as an error, never presented as durable evidence. It charges nothing, files nothing with any carrier, creates no profile, and assigns no number. Scope registration:prepare.

checkCampaignSite

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · CampaignSiteCheckRequest

opt_in_urlrequired
stringPublic https URL of the SMS opt-in form on your campaign website.
privacy_policy_urlrequired
string
terms_urlrequired
string
opt_in_screenshot_url
string
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

PUT/api/v1/registration/campaign/draftSave a texting campaign compliance draftregistration:prepare

Owner or admin only, and the organization must be fully set up. Saves this organization's texting campaign compliance draft: opt_in_url, privacy_policy_url, terms_url, and the optional opt_in_screenshot_url, opt_in_description, help_email. It writes the same draft the paid filing later reads. A supplied field is written, an omitted field keeps its stored value, and an empty string clears a saved value. A supplied help_email must be a valid address, and an empty one never erases the stored shared inbox. An opt_in_description that does not name your form, privacy, and terms URLs plus STOP and HELP is refused. It is free: it charges nothing, files nothing with any carrier, creates no profile, and assigns no number, and it records one routine API audit row. The free preflight is POST /registration/campaign/site-check and the paid filing is POST /registration/campaign/submit. Scope registration:prepare.

saveCampaignDraft

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · CampaignDraftRequest

opt_in_url
stringPublic https URL of the SMS opt-in form on your campaign website. An empty string clears the saved value.
privacy_policy_url
stringPublic https URL of the privacy policy. An empty string clears the saved value.
terms_url
stringPublic https URL of the terms of service. An empty string clears the saved value.
opt_in_screenshot_url
stringOptional public https URL of an opt-in screenshot. An empty string clears the saved value.
opt_in_description
stringHow a person opts in. It must name the form, privacy, and terms URLs plus STOP and HELP, or it is refused. An empty string clears the saved value.
help_email
stringformat=emailOptional HELP reply contact. A supplied value must be a valid address, and an empty value never erases the stored shared inbox.
expected_volume
stringOptional expected monthly message volume.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/registration/campaign/submitFile the texting campaign registrationregistration:submitIdempotency-Key

Owner or admin only, and the organization must be fully set up. Files this organization's 10DLC campaign registration and charges the non-refundable review fee for this submission from the server, never the caller. It requires confirm-equivalent compliance_acknowledged true and fee_acknowledged true, a bounded Idempotency-Key header, and scope registration:submit. Before any fee is charged it validates the saved draft, fetches the three filed public pages, and runs the same carrier checklist as POST /registration/campaign/site-check; it then reconciles the stored filing state and fails closed with 409 when an existing attempt cannot be interpreted, so an uncertain outcome is never retried blindly. When the business registration is not yet approved it saves the draft as queued and charges nothing. A repeat with the same idempotency_key is already on file and charges nothing. Send the same filing to POST /agent/approvals first when this key requires an operator approval, then pass the returned id as approval_id.

submitCampaignRegistration

Request, parameters and responses

Parameters

Idempotency-Keyrequired
string · headerUnique key for this attempt. Letters, numbers, and . _ : - are accepted. Reuse the same key to retry a request that may have been accepted.

Request body

application/json · CampaignSubmitRequest

compliance_acknowledgedrequired
booleanMust be true: acknowledges the messaging compliance requirements of the filing.
fee_acknowledgedrequired
booleanMust be true on a fresh filing: acknowledges the non-refundable review fee charged for this submission. A retry on an already-charged filing skips it.
confirmrequired
booleanMust be true: confirms the filing itself. The review fee is non-refundable per submission.
idempotency_key
stringOptional here: the bounded Idempotency-Key header is the canonical form. A repeat with the same key is already on file and charges nothing.
help_email
stringformat=emailOptional HELP reply contact for this filing. Omit to use the saved one.
campaign_verify_token
stringOptional Campaign Verify token for a political organization that needs one. Omit to use the saved token.
approval_id
stringOptional spend approval id for a key that requires an operator to approve each filing.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Billing 4

GET/api/v1/billing/balanceRead organization fundsbilling:read

The real available balance (active holds already deducted) and the outstanding held reservations as a separate number; holds are never subtracted twice. A failed read is an error, not a zero. Active owner or admin. Read-only; charges nothing and creates no payment profile. Scope billing:read.

getBillingBalance

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

GET/api/v1/billing/transactionsPage the organization ledgerbilling:read

Newest first, bounded offset/limit, exact total and has-more. Returns the public ledger id, type, whole-cent amount, running balance, description, and timestamp only, with no processor identifiers, idempotency keys, metadata, or another member's private settings. Active owner or admin. Scope billing:read.

listBillingTransactions

Request, parameters and responses

Parameters

offset
integer · queryHow many newest entries to skip.
limit
integer · queryPage size. The server caps this.

Request body

No request body.

Responses

GET/api/v1/billing/auto-topupRead Auto Top-Up configurationbilling:read

The saved automatic-replenishment configuration for this organization, including the saved card's brand, last 4 digits, and expiry, and never a card number or identifier. Active owner or admin. Scope billing:read.

getAutoTopUpSettings

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

POST/api/v1/billing/auto-topupSave Auto Top-Up configurationbilling:write

Saves the configuration exactly like Account, Auto Top-Up. enabled true authorizes future automatic charges against the already-saved, already-authorized card per the threshold, amount, daily caps and cooldown; it does not charge now, add or remove a card, or deposit funds. Enabling requires a card already on file. The trigger balance is 500–100000 cents and the amount is 1000–100000 cents, whole cents. Saving the same configuration twice is the same as once. Active owner or admin. Scope billing:write.

updateAutoTopUpSettings

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · BillingAutoTopUpUpdate

enabledrequired
boolean
thresholdCentsrequired
integermin=500, max=100000
amountCentsrequired
integermin=1000, max=100000
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Audit log 1

GET/api/v1/audit-logRead this organization's audit loglogs:read

This organization's audit log, newest first: actions taken with API keys and connected agents, plus every paid or bulk action from any source (dashboard, API, MCP, cron, import). Paid and bulk actions are list cleaning and email or address verification, campaign launches, phone number and 10DLC purchases, balance holds and contact imports. Each of those entries is written when the action starts (or is blocked) and updated with its outcome, and carries source, outcome, estimated and actual cost in cents, the target list or segment (ids and names), counts (requested, processed, succeeded, failed), started_at, finished_at and the request id. Filter by action, source, outcome, actor_user_id, key_id (an API key id), request_id, paid_only, since and until. Entries never contain contact emails, phone numbers, addresses or message bodies. Always scoped to the credential's organization. Read-only: records one routine audit row. Scope logs:read.

listAuditLog

Request, parameters and responses

Parameters

page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. The server caps this.
action
string · queryOnly this action, such as email_verification.run. End with * to match a prefix, such as campaign_launch.*.
source
string · queryone of ui, api, mcp, cron, import, systemOnly entries started from this source.
outcome
string · queryone of started, succeeded, partial, failed, blockedOnly paid or bulk actions with this outcome.
actor_user_id
string · queryOnly entries by this user.
key_id
string · queryOnly entries made with this API key.
request_id
string · queryOnly entries from this request id.
paid_only
boolean · querytrue returns only paid and bulk actions (list cleaning, verification, launches, purchases, balance holds, imports).
since
string · queryEntries at or after this ISO 8601 time.
until
string · queryEntries before this ISO 8601 time.

Request body

No request body.

Responses

Profile 2

GET/api/v1/profileRead your own personal profile and preferencesprofile:read

Reads the credential owner's OWN personal profile and preferences: full name, personal phone with its normalized readback, time zone, country, default sender name and addresses, SMS signature, quiet hours, opt-in preferences, and notification preferences. The effect is user-wide: these settings belong to the person across every organization they belong to, not to one organization. Only the owner's own row is returned; roles, administrator flags, balances, credentials, and secrets never are. Scope profile:read.

getPersonalSettings

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

PATCH/api/v1/profileSave your own personal profile and preferencesprofile:write

Owner or admin only. Changes the credential owner's OWN personal profile and preferences (user-wide across every organization they belong to). Only the fields you pass are changed; an omitted field keeps its stored value and an empty string or null clears a string field. A saved phone is normalized but NOT verified, provisioned, or rung. Notification preferences govern future alerts only: saving them does not send, schedule, or charge, and the low-balance threshold is an alert threshold, not a spending limit. It cannot change email/login identity, password, MFA, verification flags, role, membership, organization selection, administrator flags, balance, spending authorization, or API credentials. Scope profile:write.

updatePersonalSettings

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · PersonalSettingsUpdate

fullName
string | nullnullable
personalPhone
string | nullnullable
timezone
string | nullnullable
country
string | nullnullable
defaultFromName
string | nullnullable
defaultFromEmail
string | nullnullable
defaultReplyToEmail
string | nullnullable
defaultSmsSignature
string | nullnullable
quietHoursEnabled
boolean
quietHoursStart
string | nullnullable
quietHoursEnd
string | nullnullable
optInMethods
array | nullnullable
optInDescription
string | nullnullable
billingContactEmail
string | nullnullable
lowBalanceThresholdCents
integermin=0
usageNotificationsEnabled
boolean
dailySpendAlertsEnabled
boolean
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Intake 2

POST/api/v1/intake/form-submissionsRecord a website form submission as a contactintake:write

The versioned equivalent of the legacy website endpoint POST /api/intake/form-submission, using the SAME parser and consent/suppression engine. Creates or updates one contact inside the credential's organization; sends nothing and charges nothing. Provide an email, a phone, or both, and a source. A checked opt-in box needs its verbatim consent text; an unchecked box withholds that channel. A dated opt-out, a STOP, or a live suppression is never cleared. A body that names a tenant or user selector (organizationId/orgId/org_id/userId/user_id) is refused, not stripped. The contact and its receipt commit in ONE serialized transaction: returns 201 created, 200 updated, or 200 duplicate when the same externalId was already accepted, where a duplicate replays the FIRST accepted receipt without a second mutation. A stored receipt is the historical outcome of the first write, not proof the contact still matches the request (later legitimate edits can change it); a receipt written before the atomic cutover may reflect the old two-step path, and an interrupted keyed retry is not auto-resent; read the receipt first. When an existing email contact and an existing phone contact are two different people, returns 409 identity_conflict with neither contact changed. Scope intake:write.

recordFormSubmission

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · FormSubmissionRecord

email
stringEmail address, stored lowercased.
phone
stringU.S. phone number, stored as E.164.
firstName
string
lastName
string
street
string
city
string
state
string
zip
string
postalCode
stringPostal-code alias accepted when zip is omitted.
sourcerequired
stringShort form name such as volunteer, membership, contact, newsletter, or event.
emailOptIn
boolean
smsOptIn
boolean
emailConsentText
stringThe email checkbox label, verbatim, 3 to 2000 characters.
smsConsentText
stringThe text checkbox label, verbatim, 3 to 2000 characters.
optInIpAddress
string
optInAttestation
boolean
locale
string
submittedAt
stringformat=date-time
externalId
stringStable id, up to 128 characters. Reusing it replays the FIRST accepted submission instead of writing again; the contact and its receipt commit atomically, so a concurrent duplicate never re-mutates the contact. An interrupted keyed retry is not auto-resent; read the receipt for this externalId first.
attributes
object<string, string | number | boolean>additionalProperties: string | number | booleanUp to 40 extra fields as text, number, or boolean values.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

GET/api/v1/intake/form-submissions/{externalId}Read a stored form-submission receiptintake:write

Read the persisted receipt of a past submission by the externalId it was sent with, inside the credential's organization; the id is organization-scoped and never selects an organization. Returns a created/updated/duplicate receipt, or an identity_conflict receipt naming both contacts that were left unchanged. A missing receipt is 404; absence does NOT prove that no write occurred, because the contact can be written before its receipt is saved. The receipt is the historical outcome of the first accepted write, not proof that the current contact matches the request. A read failure is an error, never a synthesized success. Read-only; changes nothing. Scope intake:write.

getFormSubmission

Request, parameters and responses

Parameters

externalIdrequired
string · pathThe external id of a past form submission, organization-scoped.

Request body

No request body.

Responses

Calling 2

GET/api/v1/calling/campaignsList the calling queues you may workcalls:read

Scope calls:read. Returns the credential organization's prepared calling campaigns with a pending queue, plus this member's OWN active or paused shift session id per queue. The campaign list is organization-wide, not an individual assignment, and only the shift session id is personal. A pending_count of null means the count could not be read (unavailable), not zero, truncated reports whether more campaigns could exist than were read, and shiftsTruncated reports whether this member's own shift page was capped (so a null session_id is not proof of no open shift). It reads no balance, sender identity, contact or audience inventory, and changes no business state (the read records one routine audit row). Member calling-workspace connection.

listMyCallingCampaigns

Request, parameters and responses

Parameters

No parameters.

Request body

No request body.

Responses

PATCH/api/v1/calling/phoneSave your own operator phonecalls:operate

Scope calls:operate. Saves the credential owner's OWN operator phone. The body carries only phone; a caller-supplied user or organization selector is refused, and an unknown field is rejected. The number is normalized but is NOT verified, provisioned, or rung, and this places no call and moves no money. It returns only whether a phone was set and its last four digits. Member calling-workspace connection.

updateMyCallingPhone

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · CallingPhoneUpdate

phonerequired
stringYour operator phone as a U.S. number. Normalized but not verified.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Team 9

GET/api/v1/team/membersList the authorized organization's team rosterteam:read

Scope team:read. Owner/admin only, on an ACTIVE credential membership (a read-only organization state such as a locked organization stays readable; a suspended or removed membership does not). The organization is the one that owns the credential, never a request selector. Authorization is canonical: each member's role and status come from that organization's membership row, not from the member's own selected organization, and a removed canonical member is not restored from a stale profile pointer. The projection is narrow (member id, email, display name, canonical role/status, membership timestamps, protected-owner flag): no balances, no platform-admin flags, no secrets, no other organization's membership. Bounded page with page/limit; total is the true number of members, not one page's length. Read-only: records one routine audit row and changes no business state. Inviting, re-queuing, or cancelling an invitation and changing, suspending, reactivating, or removing an ordinary member are the separate team:manage operations.

listTeamMembers

Request, parameters and responses

Parameters

page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. The server caps this.

Request body

No request body.

Responses

GET/api/v1/team/invitationsList the authorized organization's current pending invitationsteam:read

Scope team:read. Same canonical owner/admin authentication and ACTIVE-membership requirement as the roster. Returns only the CURRENT pending invitations (this organization, not accepted, not cancelled, not dismissed, not expired), newest first, with id, email, role, created_at and expires_at. It never returns an invitation token or copy-link value, never the history of past or accepted invitations, and sends or resends nothing. Bounded page with page/limit; total is the true count. Read-only: records one routine audit row and changes no business state.

listTeamInvitations

Request, parameters and responses

Parameters

page
integer · queryPage number, starting at 1.
limit
integer · queryPage size. The server caps this.

Request body

No request body.

Responses

POST/api/v1/team/invitationsInvite a person to the organizationteam:manage

Invites one person to the credential's organization as admin, member, or volunteer, using the same invitation workflow the dashboard uses. The acting organization and inviter come only from the credential; the body accepts only email and role. A person who already has a membership of any status is refused (reactivate instead); a live pending invitation returns a conflict. The response exposes only safe invitation metadata and a `queued` acknowledgment indicating a source email event was written, NOT proof of delivery. Creates no organization, grants no role, moves no money, returns no invite token. Ordinary owner/admin authority; platform superuser alone is not authority. Scope team:manage.

createTeamInvitation

Request, parameters and responses

Parameters

No parameters.

Request body

application/json · TeamInvitationCreate

emailrequired
stringformat=emailInvitee email address. Normalized to lower case.
rolerequired
stringone of admin, member, volunteerThe role the invitee will hold if they accept.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/team/invitations/{id}/resendRe-queue a pending invitation emailteam:manage

Re-queues the invitation email for a still-pending invitation in the credential's organization. NOT idempotent: there is no request-key store and each call is a new email request, exactly like the dashboard's re-queue action. Sends no email itself and moves no money. If the outcome cannot be confirmed, read the current invitation state rather than retrying automatically. Scope team:manage.

resendTeamInvitation

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

POST/api/v1/team/invitations/{id}/cancelCancel a pending invitationteam:manage

Cancels a still-pending invitation in the credential's organization; the person can be invited again afterwards. Cancelling an invitation that is already accepted, cancelled, or dismissed is refused. Sends nothing and moves no money. Scope team:manage.

cancelTeamInvitation

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

PATCH/api/v1/team/members/{id}Change a member's roleteam:manage

Changes an ordinary member's role between admin and member in the credential's organization. The target is the path id; the body accepts only role. Promotion to owner is refused, the organization owner cannot be changed, and you cannot change your own role. The result is the live membership read back; an unconfirmable readback is reported as uncertain, not as success or a proven no-write. Scope team:manage.

changeTeamMemberRole

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · TeamMemberRoleUpdate

rolerequired
stringone of admin, memberThe member's new role. Promotion to owner is not accepted.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

DELETE/api/v1/team/members/{id}Remove an ordinary memberteam:manage

Removes an ordinary member from the credential's organization, ending their membership. The organization owner cannot be removed, you cannot remove yourself, and the last active admin cannot be removed. An optional note is recorded on the audit trail. Removes a membership only: it does not delete the account, transfer data, or move money. Scope team:manage.

removeTeamMember

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · TeamMemberNote

note
stringOptional note recorded on the team audit trail.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/team/members/{id}/suspendSuspend an ordinary memberteam:manage

Suspends an ordinary active member in the credential's organization, dropping them to read-only. The organization owner cannot be suspended, you cannot suspend yourself, and the last active admin cannot be suspended. An optional note is recorded on the audit trail. The result is the live membership read back. Scope team:manage.

suspendTeamMember

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · TeamMemberNote

note
stringOptional note recorded on the team audit trail.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

POST/api/v1/team/members/{id}/reactivateReactivate a suspended memberteam:manage

Reactivates a suspended member in the credential's organization. The organization owner cannot be acted on and you cannot reactivate yourself. A member who is not suspended is refused. An optional note is recorded on the audit trail. The result is the live membership read back. Scope team:manage.

reactivateTeamMember

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

application/json · TeamMemberNote

note
stringOptional note recorded on the team audit trail.
Complete request schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Responses

Campaigns 1

GET/api/v1/campaigns/{id}/reportRead clicks, conversions, and throughputconversions:write

Human clicks by link, conversion counts and dollars, throughput, and the channel so email and SMS can be compared. A campaign with no conversions is zero. Clicks are null when the campaign is not email or text. Scope conversions:write. Email, phone, and tokens are not returned.

getCampaignReport

Request, parameters and responses

Parameters

idrequired
string · pathCampaign Commander id for this resource.

Request body

No request body.

Responses

Scopes & permissions

Scopes determine what a credential may call. A missing scope is a hard stop: the handler is not invoked, and the action does not run. Recovery depends on the credential, and is never a silent widening or a blind retry.

  • OAuth: for an eligible active, full-access actor, the server returns the standard HTTP 403 insufficient-scope challenge, and a capable host can begin a new, explicit, user-approved consent for the complete tool-required scope set advertised by the challenge and tool metadata, retaining already-granted permissions still needed for the authorized job rather than requesting only the missing subset. An optional tool hint supplements and never replaces that standard signal.
  • API key: an authorized owner or admin mints a new key with that scope and stores it only in a masked secret store, a vault, or the environment. Existing grants are frozen: an older key keeps only the scopes it originally had and is never widened in place.
  • Denied: a call outside the role ceiling, or from an actor that is not active and full-access, remains a plain refusal rather than a fabricated permission prompt or an invitation to reconnect.
email:readRead email campaigns and drafts
email:draftCreate and edit email drafts and their audiences
email:testSend one email test
email:sendSend and schedule live email
email:transactionalSend one-off transactional email and manage its templates
agent:runsCreate and update this credential's work runs
lists:readRead, preview, and resolve saved audiences
lists:writeCreate, edit, and change membership of saved lists
contacts:readRead and search contacts, and read the contact-field registry
contacts:writeCreate and update contacts, tags, channel consent, and contact-field definitions
sms:readRead text campaigns, recipients, and outcomes
sms:draftCreate and edit text drafts and preview audiences
sms:testSend one text test
sms:sendSend and schedule live text
voice:readRead voice campaigns, calls, numbers, and dialer sessions
voice:draftCreate voice drafts, upload assets, and open dialer sessions
voice:sendPlace calls and advance dialer sessions
calls:readList the prepared calling queues you may work, and your own active or paused shift
calls:operateSave your own operator phone in the member calling workspace
mail:readRead physical-mail campaigns and preview audiences
mail:draftCreate physical-mail drafts
mail:sendLaunch a physical-mail campaign
email:verifyQuote and run email verification
address:verifyQuote and run postal address verification
settings:readRead sender and organization settings
settings:writeSave organization settings
profile:readRead your own personal profile and preferences
profile:writeSave your own personal profile and preferences
suppression:readRead do-not-contact records
suppression:writeRecord or override do-not-contact records
logs:readRead delivery events and the audit log
conversions:writeRecord a conversion
intake:writeAccept a website form submission as a contact
exports:readExport contacts
inbox:readRead inbox conversations for reply triage
registration:readRead texting brand registration status and preview a would-be filing
registration:prepareRead campaign-registration readiness and run the free campaign website-compliance preflight
registration:submitRequest approval for and submit a paid texting brand registration
billing:readRead organization funds, ledger transactions and saved Auto Top-Up settings
billing:writeConfigure Auto Top-Up against an already-authorized saved card; enabling permits future automatic charges
team:readRead the organization team roster and its current pending invitations
team:manageInvite, re-queue, and cancel team invitations, and change, suspend, reactivate, or remove an ordinary (non-owner) team member

An empty scope list means any valid credential, not a public endpoint. A public operation is one whose route answers without a credential, which is a separate property.

intake:write is for website form submissions, not for a route under /api/v1. billing:read only reads funds, the ledger and saved Auto Top-Up settings; enabling Auto Top-Up needs billing:write and permits future automatic charges.

Side effects & confirmation

Confirmation is declared by each tool, not applied uniformly. A tool whose catalog entry sets requiresConfirmation refuses to run unless the call carries confirm: true and a well-formed idempotency_key. A tool without that flag is not thereby read-only.

22 tools declare a confirmation gate, including send_email_campaign, test_email_campaign, schedule_email_campaign, unschedule_email_campaign, test_sms_campaign, send_sms_campaign, schedule_sms_campaign, unschedule_sms_campaign, create_mail_draft, launch_mail_campaign and others listed in the tool reference. Confirmation is a decision the agent reaches with the operator in conversation, not a login and not a replacement for authentication. The underlying route still applies billing, suppression, consent and do-not-contact rules.

  • There is no blanket consent screen and no agent-only approval gate. Authentication and granted scopes authorize actions directly.
  • A key whose owner configured a standing spend limit may route a paid action through the existing approval policy; without a configured limit the action runs directly under its scope.

Missing confirm is not missing effect

A tool that declares no confirm gate is not necessarily read-only. Follow its declared side effects, and never assume that the absence of a confirmation flag means nothing financial happens.

Idempotency & readback

The two surfaces express idempotency differently. Do not generalize one route's rules onto every route.

  • REST: an operation that accepts an Idempotency-Key header declares it in its own schema, with the accepted length and character set. Send it on the retryable charge or send, and reuse the same value when you retry that same attempt.
  • MCP: a tool whose catalog entry sets requiresConfirmation requires confirm: true and a 16-128 character idempotency_key argument.

A key is not an unlimited replay guarantee: preserve it for retries of the same operation and follow the tool's documented replay window. Never retry a paid or irreversible action blindly. Read the resource back first. An async 202 means the request was accepted, not delivered.

Configuration reads may themselves record an audit row. Sends that are accepted or queued are not yet delivered. Pagination is per operation: consult each operation's schema. Some list routes take page and limit; the billing ledger takes offset and limit, for example GET /api/v1/billing/transactions?offset=0&limit=50.

Errors & rate limits

400The body or query is invalid.
401The key is missing or invalid.
403The key lacks a scope, the role is insufficient, or organization setup is incomplete.
404That record is not in this organization.
409Duplicate, or the campaign is no longer a draft.
402The organization balance is too low.
429Too many requests. Wait and retry.
500Campaign Commander could not finish the request.
502 or 503The outcome is uncertain. Do not blindly retry a send; read it back.

Routes under /api/ allow 100 requests per 60 seconds per IP; a 429 body includes retryAfter, limit and resetAt. Reading the public OpenAPI document is not under that limit. Transactional email on a new organization is also limited to 10 per minute and 200 recipients per day.

Error responses

Every endpoint that lists one of these statuses returns this body. Endpoints link here instead of repeating it. An endpoint with a different error body documents that body on the endpoint itself.

400
Invalid requestDocumented on 153 operations · Error
401
Missing or invalid API keyDocumented on 154 operations · Error
402
Organization balance is too lowDocumented on 154 operations · Error
403
The key lacks the required scope, or organization setup is incompleteDocumented on 154 operations · Error
404
Not foundDocumented on 154 operations · Error
409
Conflict, such as a duplicate contact or a campaign that is no longer a draftDocumented on 154 operations · Error
429
Rate limit exceededDocumented on 154 operations · Error
500
Campaign Commander could not complete the requestDocumented on 153 operations · Error
Complete error schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

What a send costs

Email$1 / 1,000, minimum 1¢
Short text3¢
Long text or picture6¢
Call or voicemail6¢ per connected started minute. Ringing is free.
Postcard 4x6$1.19
Postcard 6x9$1.35
Postcard 6x11$1.69
Letter$1.59

Prices are read from the same constants the product bills from. Read them live from the capabilities response before you spend.

MCP server

Campaign Commander speaks the Model Context Protocol over stateless Streamable HTTP. One request builds a server, handles one JSON-RPC message and returns JSON.

EndpointPOST https://www.campaigncommanderapp.com/api/mcp
TransportStateless Streamable HTTP: no session to resume
Methodsinitialize, tools/list, tools/call, resources and prompts
GET / DELETE405: a GET is not a readiness probe
AuthOAuth 2.1 (preferred self-service flow), or an existing bearer API key

Start with initialize, then tools/list, then tools/call with get_capabilities and empty arguments. That last call is a dry read.

cURL · initializeread-only
# One JSON-RPC message per POST. There is no session to resume.
: "${CC_API_KEY:?export CC_API_KEY from your secret manager first}"

curl -fSs https://www.campaigncommanderapp.com/api/mcp \
  -H "Authorization: Bearer $CC_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{
        "protocolVersion":"2025-06-18","capabilities":{},
        "clientInfo":{"name":"my-agent","version":"0.0.0"}}}'

Tool reference

134 MCP tools, derived from the live tool catalog. Each delegates to the matching Agent API handler in-process, so authentication, scopes, tenant isolation, billing, suppression and consent stay where they already are.

Capabilities & discovery 1

get_capabilitiesread-onlyany valid credential

Read the scopes granted to this API key and the Agent API actions those scopes allow. Call this first when you are unsure what this key can do. It changes no business state (the read records one routine audit row).

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Contacts 15

list_contactsread-onlycontacts:read

Search contacts in this organization by name, email, or phone, or look one up by an exact email or phone. With q, tag, or neither, returns a page of contacts, sorted by sort_by/sort_order (created_at, first_name, last_name, email, or phone) and optionally filtered to those that have an email, phone, or address on file. A presence filter means only that the field is not NULL in the database; a blank value still counts, and it is not a claim that the value is verified, deliverable, or opted in. An exact email or phone returns one contact and does not apply q, tag, sort_by, sort_order, filter_type, page, or limit; supplied enum selectors are still validated. Omit selectors for defaults rather than passing an empty string. When the database does not provide an exact count, total and hasMore are null (unknown), not proof the list has ended. Does not return mailing addresses.

Input schema and example

Arguments

q
stringSearch name, email, or phone. At most 100 characters.
email
stringExact email address. Returns one contact, or an error when none matches.
phone
stringExact U.S. phone number. It is normalized before lookup.
tag
stringOnly contacts that have this tag.
sort_by
stringone of created_at, first_name, last_name, email, phoneSort field for the paginated list. Defaults to created_at.
sort_order
stringone of asc, descSort direction for the paginated list. Defaults to desc.
filter_type
stringone of all, email, phone, addressKeep only contacts whose named field is present (not NULL). all, the default, applies no filter.
page
integermin=1Page number, starting at 1.
limit
integermin=1, max=50Page size. At most 50.

Example arguments

{
  "q": "ada",
  "sort_by": "created_at",
  "sort_order": "desc",
  "filter_type": "email",
  "page": 1,
  "limit": 25
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_contactread-onlycontacts:read

Read one contact in this organization by id. Returns an error when the contact is not in this organization. Does not return a mailing address.

Input schema and example

Arguments

contact_idrequired
stringContact id.

Example arguments

{
  "contact_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
create_contactcontacts:write

Add one contact to this organization. Provide at least a name, email, phone, or mailing address. A duplicate email returns the existing contact instead of creating a second one. A do-not-email address is refused unless override_suppression is set with a note. Mailing address fields are the four postal columns only; verification fields cannot be set. This does not send anything.

Input schema and example

Arguments

first_name
stringFirst name. At most 120 characters.
last_name
stringLast name. At most 120 characters.
email
stringEmail address. Normalized to lower case.
phone
stringU.S. phone number. Normalized to E.164.
address
string | nullnullableStreet address. Trimmed; a partial address is allowed.
city
string | nullnullableCity. Trimmed.
state
string | nullnullableState. Trimmed and upper-cased.
zip
string | nullnullableZIP code as text. A leading zero is kept.
notes
stringFree-form notes. At most 5,000 characters.
tags
array<string>Up to 25 tags.
custom_fields
object<string, string | number>additionalProperties: string | numberFlat custom-field values: a map of field name to a text or number value. Names are trimmed to 100 characters and values to 2,000; a number is stored as text. Nested objects and arrays are not stored. This sets values on a contact; it does not define or type fields.
override_suppression
booleanOnly for an overridable do-not-email entry. Requires override_note.
override_note
stringWhy a suppression is being overridden. Required with override_suppression.

Example arguments

{
  "first_name": "Ada",
  "last_name": "Lovelace",
  "email": "ada@example.org",
  "tags": [
    "volunteer"
  ],
  "custom_fields": {
    "precinct": "12"
  }
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
update_contactcontacts:write

Change fields on one contact in this organization by id. Only the fields you pass are changed. The mailing address fields are the four postal columns only; verification fields cannot be set. Returns not found when the contact is not in this organization. This does not send anything.

Input schema and example

Arguments

contact_idrequired
stringContact id.
first_name
stringNew first name.
last_name
stringNew last name.
email
stringNew email address.
phone
stringNew U.S. phone number.
address
string | nullnullableNew street address. Pass null or an empty string to clear it.
city
string | nullnullableNew city. Pass null or an empty string to clear it.
state
string | nullnullableNew state. Trimmed and upper-cased.
zip
string | nullnullableNew ZIP code as text. A leading zero is kept.
notes
stringNew notes.
tags
array<string>Replacement tag list, up to 25.
custom_fields
object<string, string | number>additionalProperties: string | numberFlat custom-field values: a map of field name to a text or number value. Names are trimmed to 100 characters and values to 2,000; a number is stored as text. Omitted leaves the stored values unchanged; an empty object clears them all. This replaces the whole map, not one field, and does not define or type fields.

Example arguments

{
  "contact_id": "11111111-1111-4111-8111-111111111111",
  "notes": "Prefers texts"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
add_contact_tagscontacts:write

Add up to 25 tags to one contact in this organization by id. Existing tags are kept. Suppression and system verdict tags cannot be set this way.

Input schema and example

Arguments

contact_idrequired
stringContact id.
tagsrequired
array<string>Tags to add, up to 25.

Example arguments

{
  "contact_id": "11111111-1111-4111-8111-111111111111",
  "tags": [
    "door-knocked"
  ]
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
remove_contact_tagscontacts:write

Remove up to 25 tags from one contact in this organization by id. Only the named tags are removed; the rest of the tag list is kept. Removing a tag the contact does not have is a no-op. Suppression and system verdict tags cannot be changed this way. This removes ordinary tags only; it does not replace the whole tag list.

Input schema and example

Arguments

contact_idrequired
stringContact id.
tagsrequired
array<string>Tags to remove, up to 25.

Example arguments

{
  "contact_id": "11111111-1111-4111-8111-111111111111",
  "tags": [
    "volunteers"
  ]
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
preview_contact_importcontacts:read

Parse and preview a CSV/XLSX contact or suppression import before anything is committed. Returns the per-tab classification, exact row counts, unresolved metadata decisions, global-suppression matches, and a signed preview token. Requires contacts:read. Writes preview evidence only, changes no contacts, and charges nothing. Send the same files back to commit_contact_import with the token.

Input schema and example

Arguments

filesrequired
array<object>One or more CSV or XLSX files, each as base64 in content_base64. An MCP call IS a deployed function request, so the files travel base64-encoded inside one JSON body bounded by that function's 4.5 MB limit: the aggregate decoded size is capped near 2.6 MiB and a single file larger than that is refused. A whole-file upload too large to inline can instead be sent in chunks with stage_contact_import_upload and referenced by its staging id. No file path or URL is accepted.
plan
array<object>Per-tab decisions from a prior preview. Each entry pins a tab (by key, or by name for older previews) to role contacts/suppression/ignore, chooses suppression channels, and maps columns. Omit to accept the automatic classification.
tags
array<string>Tags to apply to every imported contact.
token
stringA prior preview token, to reuse the frozen classification instead of re-running the classifier.
review_choices
objectadditionalProperties: allowedAnswers for the metadata classifier's uncertain decisions, keyed '<evidenceId>'. Each value is 'suppress' or 'none'. Commit is refused while any decision is unresolved.
sms_consent_attested
booleanOperator attests the file carries SMS consent for the phone numbers it imports.
voice_consent_attested
booleanOperator attests the file carries voice-call consent for the phone numbers it imports.
clean_emails
booleanAsk to clean imported emails. Requires the email:verify scope. The commit saves contacts and does NOT clean or charge inline: cleaning exactly this import's contacts is a separate paid step, clean_import_cohort, keyed by the cohortId the commit returns. Requesting it here records the intent and reports it as requested and not performed.
clean_addresses
booleanAsk to clean imported addresses. Requires the address:verify scope. The commit saves contacts and does NOT clean or charge inline: cleaning exactly this import's contacts is a separate paid step, clean_import_cohort, keyed by the cohortId the commit returns. Requesting it here records the intent and reports it as requested and not performed.

Example arguments

{
  "files": [
    {
      "filename": "voters.csv",
      "content_base64": "RW1haWwsUGhvbmUKYWRhQGV4YW1wbGUub3JnLDg2MzU1NTAxMDAK"
    }
  ],
  "tags": [
    "canvass"
  ]
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
commit_contact_importcontacts:write

Commit a previously previewed import. Requires contacts:write; cleaned emails or addresses additionally require email:verify or address:verify and are refused before any contact is written if missing. The commit saves contacts and charges nothing, even when cleaning is requested: cleaning exactly this import's contacts runs as a SEPARATE paid step, clean_import_cohort, keyed by the cohortId the response carries. The response's `cleaning` block reports the requested channels as requested and NOT performed by this commit. Re-sending an unchanged commit with the same preview token replays the stored receipt without importing twice. Returns the persisted counts, the resulting job id for readback, and the cohortId when the commit was preview-backed.

Input schema and example

Arguments

filesrequired
array<object>One or more CSV or XLSX files, each as base64 in content_base64. An MCP call IS a deployed function request, so the files travel base64-encoded inside one JSON body bounded by that function's 4.5 MB limit: the aggregate decoded size is capped near 2.6 MiB and a single file larger than that is refused. A whole-file upload too large to inline can instead be sent in chunks with stage_contact_import_upload and referenced by its staging id. No file path or URL is accepted.
tokenrequired
stringThe preview token returned by preview_contact_import.
plan
array<object>Per-tab decisions from a prior preview. Each entry pins a tab (by key, or by name for older previews) to role contacts/suppression/ignore, chooses suppression channels, and maps columns. Omit to accept the automatic classification.
tags
array<string>Tags to apply to every imported contact. Must match the preview.
review_choices
objectadditionalProperties: allowedAnswers for the metadata classifier's uncertain decisions, keyed '<evidenceId>'. Each value is 'suppress' or 'none'. Commit is refused while any decision is unresolved.
sms_consent_attested
booleanOperator attests the file carries SMS consent for the phone numbers it imports.
voice_consent_attested
booleanOperator attests the file carries voice-call consent for the phone numbers it imports.
clean_emails
booleanAsk to clean imported emails. Requires the email:verify scope. The commit saves contacts and does NOT clean or charge inline: cleaning exactly this import's contacts is a separate paid step, clean_import_cohort, keyed by the cohortId the commit returns. Requesting it here records the intent and reports it as requested and not performed.
clean_addresses
booleanAsk to clean imported addresses. Requires the address:verify scope. The commit saves contacts and does NOT clean or charge inline: cleaning exactly this import's contacts is a separate paid step, clean_import_cohort, keyed by the cohortId the commit returns. Requesting it here records the intent and reports it as requested and not performed.

Example arguments

{
  "files": [
    {
      "content_base64": "RW1haWwKYWRhQGV4YW1wbGUub3JnCg=="
    }
  ],
  "token": "eyJ...signature",
  "tags": [
    "canvass"
  ]
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_contact_importsread-onlycontacts:read

List this organization's persisted imports, newest first, with counts per import. Requires contacts:read. Returns a bounded page and an honest continuation; it does not return per-row outcomes.

Input schema and example

Arguments

limit
integermin=1, max=100Page size. At most 100.
offset
integermin=0Rows to skip, from a prior next_offset.

Example arguments

{
  "limit": 25
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_contact_import_outcomesread-onlycontacts:read

Read the per-row outcomes of one past import by job id, newest evidence first. Requires contacts:read. Returns a bounded page with a keyset cursor and an honest continuation; category filters to create, merge, suppress, or skip. Missing tables or a foreign import are errors, not empty success.

Input schema and example

Arguments

import_idrequired
stringThe job id returned by commit_contact_import or list_contact_imports.
category
stringone of create, merge, suppress, skipOnly rows of this kind.
cursor
stringKeyset cursor from a prior next_cursor.
limit
integermin=1, max=500Page size. At most 500.

Example arguments

{
  "import_id": "11111111-1111-4111-8111-111111111111",
  "category": "create",
  "limit": 200
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_import_cleaning_cohortread-onlycontacts:read

Read the safe metadata of one frozen import identity cohort by its id (returned as cohortId by commit_contact_import when the commit was preview-backed). Requires contacts:read. Returns the cohort's id, preview and job references, snapshot version/fingerprint, the requested cleaning channels, the CAPTURED UNIQUE identity counts, a capture state and whether cohort-scoped paid cleaning is available. It never returns the raw email/address keys, never a billable-unit or pending-check count, and never a cleaning execution status. A foreign or absent cohort is 404; a missing schema is an error, not empty success.

Input schema and example

Arguments

cohort_idrequired
stringThe cohortId returned by commit_contact_import.

Example arguments

{
  "cohort_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
stage_contact_import_uploadcontacts:write

Begin or extend a staged upload for a contact file too large to send inline in one call. Requires contacts:write. Send the file in chunks: the first call omits staging_id and creates the staged upload, every later call sends the returned staging_id with the next chunk, and final true marks the last chunk. Stores bytes only: nothing is parsed, no contact is written and nothing is charged. The returned staging_id is the durable reference a later import commit uses for this file.

Input schema and example

Arguments

filenamerequired
stringFile name for the whole upload, for provenance. Required on the first chunk.
content_base64required
stringThis chunk's bytes, base64-encoded. A data: URL prefix is stripped. At most 10 MB decoded per chunk.
staging_id
stringThe staging id returned by the first chunk. Omit on the first call.
final
booleanSet true on the last chunk of the file.

Example arguments

{
  "filename": "voters.csv",
  "content_base64": "RW1haWwKYWRhQGV4YW1wbGUub3JnCg==",
  "final": true
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_contact_fieldsread-onlycontacts:read

Read the authorized organization's contact-field registry: the fields that have an explicit key/label/type definition, unioned with the keys that already appear in contacts' stored custom values and whose type is inferred from those values. Each field is returned as key (verbatim, including spaces and case), label, and type. This is the SAME registry the app's contact field settings use, so a key it lists can be filtered on; it does not return contact values, contact ids, or the contacts that carry a field. It is a bounded, read-only result: the full registry with a truthful total, not a silently truncated page. It changes no business state (the read records one routine API audit row). It does not define, convert, or remove any field.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
upsert_contact_fieldcontacts:write

Save an explicit key/label/type definition for one contact field in the authorized organization, keyed by the field key. Use this to pin a field's type (for example to make a field a number or a date) so it can be filtered as that type. The key is preserved verbatim; the label is stored trimmed. The stored row is read back and returned. This is a metadata save: it does NOT convert, clear, or repair any contact's existing value, and it does NOT change a stored value's type. Existing values that no longer match the new type keep their stored text; the app reports a type change when a filter no longer matches. A repeated identical save settles the row on that key/label/type; it spends nothing and sends nothing.

Input schema and example

Arguments

keyrequired
stringField key, at most 120 characters. Preserved verbatim, including spaces and case.
labelrequired
stringHuman-readable label, at most 120 characters. Stored trimmed.
typerequired
stringone of text, number, date, booleanThe field's type. One of the listed values; any other string is rejected.

Example arguments

{
  "key": "precinct",
  "label": "Precinct",
  "type": "number"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Lists 7

list_segmentsread-onlylists:read

List saved audiences (lists) in this organization, including name, id, and contact count. Use a returned id when a later tool asks for a segment. Does not return the people on the list.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
create_segmentlists:write

Save a new audience (list) in this organization and return its id and matched contact count. The filters use the same language as the dashboard, so preview_list first when the count matters. The saved audience is what a draft selects when you set its recipients. It creates nothing else, sends nothing, and never charges.

Input schema and example

Arguments

namerequired
stringList name, at most 120 characters.
description
stringOptional note about who is on this list, at most 1,000 characters.
tags
array<string>Match contacts that carry every one of these list tags.
tags_any
array<string>Match contacts that carry at least one of these tags.
state
stringOnly contacts in this state, by two-letter or full name.
has_email
booleanWhen true, only contacts with an email address.
has_phone
booleanWhen true, only contacts with a phone number.
has_address
booleanWhen true, only contacts with a mailing address on file.
exclude_do_not_contact
booleanWhen true, drop contacts marked do not contact.

Example arguments

{
  "name": "Polk volunteers",
  "tags": [
    "volunteer"
  ],
  "exclude_do_not_contact": true
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_segmentread-onlylists:read

Read one saved audience (list) in this organization by id, including its name, description, filters, and contact count. Returns not found for another organization's list. It does not return the people on the list and changes no business state (the read records one routine audit row).

Input schema and example

Arguments

segment_idrequired
stringSaved audience (list) id.

Example arguments

{
  "segment_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
preview_listread-onlylists:read

Count how many contacts in this organization a saved-audience definition would match, using the same filter language as the dashboard. Non-mutating: it creates no list, changes no business state (the read records one routine audit row), sends nothing, and never charges. Use it to size an audience before saving or sending.

Input schema and example

Arguments

tags
array<string>Match contacts that carry every one of these list tags.
tags_any
array<string>Match contacts that carry at least one of these tags.
state
stringOnly contacts in this state, by two-letter or full name.
has_email
booleanWhen true, only contacts with an email address.
has_phone
booleanWhen true, only contacts with a phone number.
has_address
booleanWhen true, only contacts with a mailing address on file.
exclude_do_not_contact
booleanWhen true, drop contacts marked do not contact.

Example arguments

{
  "tags": [
    "volunteer"
  ],
  "exclude_do_not_contact": true
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
change_segment_memberslists:write

Add or remove contacts on a saved static membership list in this organization by list id. Only a list whose sole filter is tags can change, and up to 100 contacts may change per call. It does not create or delete the list, does not return contacts, and does not send anything.

Input schema and example

Arguments

segment_idrequired
stringSaved audience (list) id.
actionrequired
stringone of add, removeAdd the contacts to the list, or remove them from it.
contact_idsrequired
array<string>Contact ids to add or remove, at most 100.

Example arguments

{
  "segment_id": "11111111-1111-4111-8111-111111111111",
  "action": "add",
  "contact_ids": [
    "22222222-2222-4222-8222-222222222222"
  ]
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
resolve_listread-onlylists:read

Turn a name, slug, or id an operator typed into this organization's saved audience ids and counts, returning one exact match or a short list of candidates to choose from. Read-only. It does not create a list and does not return the people on it.

Input schema and example

Arguments

queryrequired
stringThe list name, slug, or id to resolve, at most 120 characters.

Example arguments

{
  "query": "donors"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_segment_usageread-onlylists:read

Report which campaigns reference a saved audience in this organization so it is not deleted while in use, broken down by email, SMS, mail, and voice with a total. Read-only. It does not delete, rename, or edit the list.

Input schema and example

Arguments

segment_idrequired
stringSaved audience (list) id.

Example arguments

{
  "segment_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Suppressions 4

list_suppressionsread-onlysuppression:read

List do-not-contact entries (email, SMS, voice) for this organization, newest first. Read-only. It does not return mailing addresses.

Input schema and example

Arguments

channel
stringone of email, sms, voice, allFilter by stored channel. Omit to return records across every channel; 'all' returns only all-channel records.
page
integermin=1Page number, starting at 1.
limit
integermin=1, max=100Page size. At most 100.

Example arguments

{
  "channel": "email",
  "page": 1,
  "limit": 50
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
add_suppressionsuppression:write

Record an email and/or phone do-not-contact entry for this organization using the same ledger the dashboard uses. Provide an email, a phone, or both. This does not send anything.

Input schema and example

Arguments

email
stringEmail to suppress.
phone
stringU.S. phone number to suppress.
reasonrequired
stringone of manual, recipient_blocks_sender, unsubscribe, legal_requestWhy this entry exists. One of the listed values; any other string is rejected.
notesrequired
stringNote recorded on the entry. Required, 3 to 1,000 characters.

Example arguments

{
  "email": "person@example.org",
  "reason": "recipient_blocks_sender",
  "notes": "Asked to stop by phone"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
restore_suppressionsuppression:write

Withdraw a suppression override recorded through the API so a do-not-contact entry is enforced again in this organization. It does not delete the entry, does not clear consent or spam-trap blocks, and does not send anything.

Input schema and example

Arguments

suppression_idrequired
stringDo-not-contact entry id.

Example arguments

{
  "suppression_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
override_suppressionsuppression:write

Bypass one email do-not-contact entry in this organization with a required note so the address may be contacted again. Consent blocks and spam-trap entries are refused. It does not delete the entry and does not send anything.

Input schema and example

Arguments

suppression_idrequired
stringDo-not-contact entry id.
noterequired
stringWhy this entry is being bypassed, at least 3 and at most 1,000 characters.

Example arguments

{
  "suppression_id": "11111111-1111-4111-8111-111111111111",
  "note": "Recipient asked to be re-added"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Email 14

create_email_draftemail:draft

Create an unsent email draft in this organization. This does not send, schedule, or charge. Choose recipient_type all for every eligible contact, segment with segment_id or segment_ids for saved lists, selected with selected_contact_ids, or campaign_engagement with source_campaign_id and engagement. Scheduling and sending are separate tools and are not in this skeleton.

Input schema and example

Arguments

namerequired
stringDraft name. At most 160 characters.
subjectrequired
stringEmail subject. At most 255 characters.
messagerequired
stringEmail body. HTML is accepted.
recipient_type
stringone of all, segment, selected, campaign_engagementWho the draft is addressed to. Defaults to all when omitted.
segment_id
stringOne saved list id. Use with recipient_type segment.
segment_ids
array<string>Saved list ids to combine. Use with recipient_type segment.
selected_contact_ids
array<string>Contact ids. Use with recipient_type selected.
source_campaign_id
stringEarlier email campaign id. Use with recipient_type campaign_engagement.
engagement
stringone of opened, clickedWhich engagement to keep. Use with recipient_type campaign_engagement.
first_name_fallback
string | nullnullableGreeting used when a contact has no first name and the message has no inline {first_name|...} fallback. Trimmed and capped at 60 characters. Omit to use Friend. Null or blank stores Friend. An inline tag still wins.

Example arguments

{
  "name": "Saturday reminder",
  "subject": "Doors open at 9",
  "message": "<p>Bring a clipboard.</p>",
  "recipient_type": "all"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
preview_email_audienceread-onlyemail:draft

Non-mutating check for a would-be email campaign: recipient count, estimated cost, and blockers. Call this after a draft is agreed and before asking to send. It does not create, schedule, or send anything and never charges.

Input schema and example

Arguments

namerequired
stringDraft name.
subjectrequired
stringEmail subject.
messagerequired
stringEmail body. HTML is accepted.
recipient_type
stringone of all, segment, selected, campaign_engagementAudience kind. Defaults to all.
segment_id
stringOne saved list id.
segment_ids
array<string>Saved list ids to combine.
selected_contact_ids
array<string>Contact ids for recipient_type selected.
source_campaign_id
stringEarlier email campaign id for campaign_engagement.
engagement
stringone of opened, clickedEngagement to keep for campaign_engagement.

Example arguments

{
  "name": "Saturday reminder",
  "subject": "Doors open at 9",
  "message": "<p>Bring a clipboard.</p>",
  "recipient_type": "all"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_email_draftread-onlyemail:read

Read one email campaign in this organization by id, including status and scheduling state. Returns not found for another organization's campaign.

Input schema and example

Arguments

campaign_idrequired
stringEmail campaign id.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
update_email_draftemail:draft

Revise an unsent, unscheduled email draft in this organization. Only draft campaigns can be changed. Recipient selection and paid dispatch stay separate tools. This does not send or charge.

Input schema and example

Arguments

campaign_idrequired
stringEmail campaign id.
name
stringNew draft name.
subject
stringNew subject.
message
stringNew body. HTML is accepted.
from_name
stringNew From name.
from_email
stringNew From email.
reply_to_email
stringNew Reply-To email.
first_name_fallback
string | nullnullableGreeting used when a contact has no first name and the message has no inline {first_name|...} fallback. Trimmed and capped at 60 characters. Omit to leave the saved value. Null or blank clears it back to Friend. An inline tag still wins.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "subject": "Doors open at 10"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
send_email_campaignrequires confirmdestructiveemail:send

Send a prepared email campaign in this organization and charge organization balance. This spends money and cannot be undone. It requires confirm true and a unique idempotency_key. Billing, suppression, consent, and do-not-contact rules still apply. Prefer preview_email_audience first.

Input schema and example

Arguments

campaign_idrequired
stringEmail campaign id.
confirmrequired
booleanMust be true. Set only after the user agrees to send and spend.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not send twice.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "confirm": true,
  "idempotency_key": "saturday-reminder-2026"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_email_campaignsread-onlyemail:read

List this organization's email campaigns, newest first, 20 per page by default and at most 100, with status, type, recipient count, and sent, delivered, open, click, bounce, and unsubscribe totals, plus pagination and metricDefinitions. opened_count is unique recipients with any recorded open, including Apple Mail Privacy Protection prefetches and machine scanners; it is not total open hits. Read-only. It does not return message bodies or the recipient roster; read one campaign with get_email_draft or its delivery log with list_email_recipients.

Input schema and example

Arguments

page
integermin=1Page number, starting at 1.
limit
integermin=1, max=100Campaigns per page, default 20. At most 100.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
test_email_campaignrequires confirmdestructiveemail:test

Send a prepared email campaign to the API key owner's mailbox, a named active organization member, or a verified test recipient, as a real test delivery. This spends money and cannot be undone, so it requires confirm true and a unique idempotency_key. It does not send to the full audience; use send_email_campaign for that.

Input schema and example

Arguments

campaign_idrequired
stringEmail campaign id.
to
stringOptional mailbox to test to. Defaults to the key owner's address. Must be the owner, an active organization member, or a verified test recipient.
confirmrequired
booleanMust be true. Set only after the user agrees the test send spends money.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not send the test twice.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "to": "ada@example.org",
  "confirm": true,
  "idempotency_key": "email-test-saturday-01"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_test_recipientsread-onlyemail:test

List email addresses this organization has allowed to receive test sends, with pending or verified status. Read-only. It does not send a message and does not return confirmation links.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
add_test_recipientemail:test

Add an email address that may receive test sends for this organization after that address confirms a verification link. A verified address is returned without another email. A pending address is not emailed again within ten minutes. This sends one verification email. It does not send a campaign or charge the organization.

Input schema and example

Arguments

emailrequired
stringAddress to allow after it confirms the verification link.

Example arguments

{
  "email": "ada@example.org"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
remove_test_recipientemail:test

Remove an address from this organization's test-recipient list. Later test sends to that address are refused unless it is the key owner or an active member. This does not send a message or change the organization balance.

Input schema and example

Arguments

recipient_idrequired
stringTest recipient id returned by list_test_recipients.

Example arguments

{
  "recipient_id": "33333333-3333-4333-8333-333333333333"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
schedule_email_campaignrequires confirmdestructiveemail:send

Queue a prepared email draft to go out at a chosen future time. This commits a paid send and cannot be undone, so it requires confirm true and a unique idempotency_key. It does not send immediately. Note the two money events differ: any spend approval is used up now, when the campaign is queued, and is not available for another send afterwards; the balance hold is placed later, when the send job runs.

Input schema and example

Arguments

campaign_idrequired
stringEmail campaign id.
scheduled_atrequired
stringWhen to send, in ISO 8601 (for example 2026-10-11T18:30:00-04:00). Must be in the future.
confirmrequired
booleanMust be true. Set only after the user agrees to schedule a paid send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not schedule twice.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "scheduled_at": "2026-10-11T18:30:00-04:00",
  "confirm": true,
  "idempotency_key": "email-schedule-saturday-01"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
unschedule_email_campaignrequires confirmdestructiveemail:send

Cancel a scheduled email campaign before the send job claims it and return it to an editable draft. It cannot be recalled once the send starts, so it requires confirm true and a unique idempotency_key. It does not delete the draft and does not recall any email already sent.

Input schema and example

Arguments

campaign_idrequired
stringEmail campaign id.
confirmrequired
booleanMust be true. Set only after the user agrees to cancel the scheduled send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "confirm": true,
  "idempotency_key": "email-unschedule-saturday-01"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
set_email_audienceemail:draft

Replace a draft email campaign's saved audience and recipient snapshot, choosing all, segment, selected, or campaign_engagement targeting. Only an unsent draft you own can change, and segments or contacts are checked for suppressions. It changes who would receive the campaign; it does not send, schedule, or charge.

Input schema and example

Arguments

campaign_idrequired
stringEmail campaign id.
recipient_typerequired
stringone of all, segment, selected, campaign_engagementWho the draft is addressed to.
segment_id
stringOne saved list id. Use with recipient_type segment.
segment_ids
array<string>Saved list ids to combine. Use with recipient_type segment.
selected_contact_ids
array<string>Contact ids. Use with recipient_type selected.
source_campaign_id
stringEarlier email campaign id. Use with recipient_type campaign_engagement.
engagement
stringone of opened, clickedWhich engagement to keep. Use with recipient_type campaign_engagement.
exclude_campaign_ids
array<string>Earlier campaign ids whose recipients to skip.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "recipient_type": "segment",
  "segment_ids": [
    "22222222-2222-4222-8222-222222222222"
  ]
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
refresh_email_recipientsemail:draft

Re-resolve a draft email campaign's recipient snapshot from its already-saved audience after contacts change, removing duplicates and re-applying suppressions. Only an unsent draft you own with a saved audience can refresh. It does not change the audience itself and does not send or charge.

Input schema and example

Arguments

campaign_idrequired
stringEmail campaign id.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Transactional email 10

get_emailread-onlyemail:transactional

Read one sent email message in this organization by id, including its delivery status, recipients, subject, and event timestamps. Returns not found for another organization's message. It does not return the message body or other channels' messages.

Input schema and example

Arguments

email_idrequired
stringSent email message id.

Example arguments

{
  "email_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_emailsread-onlyemail:transactional

List sent email messages in this organization, newest first, optionally filtered by delivery status or recipient address. Read-only. It does not return draft campaigns or campaign audience lists.

Input schema and example

Arguments

status
stringone of reserved, sending, sent, delivered, opened, clicked, bounced, complained, failed, unknownOnly messages with this delivery status.
to
stringOnly messages sent to this recipient address.
limit
integermin=1, max=200Page size. At most 200.

Example arguments

{
  "status": "delivered",
  "limit": 50
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_email_templatesread-onlyemail:transactional

List the saved transactional email templates for this organization, with each template id, name, and subject. Use a returned id with get_email_template or send_transactional_email. It does not return template bodies or send anything.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_email_templateread-onlyemail:transactional

Read one saved transactional email template by id, including its name, subject, and stored markup. Returns not found when the template is not in this organization. It does not send anything or change the template.

Input schema and example

Arguments

template_idrequired
stringTransactional email template id.

Example arguments

{
  "template_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
create_email_templateemail:transactional

Create a saved transactional email template for this organization, the same record the templates page edits. Send a name and subject, plus html and/or text; a template must carry at least one body. Subject and bodies may use double curly brace placeholders, filled from variables on a send. A name already used in this organization is refused. This does not send any email and does not charge the balance; use send_transactional_email to send.

Input schema and example

Arguments

namerequired
stringTemplate name, 1 to 80 characters.
subjectrequired
stringSubject line. May contain double curly brace placeholders.
html
stringHTML body. Provide html, text, or both.
text
stringPlain-text body. Provide html, text, or both.

Example arguments

{
  "name": "Shift confirmation",
  "subject": "Your shift on {{date}}",
  "html": "<p>See you at {{time}}.</p>",
  "text": "See you at {{time}}."
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
update_email_templateemail:transactional

Change a saved transactional email template in this organization. Only the fields you pass are changed; an omitted name, subject, html, or text keeps its stored value. Send an empty string for html or text to clear that body, or a new value to replace it. An update that carries no fields is refused, as is a name already used by another template here. This does not send any email and does not charge the balance.

Input schema and example

Arguments

template_idrequired
stringTransactional email template id.
name
stringNew template name, 1 to 80 characters. Omit to keep the stored name.
subject
stringNew subject line. Omit to keep the stored subject.
html
stringNew HTML body, or an empty string to clear it. Omit to keep the stored value.
text
stringNew plain-text body, or an empty string to clear it. Omit to keep the stored value.

Example arguments

{
  "template_id": "11111111-1111-4111-8111-111111111111",
  "subject": "Your shift on {{date}} (updated)"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
delete_email_templatedestructiveemail:transactional

Delete one saved transactional email template from this organization. This cannot be undone and removes only that template; it does not send, recall, or charge anything, and already-sent messages keep their content. Returns not found for another organization's template or an unknown id.

Input schema and example

Arguments

template_idrequired
stringTransactional email template id.

Example arguments

{
  "template_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
send_transactional_emailrequires confirmdestructiveemail:transactional

Charge the organization balance and send one transactional email to a single address, optionally rendering a saved template with variables. This spends money and cannot be undone. Suppression and consent rules still apply. It requires confirm true and a unique idempotency_key, and it is not for bulk campaign mail.

Input schema and example

Arguments

torequired
stringRecipient email address.
subjectrequired
stringSubject line. No line breaks.
html
stringHTML body. Provide html, text, or a template_id.
text
stringPlain-text body.
from
stringFrom address. Defaults to the organization's verified From.
reply_to
stringReply-To address. Defaults to the organization reply-to.
template_id
stringSaved template id to render when html or text is omitted.
tracking
booleanTurn open and click tracking on for this message. Defaults to false.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "to": "volunteer@example.org",
  "subject": "Your shift confirmation",
  "html": "<p>Thanks for signing up.</p>",
  "confirm": true,
  "idempotency_key": "shift-confirm-2026-0001"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_transactional_emailsread-onlyemail:transactional

List recent transactional emails for this organization, newest first, with id, recipient, subject, status, and timestamps. Filter by status or recipient address. It does not return message bodies and does not send anything.

Input schema and example

Arguments

status
stringone of reserved, sending, sent, delivered, opened, clicked, bounced, complained, failed, unknownOnly messages in this delivery state.
to
stringOnly messages to this exact recipient address.
limit
integermin=1, max=100How many messages to return. At most 100.

Example arguments

{
  "status": "delivered",
  "limit": 50
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_transactional_emailread-onlyemail:transactional

Read one transactional email by id, including its recipients, status, and delivery timestamps. Returns not found when the message is not in this organization. It is read-only and does not resend or change anything.

Input schema and example

Arguments

message_idrequired
stringTransactional email id.

Example arguments

{
  "message_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Text (SMS & MMS) 14

list_sms_campaignsread-onlysms:read

List this organization's SMS and MMS campaigns with copy, status, and progress counts, newest first, optionally filtered by status or channel. Read-only. It does not return recipient phone numbers or per-recipient delivery results.

Input schema and example

Arguments

status
stringone of draft, scheduled, sending, completed, paused, failed, cancelledOnly campaigns in this status.
type
stringone of sms, mmsOnly campaigns of this channel.
page
integermin=1Page number, starting at 1.
limit
integermin=1, max=100Campaigns per page. At most 100.

Example arguments

{
  "status": "draft",
  "page": 1,
  "limit": 25
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_sms_campaignread-onlysms:read

Read one SMS or MMS campaign in this organization by id, including stored copy, status, sender-prepared counts, and scheduling state. Does not return recipient phone numbers, delivery events, or failure breakdowns.

Input schema and example

Arguments

campaign_idrequired
stringSMS or MMS campaign id.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
create_sms_draftsms:draft

Create an unsent SMS or MMS draft in this organization from a message and an audience choice. Set type mms and supply an image to make it a picture message; the image is stored as a publicly readable asset, but this does not send, schedule, or charge. Change the audience later with set_sms_audience while the campaign is still an unscheduled draft. Sending and scheduling are separate paid tools.

Input schema and example

Arguments

namerequired
stringDraft name. At most 120 characters.
messagerequired
stringSMS body text. At most 1,600 characters.
type
stringone of sms, mmssms for a plain text draft, or mms for a picture message. Defaults to sms; defaults to mms when an image is supplied.
image_base64
stringBase64-encoded image bytes for an mms draft: a JPG, PNG, or GIF at most 1 MB decoded. Requires image_content_type and image_filename. It is stored as a publicly readable asset but sends nothing and charges nothing.
image_content_type
stringone of image/jpeg, image/png, image/gifThe image's MIME type. Required with image_base64.
image_filename
stringFile name for the uploaded image. Required with image_base64.
recipient_type
stringone of all, segmentWho receives the draft. Defaults to all eligible contacts when omitted.
segment_id
stringOne saved list id. Use with recipient_type segment.
segment_ids
array<string>Saved list ids to combine. Use with recipient_type segment.

Example arguments

{
  "name": "Saturday reminder",
  "message": "Doors open at 9. Reply STOP to opt out.",
  "recipient_type": "all"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
update_sms_draftsms:draft

Revise the name, message, or channel of an unsent draft in this organization. It changes draft copy only. It does not change the audience (use set_sms_audience), schedule, send, or charge. Media depends on what you pass: editing text or name alone keeps an MMS draft's current image, supplying type mms with a new image replaces it (stored as a publicly readable asset), and setting type sms removes it.

Input schema and example

Arguments

campaign_idrequired
stringSMS or MMS campaign id.
name
stringNew draft name. At most 120 characters.
message
stringNew SMS body text. At most 1,600 characters.
type
stringone of sms, mmsNew channel. sms removes an MMS image; mms keeps or replaces it. Omit to keep the current channel.
image_base64
stringBase64-encoded replacement image bytes for an mms draft: a JPG, PNG, or GIF at most 1 MB decoded. Requires image_content_type and image_filename.
image_content_type
stringone of image/jpeg, image/png, image/gifThe image's MIME type. Required with image_base64.
image_filename
stringFile name for the uploaded image. Required with image_base64.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "message": "Doors open at 10. Reply STOP to opt out."
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
set_sms_audiencesms:draft

Replace an unscheduled SMS or MMS draft's saved audience and recipient snapshot, choosing all, segment, or custom targeting. Only a draft that has not started delivery can change. It recalculates the recipient count and cost estimate and does not send, schedule, charge, or move organization balance. A sent or scheduled campaign stays locked.

Input schema and example

Arguments

campaign_idrequired
stringSMS or MMS campaign id.
recipient_typerequired
stringone of all, segment, customWho the draft is addressed to.
segment_id
stringOne saved list id. Use with recipient_type segment.
segment_ids
array<string>Saved list ids to combine. Use with recipient_type segment.
filters
objectCustom audience filters. Use with recipient_type custom. Keys match the text draft API.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "recipient_type": "segment",
  "segment_ids": [
    "22222222-2222-4222-8222-222222222222"
  ]
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
preview_sms_audienceread-onlysms:draft

Non-mutating preflight for a would-be SMS or MMS campaign: eligible recipient count, estimated cost, sender readiness, and blockers. It does not create, upload media, schedule, or send anything, and never charges or holds money. Prefer this before asking to send.

Input schema and example

Arguments

namerequired
stringDraft name.
messagerequired
stringSMS body text.
type
stringone of sms, mmsChannel to estimate. Defaults to sms.
recipient_type
stringone of all, segmentAudience kind. Defaults to all eligible contacts when omitted.
segment_id
stringOne saved list id. Use with recipient_type segment.
segment_ids
array<string>Saved list ids to combine. Use with recipient_type segment.
has_media
booleanSet true to estimate an MMS draft's picture-message cost without uploading an image.

Example arguments

{
  "name": "Saturday reminder",
  "message": "Doors open at 9. Reply STOP to opt out.",
  "recipient_type": "all"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
test_sms_campaignrequires confirmdestructivesms:test

Send the stored SMS or MMS creative once to the API key holder's verified personal phone and charge organization balance. This spends money; it does not text the campaign audience or change the draft. Requires confirm true and a unique idempotency_key.

Input schema and example

Arguments

campaign_idrequired
stringSMS or MMS campaign id.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "confirm": true,
  "idempotency_key": "sms-test-2026-0001"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
send_sms_campaignrequires confirmdestructivesms:send

Start a prepared SMS or MMS draft in this organization and dispatch it to its recipients, charging organization balance. This spends money and cannot be undone; it requires confirm true and a unique idempotency_key. It does not create or edit the draft.

Input schema and example

Arguments

campaign_idrequired
stringSMS or MMS campaign id.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "confirm": true,
  "idempotency_key": "sms-send-2026-0001"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
schedule_sms_campaignrequires confirmdestructivesms:send

Queue an SMS or MMS draft in this organization to dispatch at a future time. It does not text anyone now; it requires confirm true and a unique idempotency_key. Note the two money events differ: any spend approval is used up now, when the campaign is queued, and is not available for another send afterwards; the balance hold is placed later, when the send job runs. Send and edit are separate tools.

Input schema and example

Arguments

campaign_idrequired
stringSMS or MMS campaign id.
scheduled_atrequired
stringFuture send time as an ISO-8601 date-time.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "scheduled_at": "2026-11-03T14:00:00.000Z",
  "confirm": true,
  "idempotency_key": "sms-schedule-2026-0001"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
unschedule_sms_campaignrequires confirmdestructivesms:send

Return a scheduled SMS or MMS campaign in this organization to an editable draft before its send time. This cancels the queued dispatch; it does not send, and requires confirm true and a unique idempotency_key. Nothing is refunded: no balance hold was placed when it was scheduled, and the spend approval used to schedule it is not returned, so it cannot be reused for another send.

Input schema and example

Arguments

campaign_idrequired
stringSMS or MMS campaign id.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "confirm": true,
  "idempotency_key": "sms-unschedule-2026-0001"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_sms_recipientsread-onlysms:readlogs:read

List a page of recipient delivery outcomes for one SMS or MMS campaign in this organization, optionally filtered by status. Does not return phone numbers or message identifiers. Requires both sms:read and logs:read.

Input schema and example

Arguments

campaign_idrequired
stringSMS or MMS campaign id.
status
stringone of pending, sending, sent, delivered, failed, skippedOnly recipients in this status.
page
integermin=1Page number, starting at 1.
limit
integermin=1, max=250Recipients per page. At most 250.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "status": "failed",
  "page": 1,
  "limit": 100
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_sms_eventsread-onlysms:readlogs:read

List a page of delivery events for one SMS or MMS campaign in this organization from the durable send ledger, optionally filtered by status. Does not return raw recipient phone numbers or carrier payloads. Requires both sms:read and logs:read.

Input schema and example

Arguments

campaign_idrequired
stringSMS or MMS campaign id.
status
stringone of queued, sending, sent, delivered, failedOnly events in this status.
page
integermin=1Page number, starting at 1.
limit
integermin=1, max=250Events per page. At most 250.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "status": "delivered",
  "page": 1,
  "limit": 100
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_sms_outcomesread-onlysms:readlogs:read

Summarize delivery outcomes for one SMS or MMS campaign in this organization: sent, delivered, failed, skipped, and failure counts by reason. Does not return recipient phone numbers or individual message records. Requires both sms:read and logs:read.

Input schema and example

Arguments

campaign_idrequired
stringSMS or MMS campaign id.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_sms_readinessread-onlysms:read

Report what is missing before this organization may send SMS or MMS right now, including sender readiness and balance. Read-only: it does not send, schedule, upload media, or change anything, and it returns no carrier account identifiers.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Physical mail 5

list_mail_campaignsread-onlymail:read

List physical-mail campaigns for this organization, newest first, with status, piece counts, and cost fields. Call it to find a campaign id for get_mail_campaign. It does not return artwork, mailing addresses, or recipient data.

Input schema and example

Arguments

status
stringone of draft, queued, processing, mailed, paused, completed, failed, canceled, needs_attentionOnly campaigns in this status. Omit for every status.
page
integermin=1Page number, starting at 1.
limit
integermin=1, max=100Page size. At most 100.

Example arguments

{
  "status": "queued",
  "page": 1,
  "limit": 25
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_mail_campaignread-onlymail:read

Read one physical-mail campaign by id, including its frozen return identity, recipient statistics, and recent piece progress. Returns not found for another organization's campaign. It does not return artwork files, mailing addresses, or recipient data.

Input schema and example

Arguments

campaign_idrequired
stringPhysical-mail campaign id.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
create_mail_draftrequires confirmdestructivemail:draft

Create a held physical-mail campaign draft in this organization from prepared artwork supplied here as base64. It validates the artwork and the audience and reserves the quoted balance, so it spends money and requires confirm true and a unique idempotency_key. Nothing is printed or mailed and no final amount is charged, so the draft can still be changed or cancelled. Size and cost it first with preview_mail_audience.

Input schema and example

Arguments

namerequired
stringDraft name. At most 160 characters.
mail_typerequired
stringone of postcard, letterKind of printed piece.
postcard_size
stringone of 4x6, 6x9, 6x11Postcard size. Required for a postcard; do not pass one for a letter, since a letter carrying a postcard size is rejected.
front_creative_base64required
stringFront artwork as base64-encoded PDF or PNG. Required.
back_creative_base64
stringBack artwork as base64-encoded PDF or PNG. Required for a postcard and optional for a letter.
notes
stringFree-form internal notes.
segment_id
stringSaved-list id to mail. Omit to mail every eligible contact.
include_partial_addresses
booleanInclude unverified addresses. Defaults to false, mailing verified addresses only.
one_mail_per_address
booleanSend at most one piece per household. Defaults to false.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.
confirmrequired
booleanMust be true. Set only after the user agrees to reserve the balance for this draft.

Example arguments

{
  "name": "Ada fall postcard",
  "mail_type": "postcard",
  "postcard_size": "6x9",
  "front_creative_base64": "JVBERi0xLjQKJcTl",
  "segment_id": "22222222-2222-4222-8222-222222222222",
  "one_mail_per_address": true,
  "idempotency_key": "ada-postcard-2026-0001",
  "confirm": true
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
preview_mail_audienceread-onlymail:read

Non-mutating preflight for a physical-mail campaign: eligible recipient count, cost estimate, and blockers. Call it after the mail options are agreed and before launching. It does not create a campaign, reserve funds, upload artwork, or submit anything for printing.

Input schema and example

Arguments

mail_typerequired
stringone of postcard, letterKind of printed piece.
postcard_size
stringone of 4x6, 6x9, 6x11Postcard size. Required for a postcard; do not pass one for a letter, since a letter carrying a postcard size is rejected.
recipient_type
stringone of all, segmentAudience kind. Required.
segment_id
stringSaved-list id. Required when recipient_type is segment.
include_partial_addresses
booleanInclude unverified addresses in the estimate. Defaults to false.
one_mail_per_address
booleanCount at most one piece per household. Defaults to false.

Example arguments

{
  "mail_type": "postcard",
  "postcard_size": "6x9",
  "recipient_type": "all"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
launch_mail_campaignrequires confirmdestructivemail:send

Print and dispatch a held physical-mail campaign and charge the organization balance. This spends money and cannot be undone: a printed piece cannot be recalled once it is submitted. It requires confirm true and a unique idempotency_key, accepts no audience or artwork changes, and is limited to a queued or needs_attention campaign already held in this organization; a plain draft is the one state it cannot start.

Input schema and example

Arguments

campaign_idrequired
stringHeld physical-mail campaign id.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "confirm": true,
  "idempotency_key": "ada-mail-launch-0001"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Voice & dialer 16

list_voice_campaignsread-onlyvoice:read

List voice and voicemail campaigns for this organization, newest first, with status and cost fields. Call it to find a campaign id for get_voice_campaign. It does not return recipient phone numbers, audio URLs, or provider identifiers.

Input schema and example

Arguments

type
stringone of call, voicemailOnly campaigns of this kind. Omit for both.
page
integermin=1Page number, starting at 1.
limit
integermin=1, max=100Page size. At most 100.

Example arguments

{
  "type": "voicemail",
  "page": 1,
  "limit": 25
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_voice_campaignread-onlyvoice:read

Read one voice or voicemail campaign by id with its name, status, message, and aggregate per-recipient call-status counts. Returns not found for another organization's campaign. It does not return recipient phone numbers or provider identifiers.

Input schema and example

Arguments

campaign_idrequired
stringVoice or voicemail campaign id.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
create_voice_draftvoice:draft

Create a local voice or voicemail campaign draft. A one-to-one call draft needs a message script; a voicemail draft needs an uploaded audio asset token with its duration. It does not place calls, reserve funds, schedule delivery, or send anything.

Input schema and example

Arguments

namerequired
stringDraft name. At most 160 characters.
typerequired
stringone of call, voicemailKind of voice campaign.
message
stringRead-aloud script. Required for a one-to-one call draft.
cc_number_id
stringCaller ID to use. Omit for the organization default.
recipient_type
stringone of all, segment, customAudience kind. Required.
segment_id
stringSaved-list id. Required when recipient_type is segment.
contact_ids
array<string>Contact ids. Required when recipient_type is custom.
audio_asset_token
stringVoicemail asset token obtained from the audio upload endpoint. Required for a voicemail draft.
audio_duration
integermin=1, max=300Audio length in seconds. Required for a voicemail draft.
audio_url
stringHTTPS audio URL. Prefer audio_asset_token.

Example arguments

{
  "name": "Ada voicemail draft",
  "type": "voicemail",
  "recipient_type": "all",
  "audio_asset_token": "11111111-1111-4111-8111-111111111111",
  "audio_duration": 30
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
launch_voice_campaignrequires confirmdestructivevoice:send

Launch a prepared voicemail campaign and charge the organization balance as calls connect. This spends money and dispatches calls to recipients; it requires confirm true and a unique idempotency_key. It launches only voicemail campaigns that already have audio, not one-to-one calls, and it holds to quiet hours, consent, and balance rules.

Input schema and example

Arguments

campaign_idrequired
stringVoicemail campaign id that has audio.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "confirm": true,
  "idempotency_key": "ada-voicemail-launch-0001"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_voice_recipientsread-onlyvoice:readlogs:read

List paginated per-recipient outcomes for one voice campaign, including call status, cost, and timestamps. Call it to review progress before or after a launch. It does not return phone numbers, email addresses, audio URLs, or provider identifiers.

Input schema and example

Arguments

campaign_idrequired
stringVoice or voicemail campaign id.
call_status
stringone of pending, dialing, completed, failed, skippedOnly recipients in this call status. Omit for every recipient.
page
integermin=1Page number, starting at 1.
limit
integermin=1, max=250Page size. At most 250.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "call_status": "completed",
  "limit": 100
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
start_voice_callrequires confirmdestructivevoice:send

Place one supervised one-to-one call that bridges the key owner's already-verified operator phone to a single contact, and charge the organization balance as the call connects. This spends money and cannot be un-rung; it requires confirm true and a unique idempotency_key. The agent cannot set the bridge destination, and no autonomous voice or text-to-speech is placed.

Input schema and example

Arguments

contact_idrequired
stringContact to call.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "contact_id": "33333333-3333-4333-8333-333333333333",
  "confirm": true,
  "idempotency_key": "ada-voice-call-0001"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_voice_callread-onlyvoice:read

Read one voice call session by id, sanitized to omit call-control identifiers. Returns not found for another organization's call. It does not place, change, or end a call.

Input schema and example

Arguments

call_idrequired
stringVoice call session id.

Example arguments

{
  "call_id": "44444444-4444-4444-8444-444444444444"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_voice_numbersread-onlyvoice:read

List the voice-enabled caller IDs this organization may place calls from, marking the default one. Use a returned id as a campaign caller ID. It does not buy, release, or change numbers and does not return connection identifiers.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
upload_voice_assetvoice:draft

Store a prepared MP3 or WAV voicemail audio supplied here as base64 and return the asset token that create_voice_draft requires. It does not place calls, create a campaign, or charge anything. Audio must actually be MP3 or WAV and at most ten megabytes.

Input schema and example

Arguments

audio_base64required
stringMP3 or WAV audio as base64.
content_type
stringone of audio/mpeg, audio/mp3, audio/wav, audio/x-wavDeclared audio type. Defaults to audio/mpeg. The contents must match it.

Example arguments

{
  "audio_base64": "SUQzBAAAAAAAI1RT",
  "content_type": "audio/mpeg"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_dialer_sessionsread-onlyvoice:read

List this operator's recent power-dialer sessions, newest first. Each session is an operator-first queue. On a conference session the operator is dialled once and stays live; on a legacy_bridge session, used when conference admission is not granted, the operator is dialled again for every contact. It does not dial a recipient and does not start any call.

Input schema and example

Arguments

page
integermin=1Page number, starting at 1.
limit
integermin=1, max=100Page size. At most 100.

Example arguments

{
  "page": 1,
  "limit": 25
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_dialer_sessionread-onlyvoice:read

Read one power-dialer session by id: queue position, the current contact, and session state. Call it to decide whether to advance to the next contact. It does not start a call or change the queue.

Input schema and example

Arguments

session_idrequired
stringPower-dialer session id.

Example arguments

{
  "session_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
advance_dialer_sessionrequires confirmdestructivevoice:send

Hang up the current contact and announce the next one in an operator-first power-dialer session, charging the session meter while the operator stays connected. This spends money and dispatches a call; it requires confirm true and a unique idempotency_key. On a conference session the operator is already bridged and is not dialled again. On a legacy_bridge session, used when conference admission is not granted, the operator is dialled again on each Next.

Input schema and example

Arguments

session_idrequired
stringPower-dialer session to advance.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "session_id": "11111111-1111-4111-8111-111111111111",
  "confirm": true,
  "idempotency_key": "ada-dialer-next-0001"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_active_callread-onlyvoice:read

Read the voice call this organization has live right now: who is on it, its state, and how long it has been running. Read-only. It does not dial, join, transfer, or hang up any call.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
start_dialer_sessionvoice:draft

Open or resume this operator's power-dialer session for a call campaign. On a conference session the operator is dialled once and stays live while each contact is announced in turn, so there is no manual dial; on a legacy_bridge session, used when conference admission is not granted, the operator is dialled again for every contact. This only opens or resumes the queue and does not dial any contact yet. The bridge destination is the verified personal phone already configured in Account settings and cannot be set here.

Input schema and example

Arguments

campaign_idrequired
stringCall campaign id whose contacts form the queue. Voicemail campaigns are not accepted here.
cc_number_id
stringOptional caller id to present. Omit to use the organization default.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
test_voice_recordingrequires confirmdestructivevoice:send

Play one robocall draft's saved recording to the API key owner's registered phone. The draft is not launched and the call is not a campaign recipient. This spends money and cannot be undone, so it requires confirm true and a unique idempotency_key. Pass approval_id only when an operator has approved this exact test.

Input schema and example

Arguments

campaign_idrequired
stringThe robocall draft whose recording to play.
confirmrequired
booleanMust be true. Set only after the user agrees to spend.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not place a second test call.
approval_id
stringOptional operator approval id for this exact test.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "confirm": true,
  "idempotency_key": "recording-test-2026"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
test_robocallrequires confirmdestructivevoice:send

Place one standalone robocall of an organization-owned recording to the API key owner's registered personal phone. It never attaches to a campaign. This spends money and cannot be undone, so it requires confirm true and a unique idempotency_key. Pass approval_id only when an operator has approved this exact test.

Input schema and example

Arguments

recording_idrequired
stringThe id of the saved recording to play.
confirmrequired
booleanMust be true. Set only after the user agrees to spend.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not place a second test call.
approval_id
stringOptional operator approval id for this exact test.

Example arguments

{
  "recording_id": "11111111-1111-4111-8111-111111111111",
  "confirm": true,
  "idempotency_key": "robocall-test-2026"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Verification 3

verify_emailsrequires confirmdestructiveemail:verify

Charge the organization balance and launch an email verification run over every contact or one saved audience, marking each address deliverable or undeliverable. This spends money and starts a background run; it does not send any mail. It requires confirm true and a unique idempotency_key.

Input schema and example

Arguments

recipient_type
stringone of all, segmentScope of the run. all checks every contact; segment limits it to saved audiences.
segment_id
stringOne saved audience id. Use with recipient_type segment.
segment_ids
array<string>Multiple saved audience ids. Use with recipient_type segment.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "recipient_type": "all",
  "confirm": true,
  "idempotency_key": "clean-list-2026-run-01"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
verify_addressesrequires confirmdestructiveaddress:verify

Charge the organization balance and launch an address check over the organization mailing audience, flagging each address as deliverable or undeliverable. This spends money and starts a background run; it does not print or mail anything. It requires confirm true and a unique idempotency_key.

Input schema and example

Arguments

confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "confirm": true,
  "idempotency_key": "clean-addresses-2026-run-01"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
clean_import_cohortrequires confirmdestructiveemail:verifyaddress:verify

Clean exactly one frozen import identity cohort and charge organization balance. Requires email:verify and address:verify. It acts only on the contacts that match the cohort's captured email keys and complete-address hashes, never on the whole organization, and never accepts a caller-supplied key list. This spends money and cannot be undone, so it requires confirm true and a unique idempotency_key. The credential organization is the one that owns the API key. Nothing is charged when no cohort identity needs cleaning.

Input schema and example

Arguments

cohort_idrequired
stringThe cohortId returned by commit_contact_import.
channelsrequired
array<string>Which identities to clean. At least one of email or address.
confirmrequired
booleanMust be true. Set only after the user agrees to spend.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not spend twice.
approval_id
stringOptional id of an approved operator spend approval for this exact cohort.

Example arguments

{
  "cohort_id": "11111111-1111-4111-8111-111111111111",
  "channels": [
    "email"
  ],
  "confirm": true,
  "idempotency_key": "clean-cohort-2026-0001"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Texting registration 8

get_texting_brand_registrationread-onlyregistration:read

Read this organization's stored texting brand-registration status, the authoritative one-time brand filing fee, and whether the credential is the active, fully-set-up organization owner (role-and-setup eligibility only, not spending authority). It reports the locally stored filing state, not a live carrier reconciliation, and never returns carrier identifiers, raw payloads, verification tokens, or a full EIN. It has no business effect: it registers nothing, charges nothing, creates no profile, and assigns no number. Paid brand submission is available through submit_texting_brand_registration (POST /api/v1/registration/brand) when the credential holds registration:submit and the active organization owner has completed setup; the owner-and-setup flag here is not a credential grant. One routine API audit row is recorded.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
preview_texting_brand_registrationread-onlyregistration:read

Validate would-be texting brand-registration details against this organization's saved settings, reporting the required fixes and the authoritative brand filing fee, exactly like the dashboard's business-information step. Omitted fields fall back to the saved value or the credential owner's own name, email, and phone; an empty string clears a value. It reserves nothing, completes no setup, and guarantees no carrier acceptance. The `ready` flag means the packet passed field validation only, not that the organization is already filed, permitted, or funded. It has no business effect: it registers nothing, charges nothing, and creates nothing; one routine API audit row is recorded. Paid submission is available through submit_texting_brand_registration (POST /api/v1/registration/brand).

Input schema and example

Arguments

legal_business_name
stringLegal business name. Omit to use the saved value.
ein
stringNine-digit EIN, such as 12-3456789. Omit to use the saved value.
street_address
stringStreet address. Omit to use the saved value.
street_address2
stringStreet address line 2. Omit to use the saved value.
city
stringCity. Omit to use the saved value.
state
stringTwo-letter state abbreviation. Omit to use the saved value.
postal_code
stringZIP code. Omit to use the saved value.
website
stringPublic website. Send an empty string to clear it; omit to use the saved value.
authorized_rep_name
stringAuthorized representative name. Omit to use the credential owner's name.
authorized_rep_email
stringAuthorized representative email. Omit to use the credential owner's email.
authorized_rep_phone
stringAuthorized representative phone. Omit to use the credential owner's phone.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
request_texting_brand_approvalregistration:submit

Create a pending spend-approval request for this organization's 10DLC brand filing, for a key that requires an operator to approve each filing. It builds the exact carrier packet the submission will file (the same fields and fallbacks as submit_texting_brand_registration) so the operator approves that exact packet. It charges nothing, reserves nothing, files nothing, and cannot approve itself: the account owner approves the pending request in Account Settings → Agent approvals, then pass the returned approval id to submit_texting_brand_registration as approval_id. Only the active organization owner may request it. Requires scope registration:submit and a unique idempotency_key.

Input schema and example

Arguments

legal_business_name
stringLegal business name. Omit to use the saved value.
ein
stringNine-digit EIN, such as 12-3456789. Omit to use the saved value.
street_address
stringStreet address. Omit to use the saved value.
street_address2
stringStreet address line 2. Omit to use the saved value.
city
stringCity. Omit to use the saved value.
state
stringTwo-letter state abbreviation. Omit to use the saved value.
postal_code
stringZIP code. Omit to use the saved value.
website
stringPublic website. Send an empty string to clear it; omit to use the saved value.
authorized_rep_name
stringAuthorized representative name. Omit to use the credential owner's name.
authorized_rep_email
stringAuthorized representative email. Omit to use the credential owner's email.
authorized_rep_phone
stringAuthorized representative phone. Omit to use the credential owner's phone.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "idempotency_key": "brand-approval-2026-01"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
submit_texting_brand_registrationrequires confirmdestructiveregistration:submit

File this organization's 10DLC brand registration and charge the non-refundable one-time brand filing fee. Only the active, fully-set-up organization owner may file, and the fee comes from the server, never the caller. Omitted fields fall back to the saved value or the credential owner's own name, email, and phone; an empty string clears a value. It spends money and cannot be undone: it requires confirm true, a unique idempotency_key, and scope registration:submit. A repeat with the same fields and key is already on file and charges nothing; an uncertain provider outcome is never retried blindly. If this key requires an approval, request it first with the same fields and pass the returned id as approval_id.

Input schema and example

Arguments

legal_business_name
stringLegal business name. Omit to use the saved value.
ein
stringNine-digit EIN, such as 12-3456789. Omit to use the saved value.
street_address
stringStreet address. Omit to use the saved value.
street_address2
stringStreet address line 2. Omit to use the saved value.
city
stringCity. Omit to use the saved value.
state
stringTwo-letter state abbreviation. Omit to use the saved value.
postal_code
stringZIP code. Omit to use the saved value.
website
stringPublic website. Send an empty string to clear it; omit to use the saved value.
authorized_rep_name
stringAuthorized representative name. Omit to use the credential owner's name.
authorized_rep_email
stringAuthorized representative email. Omit to use the credential owner's email.
authorized_rep_phone
stringAuthorized representative phone. Omit to use the credential owner's phone.
approval_id
stringOptional spend approval id for a key that requires an operator to approve each filing.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.

Example arguments

{
  "confirm": true,
  "idempotency_key": "brand-file-2026-01"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_texting_campaign_registrationread-onlyregistration:read

Read this organization's stored texting campaign (10DLC) registration readiness: the current filing status, rejection and retry notes, the frozen filed packet, the resumable draft, the persisted free site-check history, the authoritative campaign review fee, and whether setup is complete. Owner or admin only, matching the dashboard's campaign surface. It reports the locally stored state, not a live carrier reconciliation, and it never returns carrier identifiers, raw provider payloads, verification tokens, or the raw registration row, while your own brand names, URLs, and copy are preserved verbatim. already_filed means a carrier campaign reference is recorded, not approval or delivery, and a missing reference does not prove no filing occurred; confirmation_required or submitting mean do not submit another filing, and none of these flags establish whether a fee was charged, so a missing carrier identity is never permission to submit. Paid campaign filing is available through submit_texting_campaign_registration when the credential holds registration:submit. It has no business effect: it files nothing, charges nothing, creates no profile, and assigns no number; one routine API audit row is recorded. The free website preflight is check_texting_campaign_site.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
check_texting_campaign_siteregistration:prepare

Run the free website-compliance preflight for this organization's campaign: validate the opt-in, privacy, and terms URLs, fetch the live public pages, and return the same carrier checklist the paid submit enforces, then append one immutable history row stamped with this organization and the check time. Owner or admin only, and the organization must be fully set up. This is a readiness check, not a filing: it charges nothing, files nothing with any carrier, creates no profile, and assigns no number. It does make outbound reads of your public pages and appends history, so a repeat is a new timestamped record rather than a no-op. A failed history write is surfaced as an error and is never presented as durable evidence. The URLs must be public https pages on your own domain; platform or reseller hosts are refused. Requires scope registration:prepare.

Input schema and example

Arguments

opt_in_urlrequired
stringPublic https URL of the SMS opt-in form on your campaign website.
privacy_policy_urlrequired
stringPublic https URL of your privacy policy.
terms_urlrequired
stringPublic https URL of your terms of service.
opt_in_screenshot_url
stringOptional public https URL of a screenshot of the opt-in form.

Example arguments

{
  "opt_in_url": "https://friends.example.org/sms",
  "privacy_policy_url": "https://friends.example.org/privacy",
  "terms_url": "https://friends.example.org/terms"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
save_texting_campaign_draftregistration:prepare

Save this organization's texting campaign compliance draft: the opt-in form URL, privacy policy URL, terms URL, and optional opt-in screenshot URL, opt-in description, and HELP reply contact. This is the same draft the paid filing later reads. Owner or admin only, matching the dashboard's campaign surface, and the organization must be fully set up. A field you send is written; an omitted field keeps its stored value, and an empty string clears a saved value. A supplied HELP contact must be a valid email address, and an empty one never erases the stored shared inbox. It is free: it charges nothing, files nothing with any carrier, creates no profile, and assigns no number, and it records one routine API audit row. The free preflight is check_texting_campaign_site and the paid filing is submit_texting_campaign_registration. Requires scope registration:prepare.

Input schema and example

Arguments

opt_in_url
stringPublic https URL of the SMS opt-in form on your campaign website. An empty string clears the saved value.
privacy_policy_url
stringPublic https URL of your privacy policy. An empty string clears the saved value.
terms_url
stringPublic https URL of your terms of service. An empty string clears the saved value.
opt_in_screenshot_url
stringOptional public https URL of a screenshot of the opt-in form. An empty string clears the saved value.
opt_in_description
stringOptional description of how a person opts in. It must name your opt-in form URL, privacy URL, terms URL, STOP, and HELP, or it is refused. An empty string clears the saved value.
help_email
stringOptional HELP reply contact email address. A saved inbox is never erased by an empty value.

Example arguments

{
  "opt_in_url": "https://friends.example.org/sms",
  "privacy_policy_url": "https://friends.example.org/privacy",
  "terms_url": "https://friends.example.org/terms"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
submit_texting_campaign_registrationrequires confirmdestructiveregistration:submit

File this organization's 10DLC campaign registration and charge the non-refundable review fee for this submission. Owner or admin only, and the organization must be fully set up. The fee comes from the server, never the caller, and the packet is built from the saved compliance draft. It requires compliance_acknowledged true, fee_acknowledged true, confirm true, a unique idempotency_key, and scope registration:submit. Before any fee is charged it validates the draft, fetches the three filed public pages, and runs the same carrier checklist as check_texting_campaign_site. When the business registration is not yet approved it saves the compliance draft as queued and charges nothing. A repeat with the same idempotency_key is already on file and charges nothing; an uncertain carrier outcome is never retried blindly. Optionally pass help_email to set the HELP reply contact, campaign_verify_token when a political organization needs one, and approval_id when this key requires an operator to approve the filing first.

Input schema and example

Arguments

compliance_acknowledgedrequired
booleanMust be true: acknowledges the messaging compliance requirements of the filing.
fee_acknowledgedrequired
booleanMust be true: acknowledges the non-refundable review fee charged for this submission.
confirmrequired
booleanMust be true. Set only after the user agrees to spend and send.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not act twice.
help_email
stringOptional HELP reply contact email address for this filing. Omit to use the saved one.
campaign_verify_token
stringOptional Campaign Verify token for a political organization that needs one. Omit to use the saved token.
approval_id
stringOptional spend approval id for a key that requires an operator to approve each filing.

Example arguments

{
  "compliance_acknowledged": true,
  "fee_acknowledged": true,
  "confirm": true,
  "idempotency_key": "campaign-file-2026-01"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Inbox 2

list_inbox_conversationsread-onlyinbox:read

List inbox conversations for this organization, newest activity first, with id, channel, subject, status, and a short preview. Filter by status or channel. It returns contact display names only, never email addresses, phone numbers, or media, and it does not send a reply.

Input schema and example

Arguments

status
stringone of active, closedOnly conversations in this state.
channel
stringone of sms, emailOnly conversations on this channel.
limit
integermin=1, max=100How many conversations to return. At most 100.

Example arguments

{
  "channel": "sms",
  "status": "active",
  "limit": 50
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_inbox_conversationread-onlyinbox:read

Read one inbox conversation by id, including its recent message history and delivery state. Returns not found when the conversation is not in this organization. It is for read-only triage and does not send, assign, or close anything.

Input schema and example

Arguments

conversation_idrequired
stringInbox conversation id.
limit
integermin=1, max=100How many recent messages to include. At most 100.

Example arguments

{
  "conversation_id": "11111111-1111-4111-8111-111111111111",
  "limit": 100
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Billing 4

get_billing_balanceread-onlybilling:read

Read this organization's real funds: availableBalanceCents is the actual spendable balance (active holds already deducted), and outstandingHoldsCents is the total currently reserved but not yet settled or voided. A failed read is an error, never a fabricated zero. It is read-only, charges nothing, and does not create a payment profile.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_billing_transactionsread-onlybilling:read

Page through this organization's ledger, newest first, with each entry's public id, type, amount in whole cents, the running balance after it, its description, and its timestamp, plus an exact total and a has-more flag. It returns no processor identifiers, idempotency keys, metadata, or another member's private settings, and it changes no business or billing state, though each read records one routine API audit row.

Input schema and example

Arguments

offset
integermin=0, max=1000000How many newest entries to skip. Defaults to 0.
limit
integermin=1, max=100How many entries to return. At most 100.

Example arguments

{
  "offset": 0,
  "limit": 25
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_auto_topup_settingsread-onlybilling:read

Read this organization's saved automatic-replenishment configuration: whether it is enabled, the trigger balance, the top-up amount, the daily caps and cooldown, and the saved payment method's brand, last 4 digits and expiry. It never returns a card number, card identifier, or secret, and it changes no business or billing state, though each read records one routine API audit row.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
update_auto_topup_settingsbilling:write

Save this organization's Auto Top-Up configuration, exactly like Account, Auto Top-Up. Sending enabled true authorizes FUTURE automatic off-session charges against the already-saved, already-authorized card according to the threshold, amount, daily caps and cooldown; it does NOT charge now, add or remove a card, or deposit funds. Enabling requires a card already on file; without one this is refused. The trigger balance is $5–$1,000 (500–100000 cents) and the top-up amount is $10–$1,000 (1000–100000 cents), both whole cents. Saving the same configuration twice is the same as saving it once. The caller must be an active organization owner or admin.

Input schema and example

Arguments

enabledrequired
booleanWhether to enable automatic replenishment. Enabling authorizes future automatic charges against the saved card.
threshold_centsrequired
integermin=500, max=100000Trigger balance in whole cents. Replenishes when the available balance drops below this.
amount_centsrequired
integermin=1000, max=100000Top-up amount in whole cents.

Example arguments

{
  "enabled": true,
  "threshold_cents": 2500,
  "amount_cents": 10000
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Settings 9

get_communications_settingsread-onlysettings:read

Read this organization's sending identity and channel settings: from name and address, reply-to, sending-domain authentication state, setup status, and compliance details. It is redacted and read-only and does not change or verify a domain.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_organization_settingsread-onlysettings:read

Read this organization's identity and compliance settings: committee name, paid-for-by line, mailing address, From name and address, Reply-To, entity type, EIN, legal name, and website, together with setup completion and the exact missing fields. Verification tokens and provider identifiers are never returned. Read-only; it changes no business state (the read records one routine audit row) and registers nothing.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
update_organization_settingssettings:write

Save this organization's identity and compliance settings, exactly like the Account, Organization settings form. It replaces the whole form: every required field below must be sent, and these optional fields are cleared when you omit them: street2, optional contact, EIN, and the default phone. The legal name defaults to the committee name when omitted, and the website falls back to the optional contact when omitted, matching the dashboard. Send a Campaign Verify token only to change it; a saved token mask leaves the stored token in place. The caller must be an active owner or admin. This does not send, register, or charge anything.

Input schema and example

Arguments

committee_namerequired
stringCommittee or campaign name.
authorization_linerequired
stringPaid-for-by / authorized-by line.
physical_address_streetrequired
stringMailing street address.
physical_address_street2
stringMailing address line 2. Cleared when omitted.
physical_address_cityrequired
stringMailing city.
physical_address_staterequired
stringMailing state.
physical_address_ziprequired
stringMailing ZIP.
optional_contact
stringOptional public contact. Cleared when omitted.
reply_to_emailrequired
stringReply-To email address.
email_from_namerequired
stringFrom name for email.
email_from_addressrequired
stringFrom email address.
entity_typerequired
stringone of candidate, pac, party, other_527, 501c3, 501c4, 501c5, 501c6Organization type. Any other value is rejected.
ein
stringOptional EIN. Cleared when omitted.
legal_business_name
stringOptional legal name. Defaults to the committee name when omitted.
website
stringOptional website. When omitted it falls back to the optional contact, matching the dashboard. Send an empty string to clear it without changing the optional contact.
default_campaign_phone_id
stringOptional default sending number id from this organization. Another organization's number is rejected. Cleared when omitted.
campaign_verify_token
stringOptional Campaign Verify token for political texting. A saved mask leaves the stored token unchanged.
campaign_verify_email_token
stringOptional Campaign Verify token for email. A saved mask leaves the stored token unchanged.

Example arguments

{
  "committee_name": "Friends of Ada",
  "authorization_line": "Paid for by Friends of Ada",
  "physical_address_street": "1 Main St",
  "physical_address_city": "Polk City",
  "physical_address_state": "FL",
  "physical_address_zip": "33868",
  "email_from_name": "Friends of Ada",
  "email_from_address": "send@example.org",
  "reply_to_email": "reply@example.org",
  "entity_type": "candidate"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_sending_domainread-onlysettings:read

Read this organization's sending-domain authentication state and the exact DNS records it requires, together with whether the provider identity is verified. For an owned domain it reads the provider directly; a domain this organization does not own is reported as not linked without asking the provider, so it never discloses another organization's domain. Read-only; it claims nothing and changes no business state.

Input schema and example

Arguments

domain
stringOptional domain to read. Omit to use the saved campaign domain.
profile
stringone of campaign, transactional, registryWhich saved profile to read. Defaults to campaign.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
preview_sending_domainread-onlysettings:read

Check whether an ensure, verify, or recover action for a sending domain would be eligible, without claiming the domain, calling the provider, or saving anything. It reports the proposed domain, the blockers that would stop it, and the side effects of the matching configuration call. It never inspects or discloses an unattached provider identity. Read-only.

Input schema and example

Arguments

domain
stringOptional domain to preview.
from_email
stringOptional From address to preview.
profile
stringone of campaign, transactional, registryWhich profile the action would use. Defaults to campaign.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
configure_sending_domainsettings:write

Authenticate a sending domain for this organization: ensure creates the identity and returns the records to publish, verify rechecks an existing identity, and recover resumes a partially completed configuration. Only an active owner or admin in the credential's organization may run it, and it works during an incomplete setup so the From domain can be finished. It never sends a message, charges a balance, turns on a channel, or changes a price, rate, pause, or account state.

Input schema and example

Arguments

actionrequired
stringone of ensure, verify, recoverensure creates and returns records, verify rechecks, recover resumes.
profile
stringone of campaign, transactional, registryWhich saved profile to configure. Defaults to campaign.
domain
stringOptional domain. Defaults to the saved From domain.
from_email
stringOptional From address on that domain. Defaults to the saved From address.

Example arguments

{
  "action": "ensure",
  "from_email": "chair@example.com"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
search_phone_numbersread-onlysettings:read

Search the carrier marketplace for phone numbers this organization can buy. Lists toll-free inventory, or local inventory in a given area code or state, with the one-time setup price and the monthly rental for each number. Use it to find a phone_number to pass to purchase_phone_number. It is read-only: it reserves no funds, orders nothing, and assigns nothing, and it records one routine audit row.

Input schema and example

Arguments

area_code
stringUS area code (3 digits) for a local search. Ignored for a toll-free search.
state
stringTwo-letter US state for a local search. Ignored for a toll-free search.
type
stringone of toll-free, localWhich inventory to search. Defaults to toll-free.

Example arguments

{
  "type": "toll-free"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
purchase_phone_numberrequires confirmdestructivesettings:write

Buy one phone number (toll-free or local) for this organization and charge the one-time setup fee from the organization balance. This spends money and cannot be undone, so it requires confirm true and a unique idempotency_key, and phone_number must be a number returned by search_phone_numbers. A retry with the same idempotency_key reuses one reservation and never orders a second number. Local numbers are automatically attached to the organization's current 10DLC campaign when one is approved. The monthly rental is billed later by the rental job. Pass approval_id only when an operator has approved this exact purchase.

Input schema and example

Arguments

phone_numberrequired
stringThe phone number to buy, in E.164 form, exactly as returned by search_phone_numbers.
confirmrequired
booleanMust be true. Set only after the user agrees to spend.
idempotency_keyrequired
stringUnique 16 to 128 character key so a retry does not buy twice.
approval_id
stringOptional operator approval id for this exact purchase.

Example arguments

{
  "phone_number": "+18005550100",
  "confirm": true,
  "idempotency_key": "phone-purchase-2026"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
set_default_phone_numbersettings:write

Set one active number as the organization's default caller id. It changes settings only: it moves no money and orders nothing, and it does not release or reassign any other number. Returns the id it set. Use list_voice_numbers to find a number_id.

Input schema and example

Arguments

number_idrequired
stringThe id of the active number to make the default.

Example arguments

{
  "number_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Agent runs 2

list_agent_runsread-onlyagent:runs

List durable work runs started by this exact credential in this organization, newest first, with id, status, objective, and timestamps. Use a returned id with get_agent_run. It does not start, update, or delete a run.

Input schema and example

Arguments

limit
integermin=1, max=100How many runs to return. At most 100.

Example arguments

{
  "limit": 50
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_agent_runread-onlyagent:runs

Read one durable work run by id, including its status, objective, summary, and timestamps. Returns not found when the run does not belong to this credential and organization. It is read-only and does not update the run.

Input schema and example

Arguments

run_idrequired
stringAgent run id.

Example arguments

{
  "run_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Conversions 1

add_conversionconversions:write

Record a conversion event against a campaign in this organization, carrying an external id, an optional value in cents, and the time it occurred. Repeating the same external id returns the existing event instead of a duplicate. It does not send, charge, or edit the campaign.

Input schema and example

Arguments

campaign_idrequired
stringCampaign the conversion belongs to.
eventrequired
stringEvent name, such as donation or signup. Lowercase letters, digits, hyphens, underscores.
external_idrequired
stringYour unique id for this event, used to deduplicate retries.
value_cents
integermin=0Optional event value in whole cents.
occurred_at
stringOptional ISO 8601 timestamp for when the event happened.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "event": "donation",
  "external_id": "donation-0001",
  "value_cents": 2500
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Exports 1

export_contactsread-onlyexports:read

Read a page of this organization's contact records as JSON, including consent, verification, and tag fields, with a total count and a has-more flag. Page through because the full list can be large. It returns records inline and does not produce a downloadable file.

Input schema and example

Arguments

page
integermin=1Page number, starting at 1.
limit
integermin=1, max=10000Records per page. At most 10000.

Example arguments

{
  "page": 1,
  "limit": 1000
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Delivery logs 3

list_email_recipientsread-onlylogs:read

List per-recipient delivery status for one email campaign in this organization, including sent, delivered, open, click, bounce, and unsubscribe times plus the charge for each. Read-only and paginated. It does not return the campaign's message content. It does return the audience selectors as segment ids.

Input schema and example

Arguments

campaign_idrequired
stringEmail campaign id.
page
integermin=1Page number, starting at 1.
limit
integermin=1, max=250Page size. At most 250.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "page": 1,
  "limit": 100
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_email_eventsread-onlylogs:read

List delivery events for one email campaign in this organization, newest first, including sends, bounces, and complaints with their event and bounce types. Read-only and paginated. It does not return the recipient roster or the campaign's message content.

Input schema and example

Arguments

campaign_idrequired
stringEmail campaign id.
page
integermin=1Page number, starting at 1.
limit
integermin=1, max=250Page size. At most 250.

Example arguments

{
  "campaign_id": "11111111-1111-4111-8111-111111111111",
  "page": 1,
  "limit": 100
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_audit_logread-onlylogs:read

Page through this organization's audit log, newest first: credential actions plus every paid or bulk action from any source (dashboard, API, MCP, cron, import), such as list cleaning, email or address verification, campaign launches, number and 10DLC purchases, balance holds and imports. Paid entries carry source, outcome (started, succeeded, partial, failed, blocked), estimated and actual cost in cents, the target list or segment ids and names, counts, start and end time, and the request id. Filter by action, source, outcome, actor, API key, request id or date. Use it to answer who did what and when. It never returns campaign message bodies or contact data, and it changes no business state (the read records one routine audit row).

Input schema and example

Arguments

page
integermin=1Page number, starting at 1.
limit
integermin=1, max=250Events per page. At most 250.
action
stringOnly this action, such as email_verification.run. End with * for a prefix.
source
stringone of ui, api, mcp, cron, import, systemOnly entries from this source.
outcome
stringone of started, succeeded, partial, failed, blockedOnly paid or bulk actions with this outcome.
actor_user_id
stringOnly entries by this user id.
key_id
stringOnly entries made with this API key id.
request_id
stringOnly entries from this request id.
paid_only
booleantrue returns only paid and bulk actions.
since
stringISO 8601 start time (inclusive).
until
stringISO 8601 end time (exclusive).

Example arguments

{
  "page": 1,
  "limit": 100
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Other 15

list_my_calling_campaignsread-onlycalls:read

List the prepared calling queues this member may work in the credential's organization, plus this member's OWN active or paused shift session id per queue, if any. Returns the organization's launched calling campaigns with a pending queue; the list is organization-wide, not an individual assignment, and only your own shift ids are personal. A queue's pending_count of null means the count could not be read (unavailable), not zero. `truncated` reports honestly whether more campaigns could exist than were read, and `shiftsTruncated` reports honestly whether your own shift page was capped, so a null session_id cannot be read as proof you have no open shift. It reads no balance, sender identity, contact/audience inventory, or management advice, changes no business state (the read records one routine audit row), and calls nothing.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
update_my_calling_phonecalls:operate

Save the credential owner's OWN operator phone. Accepts only a `phone` value; a caller-supplied user or organization selector is refused. The number is normalized but is NOT verified, NOT provisioned, and NOT rung, and this does not place a call or move any money. It returns only whether a phone was set and its last four digits, never your full profile.

Input schema and example

Arguments

phonerequired
stringYour operator phone as a U.S. number. It is normalized but not verified.

Example arguments

{
  "phone": "+18635550101"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_personal_settingsread-onlyprofile:read

Read the credential owner's OWN personal profile and preferences: full name, personal phone (with its normalized form), time zone, country, default sender name and addresses, SMS signature, quiet hours, opt-in preferences, and notification preferences. The effect is user-wide: these settings belong to the person across every organization they belong to, not to one organization. It returns only the owner's own row, never another user's, and never a role, administrator flag, balance, credential, or secret. It changes no business state (the read records one routine audit row) and sends nothing.

Input schema and example

Arguments

This tool takes no arguments.

Example arguments

{}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
update_personal_settingsprofile:write

Change the credential owner's OWN personal profile and preferences, the same records the Account, About You / Communication / Consent / Notification forms edit. The effect is user-wide: these settings belong to the person across every organization they belong to. Only the fields you pass are changed; an omitted field keeps its stored value, and an empty string or null clears a string field. A saved phone is normalized but is NOT verified, provisioned, or rung. Notification preferences govern FUTURE alerts only; saving them does not send, schedule, or charge anything, and the low-balance threshold is an alert threshold, not a spending limit or Auto Top-Up authority. It cannot change your email/login identity, password, MFA, verification flags, role, membership, organization selection, administrator flags, balance, spending authorization, or API credentials.

Input schema and example

Arguments

full_name
string | nullnullableYour full name. Omit to keep it; send an empty string or null to clear it.
personal_phone
string | nullnullableYour personal U.S. phone number. It is normalized but not verified. Omit to keep it; send an empty string or null to clear it.
timezone
string | nullnullableIANA time zone, such as America/New_York. Omit to keep it; send an empty string or null to clear it.
country
string | nullnullableTwo-letter country code, such as US. Omit to keep it; send an empty string or null to clear it.
default_from_name
string | nullnullableDefault sender (From) name. Omit to keep it; send an empty string or null to clear it.
default_from_email
string | nullnullableDefault sender (From) email address. Omit to keep it; send an empty string or null to clear it.
default_reply_to_email
string | nullnullableDefault Reply-To email address. Omit to keep it; send an empty string or null to clear it.
default_sms_signature
string | nullnullableDefault SMS signature. Omit to keep it; send an empty string or null to clear it.
quiet_hours_enabled
booleanWhether quiet hours are on. Omit to keep it.
quiet_hours_start
string | nullnullableQuiet-hours start time, such as 21:00. Omit to keep it; send an empty string or null to clear it.
quiet_hours_end
string | nullnullableQuiet-hours end time, such as 09:00. Omit to keep it; send an empty string or null to clear it.
opt_in_methods
array | nullnullableSaved opt-in methods. This is a saved preference, not recipient-consent evidence. Omit to keep the stored list; send an empty list or null to clear it.
opt_in_description
string | nullnullableSaved opt-in description. Omit to keep it; send an empty string or null to clear it.
billing_contact_email
string | nullnullableBilling contact email address. Omit to keep it; send an empty string or null to clear it.
low_balance_threshold_cents
integermin=0Low-balance ALERT threshold in whole cents. This is not a spending limit. Omit to keep it; 0 is a real value, not an omission.
usage_notifications_enabled
booleanWhether usage notifications are on. Omit to keep it.
daily_spend_alerts_enabled
booleanWhether daily-spend alerts are on. Omit to keep it.

Example arguments

{
  "full_name": "Ada Lovelace",
  "personal_phone": "+18635550101",
  "timezone": "America/New_York",
  "billing_contact_email": "billing@example.org"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
record_form_submissionintake:write

Record one website form submission as a contact in this organization, using the same consent and suppression engine the website endpoint uses. Provide an email, a phone number, or both, plus the source name. A checked opt-in box needs its verbatim consent text; an unchecked box withholds that channel. A dated opt-out, a STOP, or a live suppression is never cleared, even by a checked box. The contact change and its receipt commit in one serialized transaction, so reusing the same external_id makes a concurrent or sequential duplicate replay the first accepted receipt as a duplicate without a second mutation, and a same-key conflict is never overwritten. A receipt is the historical outcome of the first accepted write, not proof that the stored contact still matches this request (later legitimate edits can change it); an interrupted keyed retry is not auto-resent, so read the receipt for that external_id first. With no external_id there is no dedupe or replay and a repeated submission is a separate operation. No message is sent and no charge is made.

Input schema and example

Arguments

email
stringEmail address. Stored lowercased. Provide this, a phone, or both.
phone
stringU.S. phone number. Stored as E.164. Provide this, an email, or both.
first_name
stringFirst name, up to 80 characters. Empty leaves the saved value.
last_name
stringLast name, up to 80 characters. Empty leaves the saved value.
street
stringStreet address, up to 200 characters. Empty leaves the saved value.
city
stringCity, up to 80 characters. Empty leaves the saved value.
state
stringState. A two-letter value is stored uppercased. Empty leaves the saved value.
zip
stringPostal code, up to 10 characters. Use postal_code when you only have that name.
postal_code
stringPostal code alias accepted when zip is omitted.
sourcerequired
stringShort form name such as volunteer, membership, contact, newsletter, or event. Letters, numbers, underscore, hyphen, up to 40.
email_opt_in
booleanWhether the email box was checked. Omitted means false. A real false is preserved.
sms_opt_in
booleanWhether the text box was checked. Omitted means false. A real false is preserved.
email_consent_text
stringThe email checkbox label, verbatim, 3 to 2000 characters. Required when email_opt_in is true.
sms_consent_text
stringThe text checkbox label, verbatim, 3 to 2000 characters. Required when sms_opt_in is true.
opt_in_ip_address
stringIPv4 or IPv6 text of the consenting device. Stored when this submission records text consent.
opt_in_attestation
booleanOperator attestation for the recorded text consent. Omitted defaults to true when text consent is recorded.
locale
stringLanguage tag such as en or es-US.
submitted_at
stringISO-8601 time of the submission, not in the future. Used as the consent and confirmation time. Omitted means the server time.
external_id
stringStable id for this submission, up to 128 characters. Reusing it replays the FIRST accepted submission as a duplicate instead of a second write; the contact and its receipt commit atomically, so a concurrent duplicate never re-mutates the contact. An interrupted keyed retry is not auto-resent; read the receipt for this external_id first.
attributes
object<string, string | number | boolean>additionalProperties: string | number | booleanUp to 40 extra fields from the form, as a map of field name to a text, number, or boolean value. Reserved keys (email, phone, consent and opt-out fields, form_source, locale, opt_in_*) are ignored by the intake core. Names are trimmed to 40 characters and values to 500.

Example arguments

{
  "email": "ada@example.org",
  "phone": "863-555-0148",
  "first_name": "Ada",
  "last_name": "Lovelace",
  "source": "volunteer",
  "email_opt_in": true,
  "email_consent_text": "Send me email updates from the campaign.",
  "external_id": "volunteer-form-100",
  "attributes": {
    "shift": "saturday",
    "student": true,
    "year": 2026
  }
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
get_form_submissionread-onlyintake:write

Read the persisted receipt of a past form submission by the external_id that was sent, inside this organization. Use this to recover after an interrupted submission: a created/updated result is the historical outcome of the first accepted write and an identity_conflict receipt names both contacts that were left unchanged. The receipt does not prove the stored contact still matches any later request, so look the contact up directly when current values matter. A missing receipt is a 404 error, not a success. Read-only: it changes nothing.

Input schema and example

Arguments

external_idrequired
stringThe external_id sent with the original submission, up to 128 characters.

Example arguments

{
  "external_id": "volunteer-form-100"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_team_membersread-onlyteam:read

Read the authorized organization's team roster: each member's id, email, display name, canonical role and membership status, membership timestamps where the schema supports them, and whether the member is the protected organization owner. The organization is the one that owns this credential; no argument selects it. Authorization is canonical: role and status come from that organization's membership row, so a member whose own selected organization is elsewhere is still listed here with THIS organization's role. Removed canonical members are excluded and are never restored from a stale profile pointer. Reading requires the credential's membership and user account to be ACTIVE; a read-only organization state such as a locked organization stays readable, but a suspended or removed membership does not. This is a bounded, read-only page; total is the true number of distinct members, not one page's length. It returns no balances, no platform-administrator flags, no secrets, no tokens, and no other organization's membership. It changes no business state; the read records one routine API audit row. This tool itself does not invite, remove, or change anyone; those are the separate team:manage tools (create_team_invitation, resend_team_invitation, cancel_team_invitation, change_team_member_role, suspend_team_member, reactivate_team_member, remove_team_member).

Input schema and example

Arguments

page
integermin=1Page number, starting at 1.
limit
integermin=1, max=100Roster page size. At most 100.

Example arguments

{
  "page": 1,
  "limit": 50
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
list_team_invitationsread-onlyteam:read

Read the authorized organization's CURRENT pending invitations: id, email, role, created_at, and expires_at for invitations that are not accepted, not cancelled, not dismissed, and not expired, newest first. The organization is the one that owns this credential; no argument selects it. Reading requires the credential's membership and user account to be ACTIVE; a read-only organization state such as a locked organization stays readable, but a suspended or removed membership does not. It does NOT return an invitation token, a copy-link value, or the full history of past or accepted invitations, and it does not send or resend anything. It changes no business state; the read records one routine API audit row. A bounded, read-only page; total is the true count, not one page's length.

Input schema and example

Arguments

page
integermin=1Page number, starting at 1.
limit
integermin=1, max=100Invitation page size. At most 100.

Example arguments

{
  "page": 1,
  "limit": 50
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
create_team_invitationteam:manage

Invite one person to the credential's organization as an admin, member, or volunteer, using the same invitation workflow the dashboard uses. The acting organization and the inviter come only from the credential; the body accepts only an email and role. A person who already has a membership of any status is refused and should be reactivated instead; a person with a live pending invitation returns a conflict. The response exposes only safe invitation metadata and a truthful `queued` acknowledgment: it means a source email event was written, NOT that the email was sent or delivered. It creates no organization, grants no role, moves no money, and never returns an invite token or a whole user row.

Input schema and example

Arguments

emailrequired
stringInvitee email address. Normalized to lower case.
rolerequired
stringone of admin, member, volunteerThe role the invitee will hold if they accept.

Example arguments

{
  "email": "person@example.org",
  "role": "member"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
resend_team_invitationteam:manage

Re-queue the invitation email for a still-pending invitation in the credential's organization. This is NOT idempotent: there is no request-key store and each call is a new email request, exactly like the dashboard's re-queue action. It exposes no token, sends no email itself, and moves no money. If the outcome cannot be confirmed, read the current invitation state rather than retrying automatically.

Input schema and example

Arguments

invitation_idrequired
stringTeam invitation id (UUID).

Example arguments

{
  "invitation_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
cancel_team_invitationteam:manage

Cancel a still-pending invitation in the credential's organization. A person can be invited again afterwards. Cancelling an invitation that is already accepted, cancelled, or dismissed is refused. It sends nothing and moves no money.

Input schema and example

Arguments

invitation_idrequired
stringTeam invitation id (UUID).

Example arguments

{
  "invitation_id": "11111111-1111-4111-8111-111111111111"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
change_team_member_roleteam:manage

Change an ordinary member's role between admin and member in the credential's organization. The target is the member id in the argument, never a body selector. Promotion to owner is refused, the organization owner cannot be changed, and you cannot change your own role. The result is read back from the live membership; a readback that cannot be established is reported as uncertain, not as success or a proven no-write.

Input schema and example

Arguments

member_idrequired
stringTeam member user id (UUID).
rolerequired
stringone of admin, memberThe member's new role.

Example arguments

{
  "member_id": "22222222-2222-4222-8222-222222222222",
  "role": "admin"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
suspend_team_memberteam:manage

Suspend an ordinary active member in the credential's organization, dropping them to read-only. The organization owner cannot be suspended, you cannot suspend yourself, and the last active admin cannot be suspended. An optional note is recorded on the audit trail. The result is read back from the live membership.

Input schema and example

Arguments

member_idrequired
stringTeam member user id (UUID).
note
stringOptional note recorded on the team audit trail.

Example arguments

{
  "member_id": "22222222-2222-4222-8222-222222222222",
  "note": "On leave"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
reactivate_team_memberteam:manage

Reactivate a suspended member in the credential's organization. The organization owner cannot be acted on and you cannot reactivate yourself. A member who is not suspended is refused. An optional note is recorded on the audit trail. The result is read back from the live membership.

Input schema and example

Arguments

member_idrequired
stringTeam member user id (UUID).
note
stringOptional note recorded on the team audit trail.

Example arguments

{
  "member_id": "22222222-2222-4222-8222-222222222222"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
remove_team_memberdestructiveteam:manage

Remove an ordinary member from the credential's organization. This ends their membership; it cannot be undone through this surface. The organization owner cannot be removed, you cannot remove yourself, and the last active admin cannot be removed. An optional note is recorded on the audit trail. This removes a membership only: it does not delete the person's account, transfer data, or move money.

Input schema and example

Arguments

member_idrequired
stringTeam member user id (UUID).
note
stringOptional note recorded on the team audit trail.

Example arguments

{
  "member_id": "22222222-2222-4222-8222-222222222222"
}
Complete input schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Resources & prompts

Alongside tools, the server can publish documentation resources and workflow prompts. They explain capabilities: they never grant scopes or load another tenant.

  • campaigncommander://docs/quickstart: read-only.
  • Workflow prompts contain instructions, not customer data or secrets, and never execute tools themselves.

Resources and prompts are not supported equally by every host. A host without them can read the equivalent public HTTP documents and the tool schemas instead, which are the fallback here.

Workflow recipes

18 executable recipes. Ordered steps run in sequence; a “choose exactly one” group is an alternative: a send and a schedule are never presented as two consecutive actions.

Billing: inspect funds and transaction history

Read funds, ledger history and existing Auto Top-Up configuration without initiating a payment or changing settings.

Preconditions: An organization-bound credential with billing:read and the app's owner/admin financial access.

billing:read
  1. 01get_billing_balance

    Read available funds and outstanding reservations in whole USD cents. Holds are already deducted from the available balance; do not subtract them again.

    Preconditions: billing:read.

    Outputs: Available balance, outstanding holds, currency and observation time. These are separate reads, not an atomic snapshot.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: billing:read

  2. 02list_billing_transactions

    Read the requested ledger page. When collecting the full history, advance offset by rows actually returned and continue until hasMore is false; do not mistake a server-capped page for the whole ledger.

    Preconditions: billing:read. Use a bounded limit and an offset beginning at zero for a new traversal.

    Outputs: Public ledger entries and exact pagination total/hasMore. Entries can change between requests; deduplicate by public entry id during a traversal.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: billing:read

  3. 03get_auto_topup_settings

    Inspect current replenishment settings, caps, cooldown and saved-card summary. An absent settings row is not permission to add a card or charge one.

    Preconditions: billing:read.

    Outputs: Saved configuration and limited payment-method summary, or null when no configuration exists.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: billing:read

Bounded by

  • gap.billing-and-autotopup

Billing: configure existing Auto Top-Up

Change an explicitly requested replenishment configuration, then read the persisted settings back. This is not a deposit or card-entry workflow.

Preconditions: The user has authorized this configuration change, not merely requested a balance check. An active organization owner/admin credential with billing:read and billing:write. Enabling requires an already-saved, already-authorized card and permits future automatic charges. Incomplete setup does not block this configuration control.

billing:readbilling:write
  1. 01get_auto_topup_settings

    Read the existing configuration before choosing the complete requested enabled, threshold_cents and amount_cents values. Do not infer an authorization to enable automatic payments from this read.

    Preconditions: billing:read.

    Outputs: Current settings, saved-card summary and existing guardrails, or null.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: billing:read

  2. 02update_auto_topup_settings

    Save the requested enabled flag, trigger balance and replenishment amount. Preserve the existing card, authorization metadata, caps and cooldown.

    Preconditions: billing:write. Explicit complete configuration: enabled boolean; threshold_cents 500–100000; amount_cents 1000–100000; amounts are whole cents. An already-authorized saved card when enabling.

    Outputs: The saved configuration. Read it back and compare all three requested settings before reporting success.

    Side effects: Updates configuration and records a routine audit row. Enabling permits future automatic charges; this call does not collect payment, add a card or deposit funds.

    Read back with get_auto_topup_settings.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read back after an uncertain result. The same configuration is idempotent, but do not overwrite a newer user change blindly.

    Scopes: billing:write

Bounded by

  • gap.billing-and-autotopup

Connect and discover capabilities

Authenticate, then read exactly what this credential may do before doing anything else. Nothing here changes data.

Preconditions: An organization API key (Authorization: Bearer cc_live_...) or an OAuth 2.1 access token issued by this server. The key's issuer is an active owner or admin of the organization.

  1. 01get_capabilities

    Read the granted scopes, the organization the credential acts in, and whether setup is complete. This is the only tool a credential may call before setup is finished.

    Preconditions: A valid credential.

    Outputs: Granted scopes. Organization binding. Setup completion and the questions to ask the operator.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

Bounded by

  • gap.team-credentials

Inspect and repair organization setup

Read the sender and organization settings, show the exact missing fields, and save a complete packet so sends are accepted.

Preconditions: Owner or admin role for the save step. The settings:read scope to read them and settings:write to save.

settings:readsettings:write
  1. 01get_organization_settings

    Read the committee identity, mailing address, sending identity, entity metadata, and the exact missing fields.

    Preconditions: settings:read.

    Outputs: Saved settings. A setup.complete flag and the missing field list.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: settings:read

  2. 02get_communications_settings

    Read the sender from name, from address, reply-to, the public compliance block, and the sending domain's authentication state with the records it requires.

    Preconditions: settings:read.

    Outputs: Sender and compliance summary. The sending domain's state and, for an owned domain, the exact DNS records to publish.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: settings:read

  3. 03preview_sending_domain

    Check whether authenticating the From domain would be eligible before making any change.

    Preconditions: settings:read.

    Outputs: The proposed domain, an eligibility flag, the blockers, and the side effects of configuring it.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: settings:read

  4. 04get_sending_domain

    Read the sending domain's authentication state and the exact DNS records that must be published.

    Preconditions: settings:read.

    Outputs: Ownership, verification state, and the required DNS records.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: settings:read

  5. 05configure_sending_domain

    Create, recheck, or resume the sending domain so its DNS records can be published and verified.

    Preconditions: settings:write. Owner or admin. Action confirmed with the operator.

    Outputs: The updated domain state and the records to publish.

    Side effects: Creates or rechecks a domain identity. Does not send, charge, or turn on a channel.

    Read back with get_sending_domain.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Re-running ensure or verify is safe: it rechecks the domain rather than creating a duplicate identity.

    Scopes: settings:write

  6. 06update_organization_settings

    Save the whole settings form once the operator has supplied the missing values.

    Preconditions: settings:write. Owner or admin. Values confirmed with the operator.

    Outputs: The saved settings and the recomputed setup completion.

    Side effects: Replaces the organization settings form. Does not send, register, or charge.

    Read back with get_organization_settings.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Re-sending the identical form is safe; it overwrites with the same values and does not send.

    Scopes: settings:write

Bounded by

  • gap.domain-configuration
  • gap.phone-defaults

Personal profile and preferences

Read and change the credential owner's OWN personal profile and preferences: name, personal phone, time zone, country, sender defaults, SMS signature, quiet hours, opt-in preferences, and notification preferences. The effect is user-wide: these settings belong to the person across every organization they belong to.

Preconditions: The profile:read scope to read and profile:write to save. The credential owner is an active owner or admin (current eligibility).

profile:readprofile:write
  1. 01get_personal_settings

    Read the owner's own personal profile and preferences, including the normalized phone readback. Returns only the owner's own row, never another user's, and never a role, administrator flag, balance, credential, or secret.

    Preconditions: profile:read.

    Outputs: The saved personal profile. The normalized personal phone readback.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: profile:read

  2. 02update_personal_settings

    Save a personal profile/preference patch once the operator has confirmed the values. Only the fields passed are changed; an omitted field is kept.

    Preconditions: profile:write. Owner or admin. Values confirmed with the operator.

    Outputs: The saved personal profile and the list of changed fields.

    Side effects: Updates the owner's own personal row. A saved phone is normalized but NOT verified, provisioned, or rung. Notification preferences govern future alerts only; saving them does not send, schedule, or charge.

    Read back with get_personal_settings.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Re-sending the identical patch is safe; it writes the same values and does not send.

    Scopes: profile:write

Bounded by

  • gap.member-credential-parity

Build and confirm an audience

Find or create contacts, resolve a natural-language audience to a saved list, size it, and snapshot its membership. Everything here is free and reversible.

Preconditions: contacts:read and lists:read to read; contacts:write and lists:write to change.

lists:readlists:writecontacts:read
  1. 01resolve_list

    Turn a plain-language audience ('my donors') into one saved list, or a set of candidates to confirm.

    Preconditions: lists:read.

    Outputs: A single resolved list, or needs_confirmation with candidates.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: lists:read

  2. 02preview_list

    Count how many contacts a saved-audience definition would match without saving it.

    Preconditions: lists:read.

    Outputs: A contact count, never the contacts themselves.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: lists:read

  3. 03create_segment

    Save the audience as a reusable list once its filters are agreed.

    Preconditions: lists:write. The filters confirmed with the operator.

    Outputs: The new list id and its matched contact count.

    Side effects: Creates one saved list. Sends nothing and charges nothing.

    Read back with get_segment.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Repeating creates a second list. Check get_segment first if a retry is uncertain.

    Scopes: lists:write

  4. 04get_segment

    Read a saved list by id, including its filters and current contact count.

    Preconditions: lists:read.

    Outputs: The stored list record.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: lists:read

  5. 05change_segment_members

    Add or remove contacts on a static tag list.

    Preconditions: lists:write. A static list whose only filter is tags. At most 100 contact ids per call.

    Outputs: The number of members added or removed.

    Side effects: Adds or removes the list's tags on those contacts. Sends nothing and charges nothing.

    Read back with get_segment.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Adding an already-present member is a no-op; the call reports the change it made.

    Scopes: lists:write

  6. 06list_contacts

    Search, sort, and filter contacts by name, email, or phone to build or check a list.

    Preconditions: contacts:read.

    Outputs: A page of contacts, ordered by sort_by (created_at, first_name, last_name, email, phone) and sort_order (asc, desc), optionally kept to those that have an email, phone, or address on file with filter_type. An exact email or phone returns one contact and ignores q, tag, sort_by, sort_order, filter_type, page, and limit. A presence filter means the field is not NULL in the database, not that it is verified, deliverable, or opted in.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: contacts:read

Bounded by

  • gap.campaign-registration

Email: draft, test, send, report

Build an email piece, verify the audience and cost, send one proof, send or schedule the live campaign, then read recipients and delivery events back.

Preconditions: email:read, email:draft, and email:test for the draft and proof; email:send for the live send and schedule. Setup complete (sender identity). An agreed audience, message, and spend.

email:reademail:draftemail:testemail:sendlogs:read
  1. 01create_email_draft

    Create an unsent email draft with a name, subject, body, and a recipient selection.

    Preconditions: email:draft.

    Outputs: The draft campaign id.

    Side effects: Creates one unsent draft. Sends nothing and charges nothing.

    Read back with get_email_draft.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Repeating creates a second draft. Read the campaign back first if a retry is uncertain.

    Scopes: email:draft

  2. 02set_email_audience

    Set or replace the draft's audience and rebuild its recipient snapshot.

    Preconditions: email:draft. An unscheduled draft.

    Outputs: The updated audience and recipient count.

    Side effects: Changes the draft's recipient snapshot only.

    Read back with get_email_draft.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Re-applying the same audience selection is safe, but a segment is re-resolved at call time: the same saved selection can match a changed contact set, so read the draft back to confirm the current recipient count rather than assuming the previous set.

    Scopes: email:draft

  3. 03preview_email_audience

    Size the would-be campaign and read its estimated cost and blockers before spending.

    Preconditions: email:draft.

    Outputs: Recipient count. Estimated cost. Blockers.

    Side effects: No data change beyond the routine audit row; never charges.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: email:draft

  4. 04list_test_recipients

    See which extra addresses may receive a test send, and whether each one is still pending or already verified.

    Preconditions: email:test.

    Outputs: Each address and its pending or verified status.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: email:test

  5. 05add_test_recipient

    Allow one more address to receive test sends after that address confirms the verification link.

    Preconditions: email:test.

    Outputs: The address and whether a verification email was sent.

    Side effects: Sends one verification email when the address is new or the previous link is old enough to replace. Does not send a campaign and does not charge.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Repeating a verified address sends nothing. A pending address is not emailed again within ten minutes.

    Scopes: email:test

  6. 06remove_test_recipient

    Take an address off the test-recipient list.

    Preconditions: email:test.

    Outputs: Confirmation that the address was removed.

    Side effects: The address can no longer receive test sends unless it is the owner or an active member.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Removing an address that is already gone returns not found. Read the list again before retrying.

    Scopes: email:test

  7. 07test_email_campaign

    Send one proof to the credential owner, an active member, or a verified test recipient.

    Preconditions: email:test. Recipients are the key owner's address, active members of the same organization, or verified test recipients.

    Outputs: Per-recipient test results.

    Side effects: Sends real email to those test addresses and bills each test on its own.

    Confirmation: required. The runner refuses this call without confirm true and a well-formed idempotency_key.

    Retry: Every proof is paid: it needs confirm true and a fresh idempotency_key even for a single recipient, because the runner gates the whole tool and not a recipient count. Reuse the same key so a repeat does not send a second proof.

    Scopes: email:test

  8. 08
    Choose exactly one: Deliver now or schedule for later?

    Take exactly one. `send_email_campaign` starts delivery immediately; `schedule_email_campaign` queues delivery for a future time. They are not sequential steps: an agent must never call both for the same draft in one run.

    • send_email_campaign: Send the prepared campaign now and spend organization balance. (Retry: Do not retry blindly. The call returns an accepted send, not a finished delivery. Read the campaign status back, then read list_email_events for the queued/sent/delivered evidence before treating it as done; reuse the same idempotency_key so a repeat does not send a second time.)
    • schedule_email_campaign: Queue the prepared campaign for a future send at a chosen ISO-8601 time. (Retry: A retry of the same schedule with the same idempotency_key returns the scheduled campaign and does not move the time.)
  9. 09list_email_recipients

    Read the per-recipient delivery rows for a campaign.

    Preconditions: logs:read.

    Outputs: Recipient rows with status and timestamps.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: logs:read

  10. 10list_email_events

    Read delivery events (queued, sent, delivered, bounced, opened, clicked) for a campaign. Use this as the delivery evidence after a send.

    Preconditions: logs:read.

    Outputs: Delivery events with status.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: logs:read

SMS: readiness, draft, send, report

Check texting readiness, draft a text or MMS, preview the audience, send one proof, send or schedule, then read recipients, events, and outcomes.

Preconditions: sms:read, sms:draft, and sms:test for the draft and proof; sms:send for the live send and schedule. Texting readiness satisfied (brand registered and a sending number assigned).

sms:readsms:draftsms:testsms:sendlogs:read
  1. 01get_sms_readiness

    Check whether the organization can text: registration state and an assigned sending number.

    Preconditions: sms:read.

    Outputs: A readiness verdict with the reasons it is not ready.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: sms:read

  2. 02create_sms_draft

    Create an unsent text or MMS draft with its message and audience. Set type mms and pass an image to make a picture message; the image is stored as a publicly readable asset.

    Preconditions: sms:draft.

    Outputs: The draft campaign id.

    Side effects: Creates one unsent draft. An MMS image is stored as a publicly readable asset. Sends nothing and charges nothing.

    Read back with get_sms_campaign.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Repeating creates a second draft. Read it back first if a retry is uncertain.

    Scopes: sms:draft

  3. 03set_sms_audience

    Replace an unscheduled text draft's audience and rebuild its recipient snapshot and cost estimate.

    Preconditions: sms:draft. An unscheduled draft.

    Outputs: The updated audience, recipient count, and cost estimate.

    Side effects: Changes the draft's recipient snapshot and estimate only. Sends nothing and does not move organization balance.

    Read back with get_sms_campaign.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Re-applying the same audience selection is safe, but a list is re-resolved at call time: the same saved selection can match a changed contact set, so read the draft back to confirm the current recipient count rather than assuming the previous set.

    Scopes: sms:draft

  4. 04update_sms_draft

    Revise an unsent draft's name, message, or channel. On an MMS draft a text-only edit keeps the current image, a new image replaces it, and setting type sms removes it.

    Preconditions: sms:draft.

    Outputs: The updated draft.

    Side effects: Updates one unsent draft. A replacement image is stored as a publicly readable asset. Sends nothing and charges nothing.

    Read back with get_sms_campaign.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Repeating revises the same draft. Read it back first if a retry is uncertain.

    Scopes: sms:draft

  5. 05preview_sms_audience

    Size the would-be text and read its estimated cost before spending.

    Preconditions: sms:draft.

    Outputs: Recipient count and estimated cost.

    Side effects: No data change beyond the routine audit row; never charges.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: sms:draft

  6. 06test_sms_campaign

    Send one proof text to the credential owner or up to five same-organization addresses.

    Preconditions: sms:test. Same recipient rules as the email proof.

    Outputs: Per-recipient test results.

    Side effects: Sends real texts to those test addresses and bills each.

    Confirmation: required. The runner refuses this call without confirm true and a well-formed idempotency_key.

    Retry: Every proof is paid: it needs confirm true and a fresh idempotency_key even for a single recipient, because the runner gates the whole tool and not a recipient count. Reuse the same key so a repeat does not send a second proof.

    Scopes: sms:test

  7. 07
    Choose exactly one: Deliver now or schedule for later?

    Take exactly one. `send_sms_campaign` dispatches immediately; `schedule_sms_campaign` queues dispatch for a future time. They are not sequential steps: an agent must never call both for the same draft in one run.

    • send_sms_campaign: Dispatch the prepared text now and spend organization balance. (Retry: Do not retry blindly. The call returns an accepted dispatch, not a finished delivery. Read the campaign status back, then read list_sms_events and get_sms_outcomes for the sent/delivered/failed evidence before treating it as done; reuse the same idempotency_key so a repeat does not send a second time.)
    • schedule_sms_campaign: Queue the prepared text for a future dispatch at a chosen ISO-8601 time. (Retry: A retry of the same schedule with the same idempotency_key returns the scheduled campaign and does not move the time.)
  8. 08list_sms_recipients

    Read the per-recipient delivery rows for a text campaign.

    Preconditions: sms:read and logs:read.

    Outputs: Recipient rows with status.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: sms:read, logs:read

  9. 09list_sms_events

    Read delivery events for a text campaign.

    Preconditions: sms:read and logs:read.

    Outputs: Delivery events with status.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: sms:read, logs:read

  10. 10get_sms_outcomes

    Read the delivery outcome summary (delivered, undelivered, failed) for a text campaign.

    Preconditions: sms:read and logs:read.

    Outputs: Outcome counts.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: sms:read, logs:read

Bounded by

  • gap.campaign-registration

Transactional email and templates

Manage reusable transactional templates, then send a one-off system email. Templates are a save, not a send; the send is a confirm-gated paid action.

Preconditions: email:transactional. A verified sending domain for the From address.

email:transactional
  1. 01list_email_templates

    List the organization's saved transactional templates.

    Preconditions: email:transactional.

    Outputs: Template summaries with ids.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: email:transactional

  2. 02create_email_template

    Save a new transactional template with a subject and at least one body.

    Preconditions: email:transactional. A unique name within the organization.

    Outputs: The new template id.

    Side effects: Creates one saved template. Sends nothing and charges nothing.

    Read back with get_email_template.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: A duplicate name is refused with 409; a repeat creates no second row.

    Scopes: email:transactional

  3. 03update_email_template

    Change a template's subject or body. Only the fields you pass change.

    Preconditions: email:transactional.

    Outputs: The updated template.

    Side effects: Updates one saved template. Sends nothing and charges nothing.

    Read back with get_email_template.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Repeating the same values is safe; an empty update is refused with 400.

    Scopes: email:transactional

  4. 04send_transactional_email

    Send one transactional email using a template or inline subject and body.

    Preconditions: email:transactional. A From address on a verified domain. The recipient confirmed with the operator. confirm true and a fresh idempotency_key.

    Outputs: The send result and log id.

    Side effects: Sends real email and charges the organization balance.

    Read back with get_transactional_email.

    Confirmation: required. The runner refuses this call without confirm true and a well-formed idempotency_key.

    Retry: Do not retry blindly. If the outcome is uncertain, read the log row back; reuse the same idempotency_key so a repeat is a no-op.

    Scopes: email:transactional

  5. 05get_transactional_email

    Read one transactional email's log row by id.

    Preconditions: email:transactional.

    Outputs: The stored log row.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: email:transactional

Texting brand registration: preview, optional approval, submit, status

Read the stored brand filing state, preview a would-be packet, optionally route it through the configured approval policy, submit the paid filing, and read the status back.

Preconditions: registration:read to preview and read status; registration:submit to submit. Owner role and complete setup for submission. An agreed one-time brand filing fee.

registration:readregistration:submit
  1. 01get_texting_brand_registration

    Read the stored brand filing state, the authoritative fee, and whether the credential is the active, fully-set-up owner.

    Preconditions: registration:read.

    Outputs: Filing state, fee, and eligibility that means role-and-setup only (not spending authority).

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: registration:read

  2. 02preview_texting_brand_registration

    Validate would-be brand details against the saved settings and return the required fixes and the fee.

    Preconditions: registration:read.

    Outputs: A ready flag that means field validation passed only, the missing fields, and the fee.

    Side effects: No data change beyond the routine audit row; files nothing and charges nothing.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: registration:read

  3. 03request_texting_brand_approval

    When this key has a configured spend limit, request authorization for the filing instead of submitting directly. This is the existing configured policy, not a new consent gate.

    Preconditions: registration:submit. The key has a standing spend limit set by its owner.

    Outputs: An approval id to pass to the submit step once someone approves.

    Side effects: Records an approval request. Files nothing and charges nothing.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: A new request supersedes nothing; read the approval list back if unsure.

    Scopes: registration:submit

  4. 04submit_texting_brand_registration

    Submit the paid brand filing built from the saved identity and the credential owner's representative fallbacks.

    Preconditions: registration:submit. Owner role and complete setup. A valid preview. confirm true, a fresh idempotency_key, and the fee acknowledgement.

    Outputs: The filing result and the charged fee.

    Side effects: Charges the non-refundable one-time brand fee and files with the carrier. Cannot be recalled.

    Read back with get_texting_brand_registration.

    Confirmation: required. The runner refuses this call without confirm true and a well-formed idempotency_key.

    Retry: Do not retry blindly. If the carrier outcome is uncertain, read the status back and reconcile; reuse the same idempotency_key so a replay does not double-charge or double-file.

    Scopes: registration:submit

Texting campaign registration: read readiness and run the free site preflight

Read the stored campaign-registration state, save a compliance draft, and run the free website-compliance preflight. Paid campaign filing is available through submit_texting_campaign_registration.

Preconditions: registration:read to read readiness; registration:prepare to run the free site preflight. Owner or admin role: the dashboard's campaign surface is owner/admin only, and the versioned endpoints match that boundary. An organization-bound credential. Reading readiness works while setup is incomplete; the site preflight requires a complete setup.

registration:readregistration:prepare
  1. 01get_texting_campaign_registration

    Read the current filing status, rejection and retry notes, the frozen filed packet, the resumable draft, and the persisted free site-check history.

    Preconditions: registration:read.

    Outputs: The locally stored filing state and whether the credential can resume Step 2. The frozen filed packet and the current draft (your own brand names, URLs, and copy). The append-only site-check history with timestamps. The filing flags are local only: already_filed means a carrier campaign reference is recorded, not approval or delivery, and a missing reference is not proof the carrier received nothing; confirmation_required or submitting mean do not submit another filing; none of these flags establish whether a fee was charged, so a missing carrier identity is never permission to submit.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: registration:read

  2. 02check_texting_campaign_site

    Validate the opt-in, privacy, and terms URLs against the live public pages and return the same carrier checklist the paid submit enforces, recording one timestamped history row.

    Preconditions: registration:prepare. Public https opt-in, privacy, and terms URLs on the organization's own domain; a platform or reseller host is refused. A complete organization setup.

    Outputs: Whether the site passes, the failing labels, and the per-page checks. One immutable history row with the authenticated organization and the check time.

    Side effects: Fetches the organization's public pages and appends one append-only history row. Charges nothing, files nothing with any carrier, and creates no profile or number.

    Read back with get_texting_campaign_registration.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Not idempotent: each call appends a new timestamped history row. Safe to repeat with the same URLs; a failed append is returned as an error, never as durable evidence.

    Scopes: registration:prepare

Bounded by

  • gap.campaign-registration

Physical mail: draft, preview, launch

Create a physical-mail piece with base64 artwork, size the audience, launch the campaign, and read its status. Mail is the one channel that cannot be recalled.

Preconditions: mail:read to preview; mail:draft to create; mail:send to launch. An agreed audience, artwork, and spend.

mail:readmail:draftmail:send
  1. 01create_mail_draft

    Create a physical-mail draft, assembling the base64 artwork into the upload the endpoint expects. Confirm-gated.

    Preconditions: mail:draft. confirm true and a fresh idempotency_key.

    Outputs: The draft campaign id.

    Side effects: Creates one draft with its artwork. Prints nothing and charges nothing yet.

    Read back with get_mail_campaign.

    Confirmation: required. The runner refuses this call without confirm true and a well-formed idempotency_key.

    Retry: Reuse the same idempotency_key so a retry does not create a second draft.

    Scopes: mail:draft

  2. 02preview_mail_audience

    Size the physical-mail audience and read the estimated cost.

    Preconditions: mail:read.

    Outputs: Recipient count and estimated cost.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: mail:read

  3. 03launch_mail_campaign

    Launch the physical-mail campaign and charge the organization balance.

    Preconditions: mail:send. The operator has agreed to the audience, artwork, and cost. confirm true and a fresh idempotency_key.

    Outputs: The launch result and charged amount.

    Side effects: Spends organization balance and hands the pieces to print and mail. Mail cannot be recalled.

    Read back with get_mail_campaign.

    Confirmation: required. The runner refuses this call without confirm true and a well-formed idempotency_key.

    Retry: Do not retry blindly. The retry window for an uncertain piece is the print vendor's 24-hour idempotency key; past it a retry prints a second piece. Stop and ask a person.

    Scopes: mail:send

  4. 04get_mail_campaign

    Read one physical-mail campaign by id, including its status.

    Preconditions: mail:read.

    Outputs: The stored campaign record.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: mail:read

Voice and the power dialer

Prepare voice assets and campaigns, place calls, and run the operator-first power dialer. Readiness (a voice-enabled number and the operator's personal phone) is required before the first call.

Preconditions: voice:read, voice:draft, and voice:send as needed. Readiness satisfied: a voice-enabled number, a resolvable connection, and the operator's personal phone set in account settings.

voice:readvoice:draftvoice:send
  1. 01list_voice_numbers

    List the organization's voice-enabled numbers to confirm one is available.

    Preconditions: voice:read.

    Outputs: Voice-capable numbers.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: voice:read

  2. 02upload_voice_asset

    Upload a base64 voicemail audio asset for a campaign.

    Preconditions: voice:draft. Audio no larger than the documented upload limit.

    Outputs: The stored asset reference.

    Side effects: Stores one audio asset. Places no call and charges nothing.

    Read back with get_voice_campaign.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Re-uploading the same asset is safe; it stores another copy.

    Scopes: voice:draft

  3. 03create_voice_draft

    Create an unsent voice (voicemail) campaign with its audience and asset.

    Preconditions: voice:draft.

    Outputs: The draft campaign id.

    Side effects: Creates one unsent campaign. Places no call and charges nothing.

    Read back with get_voice_campaign.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Repeating creates a second draft. Read it back first if a retry is uncertain.

    Scopes: voice:draft

  4. 04launch_voice_campaign

    Launch the voicemail campaign and charge the organization balance.

    Preconditions: voice:send. The operator has agreed to the audience and cost. confirm true and a fresh idempotency_key.

    Outputs: The launch result and charged amount.

    Side effects: Spends organization balance and starts real voicemail delivery.

    Read back with get_voice_campaign.

    Confirmation: required. The runner refuses this call without confirm true and a well-formed idempotency_key.

    Retry: Do not retry blindly. If the outcome is uncertain, read the campaign back; reuse the same idempotency_key.

    Scopes: voice:send

  5. 05start_voice_call

    Place a single voice call to one contact.

    Preconditions: voice:send. The contact confirmed. confirm true and a fresh idempotency_key.

    Outputs: The call session id.

    Side effects: Places one real call and bills the connected minute.

    Read back with get_voice_call.

    Confirmation: required. The runner refuses this call without confirm true and a well-formed idempotency_key.

    Retry: Do not retry blindly. Read the active call back before placing another.

    Scopes: voice:send

  6. 06start_dialer_session

    Open or resume a power dialer session for a campaign. Calls stay operator-first.

    Preconditions: voice:draft. A campaign id. Readiness satisfied.

    Outputs: The session id.

    Side effects: Dials the operator once and keeps the agent leg up. Bills 6 cents per operator-connected started minute.

    Read back with get_dialer_session.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Do not retry blindly. Read the session list back to find the existing session.

    Scopes: voice:draft

  7. 07advance_dialer_session

    Advance the dialer to the next contact against the live operator leg.

    Preconditions: voice:send. A live session. confirm true and a fresh idempotency_key.

    Outputs: The next contact, or that the session is finished.

    Side effects: Hangs up on the current contact, keeps the operator leg, and dials the next contact.

    Read back with get_dialer_session.

    Confirmation: required. The runner refuses this call without confirm true and a well-formed idempotency_key.

    Retry: Do not retry blindly. Read the session back; a repeat can dial a second contact.

    Scopes: voice:send

  8. 08get_active_call

    Read the currently active call for this organization.

    Preconditions: voice:read.

    Outputs: The active call, or nothing when none is live.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: voice:read

Bounded by

  • gap.phone-defaults

Import a contact or suppression file

Upload one or more CSV/XLSX workbooks, preview what will change, answer every uncertain decision, commit, and read the persisted counts and per-row outcomes back. Nothing is imported by parsing a file alone; the commit is the mutation.

Preconditions: contacts:read to preview and read back; contacts:write to commit and to stage a large upload. Optional list cleaning needs email:verify and address:verify, but is NOT performed by the import: it runs as a separate cohort-scoped step (clean_import_cohort) keyed by the cohortId the commit returns, and the organization-wide verification tools are never run off a file's permission.

contacts:readcontacts:writeemail:verifyaddress:verify
  1. 01stage_contact_import_upload

    Send a contact file that is too large to inline in one call, in bounded chunks. The first chunk omits staging_id and returns one; every later chunk sends that id, and final true marks the last chunk. The staging id is the reference a later import commit uses for the file.

    Preconditions: contacts:write. The file bytes as base64, up to 10 MB decoded per chunk.

    Outputs: A staging id, the 0-based chunk index just written, the bytes received so far and whether the upload is complete.

    Side effects: Stores the chunk bytes for this credential's organization. Changes no contact, parses nothing and charges nothing.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Safe to read back with the returned staging id; re-sending an entire chunk would append it a second time, so reconcile by the returned chunk index before repeating any call.

    Scopes: contacts:write

  2. 02preview_contact_import

    Parse and classify the uploaded files and return the exact counts, unresolved decisions, suppression matches and a signed previewToken. Send the per-tab plan, list tags and reviewChoices to keep the operator's decisions.

    Preconditions: contacts:read. The CSV/XLSX files as base64; no file path or URL is accepted.

    Outputs: A classified preview, the row counts, unresolved decision ids, and a previewToken.

    Side effects: Writes preview evidence for this credential's organization. Changes no contacts. Charges nothing.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Safe to call again; each preview supersedes the last. Read the counts back before committing.

    Scopes: contacts:read

  3. 03commit_contact_import

    Commit the previewed import with the previewToken and the same files and options. Resolve every uncertain decision first.

    Preconditions: contacts:write. A fresh previewToken. No unresolved decisions. email:verify / address:verify when cleaning is requested.

    Outputs: The persisted counts, the job id, and the cohortId when the commit was preview-backed. When cleaning was requested, a `cleaning` block reporting the requested channels as requested and NOT performed by the commit.

    Side effects: Creates, merges and suppresses contacts and writes the import job and per-row evidence. It NEVER charges and NEVER cleans inline: no list cleaning runs, and no organization-wide verification is triggered.

    Read back with get_contact_import_outcomes.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Do not retry blindly. Re-sending the unchanged commit with the same previewToken replays the stored receipt without importing twice; a changed file or mapping needs a new preview. Cleaning runs only through clean_import_cohort on the returned cohortId; never run a whole-organization verification on the strength of this file's permission.

    Scopes: contacts:write

  4. 04list_contact_imports

    List past imports for this organization, newest first, to find a job to inspect or confirm one landed.

    Preconditions: contacts:read.

    Outputs: A bounded page of imports with counts and an honest continuation.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: contacts:read

  5. 05get_contact_import_outcomes

    Read the persisted per-row outcomes of one import, optionally filtered to one kind, with a keyset continuation.

    Preconditions: contacts:read. A job id from commit_contact_import or list_contact_imports.

    Outputs: A bounded page of outcome rows with a next_cursor and has_more.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again; advance by the returned cursor, never assume a short page is the end.

    Scopes: contacts:read

  6. 06get_import_cleaning_cohort

    Read back the frozen import identity cohort captured with a preview-backed commit, using the cohortId the commit returned.

    Preconditions: contacts:read. A cohortId returned by commit_contact_import (preview-backed commits only).

    Outputs: The cohort's safe metadata: preview and job references, snapshot version/fingerprint, requested cleaning channels, the CAPTURED UNIQUE identity counts, a capture state and whether cohort-scoped paid cleaning is available.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again; a foreign or absent cohort is 404. It reports capture and availability only; it never reports or runs any cleaning.

    Scopes: contacts:read

  7. 07clean_import_cohort

    Clean exactly one frozen import identity cohort and charge organization balance. It acts only on the contacts matching the cohort's captured email keys and complete-address hashes, never on the whole organization and never on a caller-supplied key list.

    Preconditions: email:verify and address:verify. A cohortId returned by a preview-backed commit_contact_import. confirm true and a unique idempotency_key.

    Outputs: Per requested channel: whether cleaning was requested and performed, the counts, and the approved maximum. Nothing is charged when no cohort identity needs cleaning.

    Side effects: Spends organization balance and updates the matched contacts' verification verdicts. It cannot be undone.

    Confirmation: required. The runner refuses this call without confirm true and a well-formed idempotency_key.

    Retry: Do not retry blindly after an uncertain provider result: read the cohort back and the contacts' verification state first. A retry that finds no identity needing cleaning charges nothing and returns the unused approval.

    Scopes: email:verify, address:verify

Bounded by

  • gap.import-list-cleaning
  • gap.import-large-files

Website form intake: record a submission and read the receipt back

Record a website form submission as a contact through the same consent and suppression engine the website endpoint uses, then read the persisted receipt back by the external id. Nothing is sent and nothing is charged.

Preconditions: An organization-bound credential with intake:write and the app's owner/admin operational access. An active organization. Intake is a contact write that works before organization onboarding is complete, matching the legacy website endpoint.

intake:write
  1. 01record_form_submission

    Create or update one contact from a form submission. Provide an email, a phone, or both, and a source; a checked opt-in box needs its verbatim consent text, and an unchecked box withholds that channel.

    Preconditions: intake:write. An email, a phone, or both, and a source.

    Outputs: The contact id, the created/updated/duplicate result, the applied list tag, and each channel verdict. An identity_conflict refusal naming both contacts when the email and the phone already belong to two different contacts.

    Side effects: Creates or updates one contact and records one routine audit row. Applies source-derived list tags and channel consent. Sends nothing and charges nothing. A dated opt-out, a STOP, or a live suppression is never cleared.

    Read back with get_form_submission.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Reuse the same external_id on a retry so a COMPLETED submission replays the stored receipt as a duplicate rather than a second write. The adapter commits the contact and its receipt in one serialized transaction, so a same-key concurrent duplicate yields a single mutation and the first winner's receipt, and no receipt is written without its contact. A stored receipt records the outcome of the first accepted write, not proof the stored contact still matches this request, because later legitimate edits can change the contact. An interrupted (transport-ambiguous) keyed retry is not auto-resent: read the stored receipt for this external_id first. With no external_id there is no dedupe or replay; a repeated unkeyed submission is a separate operation.

    Scopes: intake:write

  2. 02get_form_submission

    Read the persisted receipt of a past submission by the external id that was sent, to confirm the outcome or recover after an interrupted attempt.

    Preconditions: intake:write. The external_id sent with the original submission.

    Outputs: The stored created/updated/duplicate receipt, or the stored identity_conflict receipt naming both unchanged contacts.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again. The receipt is the historical outcome of the first accepted write. A keyed submission writes its receipt with its contact in the same transaction, so an interrupted keyed attempt is resolved by reading this receipt: a present receipt proves the commit landed, and its absence after a failed request means no mutation was committed. The receipt does not show whether a later legitimate edit changed the contact, so look the contact up directly when that matters.

    Scopes: intake:write

Bounded by

  • gap.form-intake-atomicity

Team: read the roster and current pending invitations

Read the authorized organization's team roster and its CURRENT pending invitations without making changes. To invite, re-queue, or cancel an invitation, or to manage an ordinary member, use the team-management workflow.

Preconditions: An organization-bound credential with team:read whose issuing owner/admin is an ACTIVE member of the organization. A read-only organization state (for example a locked organization) stays readable; a suspended or removed credential membership does not.

team:read
  1. 01list_team_members

    Read a bounded page of the roster: id, email, display name, canonical role and membership status, membership timestamps, and the protected-owner flag. Advance by the returned page while hasMore is true; total is the true number of members.

    Preconditions: team:read. Owner or admin role on an active membership.

    Outputs: A page of members with an honest pagination block. Each member's role/status come from THIS organization's membership, so a member whose own selected organization is elsewhere is still shown with this organization's role.

    Side effects: No business-state change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: team:read

  2. 02list_team_invitations

    Read a bounded page of the CURRENT pending invitations (not accepted, not cancelled, not dismissed, not expired), newest first: id, email, role, created_at, expires_at.

    Preconditions: team:read. Owner or admin role on an active membership.

    Outputs: A page of pending invitations with an honest pagination block. No invitation token or copy-link value, and no history of past or accepted invitations.

    Side effects: No business-state change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: team:read

Bounded by

  • gap.member-management

Contact fields: discover the registry and pin a field's type

Read the organization's contact-field registry and, when a field should be typed, save an explicit key/label/type definition and read it back. A definition save changes field metadata only; it does not convert, clear, or repair any stored value.

Preconditions: An organization-bound credential with contacts:read to list fields and contacts:write to save a definition. The organization is the one that owns the credential; no argument selects it.

contacts:readcontacts:write
  1. 01list_contact_fields

    Read the registry: the explicit definitions unioned with the types inferred from stored contact values, keyed by their exact field keys.

    Preconditions: contacts:read.

    Outputs: The full bounded registry with a truthful total. Keys are verbatim, including spaces and case; each field carries key, label, and type.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: contacts:read

  2. 02upsert_contact_field

    Save an explicit key/label/type definition for one field so it can be filtered as that type.

    Preconditions: contacts:write. An agreed field key, label, and supported type (text, number, date, boolean).

    Outputs: The stored definition read back in field. confirmed is false when the save committed but the stored row could not be read back; that is not a refusal.

    Side effects: Writes one field-definition row and records a routine audit row. It does NOT convert, clear, or repair any contact's stored value and does not change a stored value's type.

    Read back with list_contact_fields.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: A repeated identical save settles the same key/label/type and is safe; do not replay an unknown (unconfirmed transport) outcome blindly; read the registry back first.

    Scopes: contacts:write

Bounded by

  • gap.contact-field-typed-values

Team: read the roster and manage invitations and ordinary members

Read the authorized organization's roster and current pending invitations, then invite, re-queue, or cancel an invitation, or change, suspend, reactivate, or remove an ordinary (non-owner) member, with each management action read back from the live state. This is ordinary owner/admin authority inside the credential's organization; the organization owner is never a target.

Preconditions: An organization-bound credential holding BOTH team:read and team:manage, whose issuing owner/admin is an ACTIVE member of the organization. Confirm each management action with the operator before it runs; none is money-moving or irreversible, so no confirm/idempotency argument is required.

team:readteam:manage
  1. 01list_team_members

    Read the current roster (id, email, display name, canonical role/status, protected-owner flag) before changing anything.

    Preconditions: team:read.

    Outputs: A bounded page of members with an honest pagination block; total is the true member count.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: team:read

  2. 02list_team_invitations

    Read the CURRENT pending invitations (id, email, role, created_at, expires_at) to find the one to re-queue or cancel.

    Preconditions: team:read.

    Outputs: A bounded page of pending invitations; no invite token or copy-link value is ever returned.

    Side effects: No data change beyond the routine audit row.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read-only. Safe to call again.

    Scopes: team:read

  3. 03create_team_invitation

    Invite one person by email as admin, member, or volunteer. Only email and role are accepted; a person who already has a membership must be reactivated instead.

    Preconditions: team:manage. An agreed email and role.

    Outputs: Safe invitation metadata and a `queued` acknowledgment: a source email event was written, which is NOT proof the email was sent or delivered.

    Side effects: Creates one pending invitation and queues a source email event. Creates no organization, grants no role, and moves no money.

    Read back with list_team_invitations.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read the pending invitations back after an uncertain result. A repeated invite for the same live pending invitation returns a conflict rather than a second one.

    Scopes: team:manage

  4. 04resend_team_invitation

    Re-queue the invitation email for a still-pending invitation.

    Preconditions: team:manage. A still-pending invitation id.

    Outputs: The re-queue acknowledgment; the email itself is not sent by this call.

    Side effects: Queues another source email event for the same pending invitation. Sends no email itself and moves no money.

    Read back with list_team_invitations.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: This is NOT idempotent: there is no request-key store, so each call queues the email again as a new request. Read the invitation state back instead of retrying blindly.

    Scopes: team:manage

  5. 05cancel_team_invitation

    Cancel a still-pending invitation so the person can be invited again.

    Preconditions: team:manage. A still-pending invitation id.

    Outputs: The cancellation result; the pending invitation is no longer listed.

    Side effects: Marks the invitation cancelled. Sends nothing and moves no money.

    Read back with list_team_invitations.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Cancelling an already accepted, cancelled, or dismissed invitation is refused. Read the invitations back before re-inviting.

    Scopes: team:manage

  6. 06change_team_member_role

    Change an ordinary member's role between admin and member.

    Preconditions: team:manage. A non-owner member id and the new role.

    Outputs: The live membership read back (id, email, role, membership_status); an unconfirmable readback is reported uncertain, not as success.

    Side effects: Changes one ordinary member's role. Promotion to owner, changing the owner, and changing your own role are refused. Sends nothing and moves no money.

    Read back with list_team_members.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read the roster back after an uncertain result before repeating; a repeat settles the same role.

    Scopes: team:manage

  7. 07suspend_team_member

    Suspend an ordinary active member, dropping them to read-only.

    Preconditions: team:manage. A non-owner active member id.

    Outputs: The live membership read back with its membership_status.

    Side effects: Suspends one ordinary membership. The owner cannot be suspended, you cannot suspend yourself, and the last active admin cannot be suspended. Sends nothing and moves no money.

    Read back with list_team_members.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read the roster back; a repeat against an already-suspended member is refused.

    Scopes: team:manage

  8. 08reactivate_team_member

    Reactivate a suspended member.

    Preconditions: team:manage. A suspended, non-owner member id.

    Outputs: The live membership read back with its restored membership_status.

    Side effects: Reactivates one suspended membership. The owner cannot be acted on and you cannot reactivate yourself. Sends nothing and moves no money.

    Read back with list_team_members.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Read the roster back; a member who is not suspended is refused, so a repeat is safe and reports the refusal.

    Scopes: team:manage

  9. 09remove_team_member

    Remove an ordinary member, ending their membership. This cannot be undone through this surface.

    Preconditions: team:manage. A non-owner member id, confirmed with the operator.

    Outputs: The removal result; removed members are no longer listed.

    Side effects: Ends one ordinary membership. It does not delete the account, transfer data, or move money. The owner cannot be removed, you cannot remove yourself, and the last active admin cannot be removed.

    Read back with list_team_members.

    Confirmation: this tool declares no confirm/idempotency gate. That does not establish whether it writes data or reserves funds; follow its side effects.

    Retry: Do not treat removal as reversible here. Read the roster back to confirm the outcome; re-inviting the person starts a fresh invitation.

    Scopes: team:manage

Bounded by

  • gap.member-management

Schema appendix

Named schemas referenced by the operations above. A field that points at another schema links to it; recursive schemas stop at the first repeat rather than expanding forever.

Error
errorrequired
stringWhat went wrong, in Campaign Commander wording.
requiredScopes
array<string>
missingScopes
array<string>
retryAfter
integerSeconds to wait after a 429.
limit
integer
resetAt
stringformat=date-time
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
Success

A completed action.

No named properties; see the complete schema below.

Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ObjectBody

A JSON object. See the operation description for the fields that route accepts.

No named properties; see the complete schema below.

Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ApprovalOptional
approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TeamInvitationCreate
emailrequired
stringformat=emailInvitee email address. Normalized to lower case.
rolerequired
stringone of admin, member, volunteerThe role the invitee will hold if they accept.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TeamMemberRoleUpdate
rolerequired
stringone of admin, memberThe member's new role. Promotion to owner is not accepted.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TeamMemberNote
note
stringOptional note recorded on the team audit trail.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TeamInvitationResult
invitationrequired
objectSafe invitation metadata only. No invite token, organization id, inviter, or whole row.
emailQueuedrequired
booleanTrue when a source email event was queued. NOT proof the email was sent or delivered.
deliveryrequired
stringone of queued
note
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TeamInvitationAction
okrequired
boolean
invitationIdrequired
string | nullformat=uuid, nullable
emailQueued
booleanPresent for a re-queue. NOT proof the email was sent or delivered.
delivery
stringone of queued
note
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TeamMemberResult
okrequired
boolean
memberrequired
objectSafe member metadata read back from the live membership. No whole user row.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ScheduleBody
scheduledAtrequired
stringformat=date-timeISO-8601 with a numeric offset or Z. At least 5 minutes ahead and no more than 366 days out.
approvalId
stringOptional legacy spend approval. Omit for direct execution.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
Pagination
pagerequired
integer
limitrequired
integer
totalrequired
integer
hasMorerequired
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
Contact
idrequired
stringformat=uuid
first_name
string | nullnullable
last_name
string | nullnullable
email
string | nullformat=email, nullable
phone
string | nullnullableE.164 when the server stored one.
address
string | nullnullableStreet address, trimmed. A partial address is allowed; a null address_hash is not a verification result.
city
string | nullnullableCity, trimmed.
state
string | nullnullableState, trimmed and upper-cased.
zip
string | nullnullableZIP code as text. A leading zero is kept.
notes
string | nullnullable
tags
array<string>
custom_fields
object<string, string>additionalProperties: string
email_opt_out
boolean
email_opt_out_date
string | nullformat=date-time, nullable
sms_opt_out
boolean
sms_opt_out_date
string | nullformat=date-time, nullable
do_not_contact
boolean
dnc_reason
string | nullnullable
dnc_date
string | nullformat=date-time, nullable
created_at
stringformat=date-time
updated_at
stringformat=date-time
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactWrite

At least one of first name, last name, email, phone, or a mailing-address field is required on create.

firstName
string | nullmaxLength=120, nullable
first_name
string | nullmaxLength=120, nullable
lastName
string | nullmaxLength=120, nullable
last_name
string | nullmaxLength=120, nullable
email
string | nullformat=email, nullable
phone
string | nullnullable
address
string | nullnullableStreet address. Trimmed. Omit to leave unchanged; null or an empty string clears it. A partial address is stored as-is; it is never reported as verified or deliverable.
city
string | nullnullableCity. Trimmed. Omit to leave unchanged; null or an empty string clears it.
state
string | nullnullableState. Trimmed and upper-cased. Omit to leave unchanged; null or an empty string clears it.
zip
string | nullnullableZIP code as text; a leading zero is kept. Omit to leave unchanged; null or an empty string clears it.
notes
string | nullnullable
tags
array<string>maxItems=25
customFields
object<string, string>additionalProperties: string
custom_fields
object<string, string>additionalProperties: string
overrideSuppression
booleanRequired, with overrideNote, to add a suppressed email that the product allows an override for.
overrideNote
stringminLength=3
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactEnvelope
contact
Contact Contact
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactList
contacts
array<Contact> Contact
pagination
Pagination Pagination
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactSearchPagination
pagerequired
integer
limitrequired
integer
totalrequired
integer | nullnullableExact filtered count. null only when the database did not return a count, never a fabricated zero.
hasMorerequired
boolean | nullnullableWhether another page exists. null means the exact count is unavailable, not that the list has ended; retry before assuming enumeration is complete.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactSearchResult

List mode returns a page of contacts with pagination; exact email/phone lookup returns a single contact.

contacts
array<Contact> Contact
pagination
ContactSearchPagination ContactSearchPagination
contact
Contact Contact
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TagWrite
tagsrequired
array<string>minItems=1, maxItems=25
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ConsentWrite
emailOptOut
boolean
smsOptOut
boolean
doNotContact
booleanfalse is refused.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ListFilters

Same filter object the product saves on a list.

custom
array<object>
tags
array<string>maxItems=25
tagsAny
array<string>
state
string
hasEmail
boolean
hasPhone
boolean
hasAddress
boolean
excludeDNC
boolean
excludeEmailOptOut
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ListWrite
name
stringmaxLength=120
description
stringmaxLength=1000
filters
ListFilters ListFilters
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ListPreview
filtersrequired
ListFilters ListFilters
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ListRecord
id
stringformat=uuid
name
string
slug
string | nullnullable
locked
boolean
contact_count
integer
description
string | nullnullable
created_at
stringformat=date-time
filters
ListFilters ListFilters
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ListCollection
listsrequired
array<ListRecord> ListRecord
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ListUsage
usagerequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
MemberIds
contactIdsrequired
array<string>maxItems=100
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
Suppression
id
stringformat=uuid
channel
stringone of email, sms, voice, all
email
string | nullnullable
phone
string | nullnullable
reason
string
consent_source
string | nullnullable
consent_timestamp
string | nullformat=date-time, nullable
suppressed_at
string | nullformat=date-time, nullable
created_at
stringformat=date-time
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SuppressionList
suppressionsrequired
array<Suppression> Suppression
paginationrequired
Pagination Pagination
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SuppressionWrite
email
stringformat=email
phone
string
reasonrequired
stringone of manual, recipient_blocks_sender, unsubscribe, legal_request
noterequired
stringminLength=3, maxLength=1000
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SuppressionBypass
noterequired
stringminLength=3, maxLength=1000
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SuppressionEnvelope

The created email draft.

No named properties; see the complete schema below.

Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailDraft
name
string
subject
string
message
stringHTML body. html or body are accepted aliases.
html
string
body
string
fromName
string
fromEmail
stringformat=email
replyToEmail
stringformat=email
recipientType
stringone of all, segment, selected, campaign_engagement
segmentId
stringformat=uuid
segmentIds
array<string>
selectedContactIds
array<string>
sourceCampaignId
stringformat=uuid
engagement
stringone of opened, clicked
engagementInclude
stringone of human, all
excludeCampaignIds
array<string>Prior email campaigns. People on them are left out, once per contact.
resendToNonOpenersAfterHours
any24 or true turns on a next-day send to people who did not open. false or null leaves it off.
firstNameFallback
string | nullnullableGreeting used when a contact has no first name and the message has no inline {first_name|...} fallback. Trimmed and capped at 60 characters. Omit to use Friend. Null or blank stores Friend. An inline tag still wins.
scheduledAt
stringformat=date-timeOptional. Also schedules the new draft. Requires email:send and Idempotency-Key.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailDraftPatch
name
string
subject
string
message
string
html
string
body
string
fromName
string
fromEmail
stringformat=email
replyToEmail
stringformat=email
firstNameFallback
string | nullnullableGreeting used when a contact has no first name and the message has no inline {first_name|...} fallback. Trimmed and capped at 60 characters. Omit to leave the saved value. Null or blank clears it back to Friend. An inline tag still wins.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailPreview
ready
boolean
blockers
array<string>
audience
objectadditionalProperties: allowed
cost
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailCreateResult
success
boolean
campaignId
stringformat=uuid
recipients
integer
uniqueRecipients
integer
costInCents
integer
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailSendResult
success
boolean
queued
boolean
status
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailTest
to
anyOne address or a list of up to 5. Each must be the key owner, an active member, or a verified test recipient.
testEmails
array<string>maxItems=5
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalSend
torequired
anyRequired. One address or a list. Combined to, cc, and bcc must be 1 to 50.
cc
any
bcc
any
from
string
reply_to
string
subject
stringmaxLength=998
html
string
text
string
template_id
stringformat=uuid
variables
objectadditionalProperties: allowed
headers
object<string, string>additionalProperties: string
tags
array<string>maxItems=10
tracking
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalAccepted
id
stringformat=uuid
status
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ConversionWrite
campaignIdrequired
stringformat=uuid
eventrequired
stringpattern=^[a-z][a-z0-9_-]{0,79}$
externalIdrequired
string
valueCents
integermin=0
occurredAt
stringformat=date-time
metadata
objectadditionalProperties: allowed
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VerificationQuote
uniqueToCheck
integer
costCents
integer
resourceId
string
balanceCents
integer
configured
booleanWhether email or address verification is turned on. This is not a vendor name.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsDraft
type
stringone of sms, mms
name
stringmaxLength=120
message
stringmaxLength=1600
recipientType
stringone of all, segment, custom
segmentId
stringformat=uuid
segmentIds
array<string>
filters
ListFilters ListFilters
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsCampaign
id
stringformat=uuid
name
string
type
stringone of sms, mms
status
string
message
string
hasMedia
boolean
totalRecipients
integer
sentCount
integer
failedCount
integer
deliveredCount
integer
estimatedCostCents
integer
actualSpendCents
integer
scheduledAt
string | nullformat=date-time, nullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsCampaignEnvelope
success
boolean
status
string
campaign
SmsCampaign SmsCampaign
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsCampaignList

Text campaigns for this organization.

No named properties; see the complete schema below.

Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsOutcomes
outcomes
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceDraft
typerequired
stringone of call, voicemail
namerequired
stringmaxLength=160
message
stringRequired when type is call.
ccNumberIdrequired
string
recipientTyperequired
stringone of all, segment, custom
segmentId
stringformat=uuid
contactIds
array<string>
audioAssetToken
stringRequired for voicemail. From the upload route.
audioDuration
integermin=1, max=300
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceDraftResult

A voice draft was saved. Nothing was dialed.

successrequired
boolean
statusrequired
string
providerSubmittedrequired
boolean
campaignId
stringformat=uuid
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceAsset

A voicemail file token. The storage location is not returned. Pass assetToken when creating the campaign. audioUrl is optional.

successrequired
boolean
assetTokenrequired
stringOpaque token. It does not contain a storage URL.
acceptedTypes
array<string>
maxDurationSecondsrequired
integer
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceCallCreate
contactIdrequired
stringformat=uuid
approvalId
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PowerDialerOpen
campaignIdrequired
stringformat=uuid
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
AgentRun
id
stringformat=uuid
objective
string
summary
string | nullnullable
status
stringone of active, waiting_for_master, needs_input, completed, cancelled
created_at
stringformat=date-time
updated_at
stringformat=date-time
completed_at
string | nullformat=date-time, nullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
AgentRunList

No named properties; see the complete schema below.

Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
AgentRunCreate
objectiverequired
stringminLength=3, maxLength=500
summary
stringmaxLength=2000
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
AgentRunUpdate
status
stringone of active, waiting_for_master, needs_input, completed, cancelled
summary
stringmaxLength=2000
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
Capabilities

Authenticated. Prices are customer prices.

apiVersion
string
agent
objectadditionalProperties: allowed
endpoints
object<string, string>additionalProperties: string
pricing
objectadditionalProperties: allowed
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CommunicationSettings
organization
objectadditionalProperties: allowed
email
objectadditionalProperties: allowedFrom name, from address, reply-to, and a domain status label. DNS records are not returned.
compliance
objectadditionalProperties: allowed
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
OrganizationSettingsFields

The reviewed organization-settings allowlist. Verification tokens, fingerprints, and provider identifiers are never returned.

committeeNamerequired
string | nullnullable
authorizationLinerequired
string | nullnullable
physicalAddressStreetrequired
string | nullnullable
physicalAddressStreet2
string | nullnullable
physicalAddressCityrequired
string | nullnullable
physicalAddressStaterequired
string | nullnullable
physicalAddressZiprequired
string | nullnullable
optionalContact
string | nullnullable
replyToEmailrequired
string | nullnullable
emailFromNamerequired
string | nullnullable
emailFromAddressrequired
string | nullnullable
organizationTyperequired
string | nullnullable
ein
string | nullnullable
legalBusinessName
string | nullnullable
website
string | nullnullable
defaultCampaignPhoneId
string | nullnullable
sendingDomain
string | nullnullable
campaignVerifyProvidedrequired
boolean
campaignVerifyImportedrequired
boolean
campaignVerifyEmailProvidedrequired
boolean
updatedAt
string | nullnullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
OrganizationSettingsSetup
completerequired
boolean
missingrequired
array<string>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
OrganizationSettings
organizationrequired
object
settingsrequired
OrganizationSettingsFields | null OrganizationSettingsFields
setuprequired
OrganizationSettingsSetup OrganizationSettingsSetup
rolerequired
string | nullnullable
canEditSettingsrequired
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
OrganizationSettingsUpdate
committeeNamerequired
string
authorizationLinerequired
string
physicalAddressStreetrequired
string
physicalAddressStreet2
string
physicalAddressCityrequired
string
physicalAddressStaterequired
string
physicalAddressZiprequired
string
optionalContact
string
replyToEmailrequired
string
emailFromNamerequired
string
emailFromAddressrequired
string
organizationTyperequired
stringone of candidate, pac, party, other_527, 501c3, 501c4, 501c5, 501c6
ein
string
legalBusinessName
string
website
string
defaultCampaignPhoneId
string
campaignVerifyToken
string
campaignVerifyEmailToken
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
OrganizationSettingsSave
settingsrequired
OrganizationSettingsFields | null OrganizationSettingsFields
changedFieldsrequired
array<string>
setuprequired
OrganizationSettingsSetup OrganizationSettingsSetup
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PersonalSettingsFields

The credential owner's own personal profile and preferences. User-wide: these belong to the person across every organization they belong to. Values preserve a legitimate word that is also a supplier's name (an ordinary name in a full name or signature is not rewritten).

idrequired
stringformat=uuid
emailrequired
string | nullnullableRead-only. Login email is not changed here.
fullNamerequired
string | nullnullable
personalPhonerequired
string | nullnullable
personalPhoneE164
string | nullnullableRead-only normalized phone.
timezone
string | nullnullable
country
string | nullnullable
defaultFromName
string | nullnullable
defaultFromEmail
string | nullnullable
defaultReplyToEmail
string | nullnullable
defaultSmsSignature
string | nullnullable
quietHoursEnabled
boolean
quietHoursStart
string | nullnullable
quietHoursEnd
string | nullnullable
optInMethods
array<string>Saved preferences, not recipient-consent evidence.
optInDescription
string | nullnullable
billingContactEmail
string | nullnullable
lowBalanceThresholdCents
integer | nullnullableAlert threshold in whole cents, not a spending limit.
usageNotificationsEnabled
boolean
dailySpendAlertsEnabled
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PersonalSettings
profilerequired
PersonalSettingsFields | null PersonalSettingsFields
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PersonalSettingsUpdate

An allowlisted patch of the credential owner's own personal profile and preferences. Only the keys you send are changed; an omitted field keeps its stored value and an empty string or null clears a string field.

fullName
string | nullnullable
personalPhone
string | nullnullable
timezone
string | nullnullable
country
string | nullnullable
defaultFromName
string | nullnullable
defaultFromEmail
string | nullnullable
defaultReplyToEmail
string | nullnullable
defaultSmsSignature
string | nullnullable
quietHoursEnabled
boolean
quietHoursStart
string | nullnullable
quietHoursEnd
string | nullnullable
optInMethods
array | nullnullable
optInDescription
string | nullnullable
billingContactEmail
string | nullnullable
lowBalanceThresholdCents
integermin=0
usageNotificationsEnabled
boolean
dailySpendAlertsEnabled
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PersonalSettingsSave
profilerequired
PersonalSettingsFields | null PersonalSettingsFields
changedFieldsrequired
array<string>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BrandSubmitRequest

The same brand fields as the preview, plus the fee acknowledgement. Send the same fields to POST /agent/approvals first when this key requires an operator approval, then pass the returned id as approvalId.

legal_business_name
stringLegal business name. Omit to use the saved value.
ein
stringNine-digit EIN. Omit to use the saved value.
street_address
string
street_address2
string
city
string
state
string
postal_code
string
website
stringSend an empty string to clear it; omit to use the saved value.
authorized_rep_name
string
authorized_rep_email
stringformat=email
authorized_rep_phone
string
fee_acknowledgedrequired
booleanMust be true: acknowledges the non-refundable one-time brand filing fee.
approvalId
stringOptional spend approval id for a key that requires an operator to approve each filing.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BrandSubmitResult
success
boolean
already_filed
booleanTrue when a matching filing is already on file; fee_charged_cents is then 0.
brand_status
string
fee_charged_centsrequired
integerThe non-refundable one-time brand filing fee that was charged.
filing_reconciliation_required
booleanAn uncertain carrier outcome. Do not resubmit; contact support.
idempotency_conflict
booleanThe key was reused with different business information. Refresh before a new submission.
message
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BrandRegistrationFee
brand_registration_centsrequired
integerOne-time, non-refundable brand filing fee in cents.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BrandRegistrationEligibility
owner_and_setup_eligiblerequired
booleanRole-and-setup eligibility only: the credential is the active, fully-set-up organization owner. It is not a grant of spending authority and does not mean a paid submission is available.
reasonrequired
stringPlain-language reason. Not a carrier name.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BrandRegistrationFiling
registration_id
stringformat=uuid
statusrequired
stringLocally stored filing state.
already_filedrequired
booleanA nonempty carrier reference plus a post-submission state. Not true for a draft or an unknown status.
has_carrier_referencerequired
booleanWhether a carrier brand reference is stored (the value itself is never returned).
verifiedrequired
boolean
rejectedrequired
boolean
submittingrequired
booleanA stored submission is still in flight.
confirmation_requiredrequired
booleanA prior paid filing may be with the carrier unconfirmed. Do not resubmit.
submitted_at
string | nullformat=date-time, nullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BrandRegistrationStatus
sourcerequired
stringone of localThe status is stored locally, not a live carrier reconciliation.
note
string
submission_note
stringStates that paid brand submission requires registration:submit.
organization
objectadditionalProperties: allowed
brand_statusrequired
string
filing
BrandRegistrationFiling | null BrandRegistrationFiling
feerequired
BrandRegistrationFee BrandRegistrationFee
balance_cents
integer
eligibilityrequired
BrandRegistrationEligibility BrandRegistrationEligibility
setuprequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BrandPreviewRequest
legal_business_name
stringLegal business name. Omit to use the saved value.
ein
stringNine-digit EIN. Omit to use the saved value.
street_address
string
street_address2
string
city
string
state
string
postal_code
string
website
stringSend an empty string to clear it; omit to use the saved value.
authorized_rep_name
string
authorized_rep_email
stringformat=email
authorized_rep_phone
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BrandPreview
source
stringone of local
note
string
submission_note
stringStates that paid brand submission requires registration:submit.
readyrequired
booleanWhether the supplied packet passes the same field validation the dashboard submit uses. Packet validity only; it is not a statement about filing state, role permission, or a sufficient balance.
problem
string | nullnullableThe first required fix, or null when ready.
missing_fieldsrequired
array<string>
organization
objectadditionalProperties: allowed
brand_status
string
already_filed
boolean
confirmation_required
boolean
feerequired
BrandRegistrationFee BrandRegistrationFee
balance_cents
integer
eligibilityrequired
BrandRegistrationEligibility BrandRegistrationEligibility
setuprequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignRegistrationFiling
id
stringformat=uuid
statusrequired
stringLocally stored campaign filing state.
use_case
string | nullnullableThe registered traffic use case.
is_current
boolean
submission_number
integer | nullnullable
rejection_reason
string | nullnullableCarrier rejection text when the filing was rejected.
submitted_at
string | nullformat=date-time, nullable
approved_at
string | nullformat=date-time, nullable
has_carrier_referencerequired
booleanWhether a carrier campaign reference is stored (the value itself is never returned).
already_filedrequired
booleanTrue exactly when a carrier campaign reference is recorded. It means an identity is stored, not approval, delivery, or a charge. False means no recorded reference, not proof that the carrier received nothing.
rejectedrequired
boolean
retryablerequired
booleanA rejected filing may be corrected and resubmitted (with or without a recorded carrier reference). False when the attempt is unconfirmed (confirmation_required) or still in progress (submitting), matching the paid route's reconciliation precedence. Not a fee receipt.
confirmation_requiredrequired
booleanAn existing local attempt cannot be interpreted with confidence (an explicit unconfirmed-outcome marker, an unrecognized/missing status, an unrecognized submission-state marker, or an active-looking status with no carrier reference). Do not submit another filing; reconcile it. This does not establish whether a fee was charged.
submittingrequired
booleanExplicitly stored as in progress (submission_state 'submitting'). Not proof the process is alive and not a charge claim.
campaign_verify_imported_at
string | nullformat=date-time, nullable
opt_in_description
string | nullnullableYour own opt-in copy (frozen filed flow, else the current draft).
sample_message_1
string | nullnullableYour own sample message (frozen filed sample, else the current draft).
filed_opt_in_url
string | nullnullable
filed_privacy_url
string | nullnullable
filed_terms_url
string | nullnullable
filed_screenshot_url
string | nullnullable
filed_message_flow
string | nullnullable
filed_sample_1
string | nullnullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignDraft
opt_in_method
string | nullnullable
opt_in_description
string | nullnullable
opt_in_url
string | nullnullable
privacy_policy_url
string | nullnullable
terms_url
string | nullnullable
opt_in_screenshot_url
string | nullnullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SiteCheckHistoryEntry
id
stringformat=uuid
event_type
string | nullnullable
okrequired
boolean
failed_labelsrequired
array<string>
opt_in_url
string | nullnullable
privacy_url
string | nullnullable
terms_url
string | nullnullable
checked_at
string | nullformat=date-time, nullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignRegistrationStatus
sourcerequired
stringone of localThe status is stored locally, not a live carrier reconciliation.
note
string
submission_note
stringStates that paid campaign filing requires registration:submit.
site_check_note
string
organization
objectadditionalProperties: allowed
campaign_statusrequired
stringThe organization-level campaign status label.
filingrequired
CampaignRegistrationFiling | null CampaignRegistrationFiling
draftrequired
CampaignDraft | null CampaignDraft
organization_type
string | nullnullable
last_site_checkrequired
SiteCheckHistoryEntry | null SiteCheckHistoryEntry
site_check_historyrequired
array<SiteCheckHistoryEntry> SiteCheckHistoryEntry
feerequired
object
balance_cents
integer
setuprequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignSiteCheckRequest
opt_in_urlrequired
stringPublic https URL of the SMS opt-in form on your campaign website.
privacy_policy_urlrequired
string
terms_urlrequired
string
opt_in_screenshot_url
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignSiteCheckResult
sourcerequired
stringone of local
note
string
recordedrequired
booleanWhether the history row was durably appended. It is never true when the append failed.
checked_atrequired
stringformat=date-time
okrequired
boolean
failed_labelsrequired
array<string>
opt_inrequired
array<object>
privacyrequired
array<object>
termsrequired
array<object>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignSiteCheckFailure
ok
booleanone of falseAlways false on a failed preflight.
recorded
booleanone of falseWhether a durable history row was appended. False on every failure path: the check is never presented as durable evidence.
code
stringone of invalid_packet, fetch_failed, history_failedMachine-readable failure. invalid_packet: the URL packet failed validation and no page was fetched. fetch_failed: the live pages could not be loaded. history_failed: the pages were checked but the history row could not be written, so the result is not durable.
errorrequired
stringHuman-readable failure text.
outcome
objectadditionalProperties: allowedPresent only when the pages WERE fetched (history_failed): the same safe ok/failedLabels/optIn/privacy/terms checklist as the success body, so a caller knows the check ran but was not recorded.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignDraftRequest
opt_in_url
stringPublic https URL of the SMS opt-in form on your campaign website. An empty string clears the saved value.
privacy_policy_url
stringPublic https URL of the privacy policy. An empty string clears the saved value.
terms_url
stringPublic https URL of the terms of service. An empty string clears the saved value.
opt_in_screenshot_url
stringOptional public https URL of an opt-in screenshot. An empty string clears the saved value.
opt_in_description
stringHow a person opts in. It must name the form, privacy, and terms URLs plus STOP and HELP, or it is refused. An empty string clears the saved value.
help_email
stringformat=emailOptional HELP reply contact. A supplied value must be a valid address, and an empty value never erases the stored shared inbox.
expected_volume
stringOptional expected monthly message volume.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignDraftSaved
sourcerequired
stringone of local
note
string
savedrequired
booleanTrue only when the draft was durably written. A failed write is an error, never a false success.
saved_fieldsrequired
array<string>The stored column names that were written. The draft copy itself is not echoed.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignSubmitRequest
compliance_acknowledgedrequired
booleanMust be true: acknowledges the messaging compliance requirements of the filing.
fee_acknowledgedrequired
booleanMust be true on a fresh filing: acknowledges the non-refundable review fee charged for this submission. A retry on an already-charged filing skips it.
confirmrequired
booleanMust be true: confirms the filing itself. The review fee is non-refundable per submission.
idempotency_key
stringOptional here: the bounded Idempotency-Key header is the canonical form. A repeat with the same key is already on file and charges nothing.
help_email
stringformat=emailOptional HELP reply contact for this filing. Omit to use the saved one.
campaign_verify_token
stringOptional Campaign Verify token for a political organization that needs one. Omit to use the saved token.
approval_id
stringOptional spend approval id for a key that requires an operator to approve each filing.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignSubmitResult
successrequired
boolean
already_submitted
booleanTrue when an existing filing attempt is already on file. No new review fee is charged.
already_filed
booleanTrue when a carrier campaign reference is already recorded for this organization.
campaign_status
stringqueued when the business registration is not yet approved, draft when the carrier returned no reference, otherwise submitted.
fee_charged_cents
integerThe non-refundable review fee charged for this submission, or 0 when nothing was charged.
filing_reconciliation_required
booleanAn uncertain carrier outcome or an unrecordable result. Do not resubmit; contact support.
message
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PhoneNumberSearchResults
numbersrequired
array<object>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PhoneNumberPurchaseRequest
phoneNumberrequired
stringThe toll-free number to buy, in E.164 form.
confirmrequired
booleanMust be true. A purchase spends the setup fee and cannot be undone.
approvalId
stringOptional operator approval id for this exact purchase.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PhoneNumberPurchaseResult
successrequired
boolean
already_purchased
booleanTrue when a retry with the same key matched a completed purchase.
phoneNumber
stringThe purchased number, when known.
orderId
stringThe carrier order reference for support. Not a customer-facing id.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PhoneNumberDefaultResult
successrequired
boolean
id
stringThe number id that is now the default.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CallingQueues

The prepared calling queues this member may work in the credential's organization, plus this member's own active or paused shift session id per queue. The campaign list is organization-wide, not an individual assignment; only the shift session id is personal. A pending_count of null means the count could not be read (unavailable), not zero. truncated reports whether more campaigns could exist than were read; shiftsTruncated reports whether this member's own shift page was capped, so a null session_id is not proof of no open shift.

campaignsrequired
array<object>
truncatedrequired
boolean
shiftsTruncatedrequired
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CallingPhone

The persisted result of saving the credential owner's own operator phone. Only whether a phone was set and its last four digits are returned.

phonerequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CallingPhoneUpdate

The only field accepted when saving your own operator phone. A caller-supplied user or organization selector is refused.

phonerequired
stringYour operator phone as a U.S. number. Normalized but not verified.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
OpenApiDocument

This OpenAPI document. The same JSON is served at /openapi.json.

openapirequired
string
inforequired
objectadditionalProperties: allowed
servers
array<object>
pathsrequired
objectadditionalProperties: allowed
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
Approval

A single-use legacy spend approval bound to this key.

idrequired
stringformat=uuid
statusrequired
stringone of pending, approved, expired, consumed, rejected
actionrequired
string
resource_type
stringnullable
resource_id
stringnullable
max_centsrequired
integermin=0Whole cents.
max_units
integernullable
requested_atrequired
stringformat=date-time
expires_atrequired
stringformat=date-time
approved_at
stringformat=date-time, nullable
consumed_at
stringformat=date-time, nullable
agent_run_id
stringnullable
approved_by
string | nullnullablestanding limit when this key's standing spend limit granted the approval. Null when a person approved it or it is still pending. The key id is api_key_id.
api_key_id
stringformat=uuidKey that requested the spend. Recorded with approved_by standing limit.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ApprovalList

Legacy approvals for this key only.

approvalsrequired
array<Approval> Approval
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ApprovalRequest

Optional request for a legacy spend approval. Paid actions do not wait on this. For registration.brand.submit, send `brand` with the same brand fields the submit call will use and omit resourceId; the owner approves the server-derived packet hash, so the same fields must be sent again at execution.

actionrequired
stringminLength=1, maxLength=120example "email_campaign.send"
maxCents
integermin=1example 500
resourceType
string
resourceId
string
agentRunId
stringmaxLength=200
brand
BrandPreviewRequest BrandPreviewRequest
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
Deleted

The row was removed or the action completed.

successrequired
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
MemberChange

How many static-list memberships changed.

successrequired
boolean
added
integermin=0
removed
integermin=0
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ListResolve

One matching list, or candidates when the name is ambiguous.

match
objectnullable, additionalProperties: allowed
candidatesrequired
array<object>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ListCount

A count only. Contacts are not returned.

countrequired
integermin=0
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
InboxConversation

Inbox triage row. Delivery addresses are omitted.

idrequired
stringformat=uuid
contact_id
stringformat=uuid, nullable
channelrequired
stringone of sms, email
subject
stringnullable
statusrequired
stringone of active, closed
last_message_at
stringformat=date-time, nullable
last_message_preview
stringnullable
unread_count
integermin=0
created_at
stringformat=date-time
updated_at
stringformat=date-time
contact
objectnullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
InboxList

Conversations for triage.

conversationsrequired
array<InboxConversation> InboxConversation
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
InboxMessage

One message. Phone numbers and email addresses are omitted.

idrequired
stringformat=uuid
channelrequired
stringone of sms, email
directionrequired
stringone of inbound, outbound
content
stringnullable
subject
stringnullable
status
string
created_at
stringformat=date-time
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
InboxDetail

One conversation and its recent messages.

conversationrequired
InboxConversation InboxConversation
messagesrequired
array<InboxMessage> InboxMessage
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SuppressionRow

A suppression after a bypass or a withdrawn bypass.

idrequired
stringformat=uuid
status
string
bypassed
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailCampaignSummary

An email campaign without the full HTML body.

idrequired
stringformat=uuid
namerequired
string
statusrequired
stringone of draft, scheduled, sending, sent, paused, failed, canceled
subject
stringnullable
total_recipients
integermin=0
scheduled_at
stringformat=date-time, nullable
created_at
stringformat=date-time
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailCampaignList

Email campaigns for this organization.

campaignsrequired
array<EmailCampaignSummary> EmailCampaignSummary
pagination
object
metricDefinitions
object<string, string>additionalProperties: stringPlain-English meaning of each count field.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailCampaignDetail

Stored email content, counts, and schedule.

campaignrequired
objectadditionalProperties: allowed
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailMutation

The draft was saved, refreshed, tested, scheduled, or returned to draft.

successrequired
boolean
campaignId
stringformat=uuid
status
string
recipientCount
integermin=0
scheduledAt
stringformat=date-time, nullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalEmail

One system email. Carrier message ids are not included.

idrequired
stringformat=uuid
subject
stringnullable
statusrequired
string
attempt_count
integermin=0
next_attempt_at
stringformat=date-time, nullable
created_at
stringformat=date-time
charge_cents
integermin=0Whole cents.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalList

System emails for this organization.

emailsrequired
array<TransactionalEmail> TransactionalEmail
pagination
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalDetail

One system email and its recipients. Carrier message ids are omitted.

emailrequired
TransactionalEmail TransactionalEmail
recipients
array<object>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalTemplate

A reusable system-email template. Placeholders use double curly braces.

idrequired
stringformat=uuid
namerequired
string
subjectrequired
string
html
string
text
stringnullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalTemplateWrite

Create or update a transactional template.

namerequired
stringminLength=1, maxLength=120
subjectrequired
stringminLength=1, maxLength=200
htmlrequired
stringminLength=1
text
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TemplateList

Transactional templates.

templatesrequired
array<TransactionalTemplate> TransactionalTemplate
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalWebhookWrite

Create a transactional webhook. The url must be https.

urlrequired
stringformat=uri
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalWebhookUpdate

Turn a transactional webhook on or off.

enabledrequired
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalWebhook

A transactional webhook endpoint. The secret is omitted.

idrequired
stringformat=uuid
urlrequired
string
enabledrequired
boolean
created_at
stringformat=date-time
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalWebhookCreated

A new transactional webhook. The secret is shown once.

idrequired
stringformat=uuid
urlrequired
string
enabled
boolean
created_at
stringformat=date-time
secretrequired
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TransactionalWebhookList

Transactional webhook endpoints for this organization.

endpointsrequired
array<TransactionalWebhook> TransactionalWebhook
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TemplateDetail

One transactional template.

templaterequired
TransactionalTemplate TransactionalTemplate
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailRecipient

One email recipient outcome. Carrier message ids are omitted.

idrequired
stringformat=uuid
contact_id
stringformat=uuid, nullable
email
stringformat=email
statusrequired
string
error
stringnullablePlain language. Carrier text is not passed through.
sent_at
stringformat=date-time, nullable
opened_at
stringformat=date-time, nullable
clicked_at
stringformat=date-time, nullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailRecipientPage

Paginated email recipient outcomes.

recipientsrequired
array<EmailRecipient> EmailRecipient
pagination
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailEvent

One delivery event. Carrier message ids and raw diagnostics are omitted.

idrequired
stringformat=uuid
event_typerequired
stringone of send, delivery, open, click, bounce, complaint
email_to
stringformat=email
bounce_type
stringone of Permanent, Transient, nullnullable
created_at
stringformat=date-time
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailEventPage

Paginated email delivery events.

eventsrequired
array<EmailEvent> EmailEvent
pagination
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
EmailCampaignClicks

Opens for one email campaign and clicks grouped by a normalized link or by utm_content.

campaignIdrequired
stringformat=uuid
groupByrequired
stringone of url, utm_contenturl is the normalized link. utm_content is that query parameter.
opensrequired
object
clicksrequired
array<object>
definitions
objectadditionalProperties: allowedPlain-English meaning of each opens and clicks count.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ConversionSourceList

Conversion sources for this organization. The token is not included.

sourcesrequired
array<object>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ConversionSourceWrite

Create a conversion source. An Anedot source is a donation and needs a signing secret of at least 16 characters.

kindrequired
stringone of donation, signup, rsvp
parserrequired
stringone of anedot, generic
signingSecret
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ConversionSourceCreated

The source was created. The token is returned once.

sourcerequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CampaignPerformanceReport

Human clicks, conversions, and throughput for one campaign. Email, phone, and tokens are omitted.

campaignIdrequired
stringformat=uuid
channelrequired
stringone of email, sms, mms, nullnullable
conversionsrequired
objectadditionalProperties: allowed
throughputrequired
object
clicksrequired
array<object>nullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ConversionResult

The conversion was stored.

successrequired
boolean
id
stringformat=uuid
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VerificationResult

A verification quote or a completed check. Balance is whole cents.

success
boolean
costCentsrequired
integermin=0Whole cents.
uniqueToCheck
integermin=0
balanceCents
integer
configured
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsReadiness

Whether this organization can send texts or pictures.

smsrequired
object
mmsrequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsPreview

Text audience and cost. Nothing is sent or charged.

recipientCountrequired
integermin=0
costCentsrequired
integermin=0Whole cents.
segmentCount
integermin=1
balanceCents
integer
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsMutation

A text draft was tested, started, scheduled, or returned to draft.

successrequired
boolean
status
string
campaignId
stringformat=uuid
scheduledAt
stringformat=date-time, nullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsRecipientPage

Text recipient outcomes. Full phone numbers are omitted. Error text is plain language.

recipientsrequired
array<object>
pagination
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsEventPage

Text delivery events.

eventsrequired
array<object>
pagination
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SmsCampaignClicks

Clicks for each tracked link on one text campaign. Redirect tokens are omitted.

campaignIdrequired
stringformat=uuid
clicksrequired
array<object>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
MailPreview

Postcard or letter audience and cost. Nothing is printed or reserved.

deliverableCountrequired
integermin=0
estimatedCostCentsrequired
integermin=0Whole cents.
costPerPieceCents
integermin=0Whole cents.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
MailCreateForm

Multipart postcard or letter draft. frontCreative is a file.

namerequired
stringminLength=1, maxLength=120
mailTyperequired
stringone of postcard, letter
postcardSize
stringone of 4x6, 6x9, 6x11
listId
stringformat=uuid
frontCreativerequired
stringformat=binary
backCreative
stringformat=binary
letterCreative
stringformat=binary
includePartialAddresses
stringone of true, false
oneMailPerAddress
stringone of true, false
isTest
stringone of true, falseHidden. true keeps the campaign out of ordinary lists.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
MailCampaign

A postcard or letter campaign. Creative file URLs are omitted.

idrequired
stringformat=uuid
namerequired
string
mail_typerequired
stringone of postcard, letter
postcard_size
stringone of 4x6, 6x9, 6x11, nullnullable
statusrequired
stringone of draft, queued, processing, mailed, paused, completed, failed, canceled, needs_attention
estimated_recipients
integermin=0
cost_per_piece_cents
integermin=0Whole cents.
estimated_cost_cents
integermin=0Whole cents.
created_at
stringformat=date-time
is_test
booleanHidden test campaigns are omitted from ordinary lists. Default false.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
MailList

Postcard and letter campaigns.

campaignsrequired
array<MailCampaign> MailCampaign
pagination
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
MailDetail

Configuration and progress. Recent jobs include why a piece was not sent. Vendor names are removed.

campaignrequired
MailCampaign MailCampaign
stats
objectadditionalProperties: allowed
recentJobs
array<object>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
MailLaunch

Printing was submitted. It cannot be recalled.

successrequired
boolean
status
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceNumber

An active voice-enabled sending number. The number is masked.

idrequired
stringformat=uuid
label
stringnullable
maskedPhone
string
voiceEnabled
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceNumberList

Voice caller ids for this organization.

numbersrequired
array<VoiceNumber> VoiceNumber
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceAssetUpload

Multipart voicemail upload. file is MP3 or WAV, at most 10 MB.

filerequired
stringformat=binaryaudio/mpeg or audio/wav
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceCampaignSummary

A call or voicemail campaign.

idrequired
stringformat=uuid
name
string
typerequired
stringone of call, voicemail, robocall
statusrequired
string
created_at
stringformat=date-time
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceCampaignList

Call and voicemail campaigns.

campaignsrequired
array<VoiceCampaignSummary> VoiceCampaignSummary
pagination
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceCampaignDetail

One call or voicemail campaign and recipient counts.

campaignrequired
VoiceCampaignSummary VoiceCampaignSummary
recipients
objectadditionalProperties: allowed
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceLaunchResult

Voicemail delivery started.

successrequired
boolean
status
string
providerSubmitted
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceRecordingTest

One recording test was placed to the key owner's registered phone. The list was not dialed.

successrequired
boolean
testrequired
boolean
personalPhoneTestrequired
boolean
session
CallSession CallSession
reused
boolean
providerSubmitted
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceRobocallTestRequest

An organization-owned recording to play to the key owner's registered phone.

audioUrlrequired
stringformat=uri
audioAssetTokenrequired
stringOpaque token from the voice asset upload.
audioDurationrequired
integermin=1, max=300
ccNumberId
string
approvalId
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
VoiceRecipientPage

Call outcomes. Full phone numbers are omitted.

recipientsrequired
array<object>
pagination
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CallSession

A live or finished operator-first call. Browser audio is not part of this API.

idrequired
stringformat=uuid
statusrequired
string
contactName
stringnullable
startedAt
stringformat=date-time, nullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CallStart

The operator leg was dialed, or an existing session was reused.

successrequired
boolean
sessionrequired
CallSession CallSession
reused
boolean
providerSubmitted
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CallActive

The operator's current call, if one is up.

sessionrequired
any CallSessionnullable
activeCall
objectnullable, additionalProperties: allowed
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
CallControlResult

The on-screen control was accepted. Next hangs up the voter only.

successrequired
boolean
session
CallSession CallSession
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
MailPreviewRequest

Audience and format for a print estimate. Nothing is reserved.

mailTyperequired
stringone of postcard, letter
postcardSize
stringone of 4x6, 6x9, 6x11
recipientTyperequired
stringone of all, segment
segmentId
stringformat=uuid
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PowerDialerOpened

A dialer session is ready. No voter is dialed until the operator answers.

successrequired
boolean
sessionrequired
objectadditionalProperties: allowed
reused
boolean
providerSubmitted
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PowerDialerList

Dialer sessions for this key.

sessionsrequired
array<object>
pagination
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
PowerDialerSession

One dialer session.

sessionrequired
objectadditionalProperties: allowed
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
AuditPage

This organization's audit log entries, newest first.

eventsrequired
array<object>
paginationrequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BillingBalance

Organization funds. availableBalanceCents is the actual spendable balance with active holds already deducted; outstandingHoldsCents is the total currently reserved and not yet settled or voided. The holds are never subtracted again.

organizationIdrequired
stringformat=uuid
balancerequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BillingTransaction

One ledger entry. Only the public ledger id, type, amount, running balance, description, and timestamp are returned.

idrequired
stringformat=uuid
transaction_typerequired
string
amount_centsrequired
integer
balance_after_cents
integernullable
description
stringnullable
created_atrequired
stringformat=date-time
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BillingTransactionPage

A page of ledger entries with an exact total and a has-more flag.

organizationIdrequired
stringformat=uuid
transactionsrequired
array<BillingTransaction> BillingTransaction
paginationrequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BillingAutoTopUpConfiguration

The saved automatic-replenishment configuration. The saved payment method is reported as brand, last 4 digits, and expiry only, and never a card number or identifier.

enabledrequired
booleanWhen true, future automatic charges are authorized against the saved card.
thresholdCentsrequired
integermin=500, max=100000
amountCentsrequired
integermin=1000, max=100000
maxTopUpsPerDay
integer
maxAmountPerDayCents
integer
cooldownMinutes
integer
disabledReason
stringnullable
paymentMethod
objectnullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BillingAutoTopUp

This organization's saved Auto Top-Up configuration, or null when none is saved.

organizationIdrequired
stringformat=uuid
settings
any BillingAutoTopUpConfigurationnullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
BillingAutoTopUpUpdate

A full Auto Top-Up configuration save. Enabling authorizes future automatic charges against the already-saved card; it does not charge now and cannot add or remove a card.

enabledrequired
boolean
thresholdCentsrequired
integermin=500, max=100000
amountCentsrequired
integermin=1000, max=100000
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportPreviewForm

Multipart form for a contact or suppression import preview. The file field repeats for multiple CSV/XLSX workbooks. plan, tags and reviewChoices carry the operator's per-tab decisions, list tags and metadata answers so nothing is dropped.

filerequired
array<string>One or more CSV or XLSX files.
plan
stringJSON array of per-tab decisions: name, key, role (contacts|suppression|ignore), channels, and column mapping. Omit to accept the automatic classification.
tags
stringComma-separated tags applied to every imported contact.
metadataToken
stringA prior preview token, to reuse the frozen classification instead of re-running the classifier.
reviewChoices
stringJSON object of metadata answers, keyed '<evidenceId>', each 'suppress' or 'none'.
cleanEmails
booleanAsk to clean imported emails later. Only enforced at commit.
cleanAddresses
booleanAsk to clean imported addresses later. Only enforced at commit.
smsConsentAttested
booleanOperator attests the file carries SMS consent for its phone numbers.
voiceConsentAttested
booleanOperator attests the file carries voice-call consent for its phone numbers.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportCommitForm

Multipart form for committing a previewed import. Send the same files and options as the preview, plus the previewToken. Cleaned emails require email:verify and cleaned addresses require address:verify, refused before any contact write when absent.

filerequired
array<string>The same CSV/XLSX files that were previewed.
previewTokenrequired
stringThe signed token returned by the preview.
plan
stringJSON array of per-tab decisions, unchanged from the preview.
tags
stringComma-separated tags, unchanged from the preview.
reviewChoices
stringJSON metadata answers, unchanged from the preview.
cleanEmails
booleanRequest email cleaning. Scope email:verify required. The commit saves contacts only and charges nothing, and does not clean inline: cleaning exactly this import's contacts runs as a separate cohort-scoped paid step keyed by the cohortId the commit returns, so the response reports it as requested and not performed by the commit.
cleanAddresses
booleanRequest address cleaning. Scope address:verify required. The commit saves contacts only and charges nothing, and does not clean inline: cleaning exactly this import's contacts runs as a separate cohort-scoped paid step keyed by the cohortId the commit returns, so the response reports it as requested and not performed by the commit.
smsConsentAttested
boolean
voiceConsentAttested
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportPreview

A parsed, classified import preview. It writes preview evidence only and changes no contacts. Carries the exact counts, unresolved decisions, suppression matches and the signed preview token to commit.

sheets
array<ContactImportSheet> ContactImportSheetPer-tab classification with role, headers, suggested mapping and reasons.
previewrequired
ContactImportPreviewBody ContactImportPreviewBody
previewTokenrequired
stringSigned token to commit this exact upload and mapping.
metadataToken
stringSigned token to reuse the frozen classification on a refresh.
ledgerMatches
objectadditionalProperties: allowedHow many file emails and phones already match this organization's suppression ledger.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportPreviewBody

The row-by-row body of a preview or a commit. Every row explanation travels as `source_reason` and each before/after source cell value as `source_before`/`source_after`, the import-specific key names that survive redaction. The exact counts and unresolved decision ids pass through.

hash
stringnullableThe canonical plan hash the commit binds to.
totalRowsrequired
integer
counts
objectadditionalProperties: allowedRows by kind: create, merge, skip, suppress.
rowsrequired
array<ContactImportOutcome> ContactImportOutcome
reasonTotals
array<object>Rows by reason; the reason travels as `source_reason` so a reason naming an ordinary organization survives.
mergeBreakdown
objectnullable, additionalProperties: allowed
metadata
array<object>Classifier evidence, including unresolved decision ids.
unresolved
array<string>
uniqueContactMutations
integer
uniqueEmails
integer
ignoredRows
integer
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportSheet

One classified tab. The tab label, the file's own column headers and the suggested column mapping are the customer's own column names and are exactly what the caller echoes back to build the commit plan, so they travel under import-specific `source_*` names that survive redaction; a generic `headers`/`mapping`/`key` elsewhere is still scrubbed.

name
stringnullableThe tab label from the uploaded workbook.
source_key
stringnullableStable tab key within the upload, to pin the plan.
file_name
stringnullable
rolerequired
stringone of contacts, suppression, ignore
row_count
integer
source_headers
array<string>The file's own column headers, verbatim.
source_mapping
objectadditionalProperties: allowedSuggested column header per field, plus a custom header-to-field map.
source_reasons
array<string>Plain-language classification reasons.
source_samples
array<object>
default_channels
objectadditionalProperties: allowed
source_status_counts
array<object>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportSheetSummary

One per-workbook summary from a completed commit, projected the same way: the summary explanation travels as `source_reason`.

name
stringnullable
rolerequired
stringone of contacts, suppression, ignore
row_count
integer
source_reason
stringnullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportCommit

The persisted result of committing an import. Nothing is charged and no list cleaning is performed inline; when cleaning was requested the response carries a `cleaning` block reporting the channels as requested and not performed, and cohortId names the separate cohort-scoped paid step. The previewed rows are returned under the same redaction-safe shape as the preview.

successrequired
boolean
importedrequired
integer
taggedExisting
integer
skippedDuplicates
integer
phonesNotUsable
integer
emailsNotUsable
integer
rejected
integer
alreadySuppressed
integer
replayed
booleanPresent and true when an unchanged commit returned the stored receipt.
jobId
stringformat=uuid, nullable
cohortId
string | nullformat=uuid, nullableThe stable id of the frozen import identity cohort captured with a preview-backed commit. Absent for legacy/no-snapshot commits. Its presence means a frozen identity set was saved, not that anything was cleaned or charged.
jobs
array<object>One job per workbook.
list
stringnullableThe first list tag applied.
cleaningError
stringnullableWhy optional list cleaning did not complete, when it did not.
preview
ContactImportPreviewBody ContactImportPreviewBody
sheets
array<ContactImportSheetSummary> ContactImportSheetSummary
cleaning
objectnullable, additionalProperties: allowedPresent when cleaning was requested. Lists the requested channels and states that cleaning was NOT performed by this commit, and that it is available as a separate cohort-scoped paid step keyed by cohortId.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportHistory

Bounded, newest-first history of this organization's imports with an honest continuation.

importsrequired
array<ContactImportHistoryRow> ContactImportHistoryRow
has_morerequired
boolean
next_offset
integernullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportHistoryRow

One persisted import: file name, status, timestamps, counts, suppression counts and evidence version.

idrequired
stringformat=uuid
filename
stringnullable
status
stringnullable
started_at
stringformat=date-time
finished_at
stringformat=date-time, nullable
rows_read
integer
contacts_created
integer
contacts_updated
integer
duplicates_merged
integer
rows_rejected
integer
phones_not_usable
integer
emails_not_usable
integer
suppressions
objectadditionalProperties: allowedSuppression counts by channel.
evidence_version
integer
outcome_counts
objectnullable, additionalProperties: allowed
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportOutcomes

A bounded page of per-row import outcomes with a keyset cursor and an honest continuation. Evidence version 2 reads persisted outcome rows; older jobs fall back to the frozen summary.

evidence_version
integer
outcomesrequired
array<ContactImportOutcome> ContactImportOutcome
has_morerequired
boolean
next_cursor
stringnullable
category
stringnullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportOutcome

One persisted import outcome row. User-authored values are preserved under import-specific key names (`source_reason`, `source_before`, `source_after`) so a generic `reason` elsewhere is still scrubbed; only the shape is normalized.

id
stringnullable
sheet_key
stringnullable
sheet_name
stringnullable
file_name
stringnullable
row_number
integernullable
kindrequired
stringone of create, merge, suppress, skip
source_reason
stringnullableThe customer-authored per-row explanation.
email
stringnullable
phone
stringnullable
flags
array<string>
deltas
array<object>Per-field before/after source cell values, keyed so they survive redaction.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportCleaningCohort

The safe metadata of one frozen import identity cohort. Captured unique counts only: no raw email/address keys, no billable-unit or pending-check counts, and no cleaning execution status. `paid_cleaning.available` reports that the separate cohort-scoped paid cleaning step exists; it never claims any cleaning has run.

cohortrequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportCohortClean

The body of a cohort-clean request. It names only channels and an optional approval; the identity set is read from the server-side cohort, never from the caller. Requires confirm true and an idempotency_key because it spends balance.

channelsrequired
array<string>Which identities to clean. At least one.
confirmrequired
booleanMust be true.
idempotency_keyrequired
stringUnique 16 to 128 character key.
approval_id
stringOptional approved operator spend approval id for this exact cohort.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportCohortCleanResult

The result of cleaning a frozen import identity cohort. Each requested channel reports whether cleaning was requested and performed and its counts. Only the cohort's own identities were checked; no whole-organization run happens. Nothing is charged when no cohort identity needs cleaning.

successrequired
boolean
cohort_idrequired
stringformat=uuid
chargedCents
integer
channelsrequired
objectadditionalProperties: allowedPer-channel outcome: requested, performed, counts, and the approved maximum.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportStagedUpload

One chunk of a staged contact-import upload. The first chunk omits staging_id; every later chunk sends the returned id. final true marks the last chunk. Bytes only: nothing is parsed and nothing is charged.

filenamerequired
stringFile name for the whole upload.
content_base64required
stringThis chunk's bytes, base64-encoded.
staging_id
stringThe id returned by the first chunk. Omit on the first call.
final
booleanSet true on the last chunk.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactImportStagedUploadResult

The state of a staged upload after one chunk. The staging_id is the durable reference a later import commit uses for this file. No bytes are echoed.

staging_idrequired
stringformat=uuid
filename
string
chunk_indexrequired
integer0-based index of the chunk just appended.
bytes_receivedrequired
integer
completerequired
boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
FormSubmissionChannel

A channel verdict for one form submission.

permittedrequired
boolean
reasonrequired
stringone of opted_in, already_permitted, not_opted_in, not_provided, opted_out, suppressed, identifier_differs, do_not_contact
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
FormSubmissionRecord

A website form submission. Provide an email, a phone, or both, and a source. A checked opt-in box requires its verbatim consent text. A tenant or user selector is refused, not honored.

email
stringEmail address, stored lowercased.
phone
stringU.S. phone number, stored as E.164.
firstName
string
lastName
string
street
string
city
string
state
string
zip
string
postalCode
stringPostal-code alias accepted when zip is omitted.
sourcerequired
stringShort form name such as volunteer, membership, contact, newsletter, or event.
emailOptIn
boolean
smsOptIn
boolean
emailConsentText
stringThe email checkbox label, verbatim, 3 to 2000 characters.
smsConsentText
stringThe text checkbox label, verbatim, 3 to 2000 characters.
optInIpAddress
string
optInAttestation
boolean
locale
string
submittedAt
stringformat=date-time
externalId
stringStable id, up to 128 characters. Reusing it replays the FIRST accepted submission instead of writing again; the contact and its receipt commit atomically, so a concurrent duplicate never re-mutates the contact. An interrupted keyed retry is not auto-resent; read the receipt for this externalId first.
attributes
object<string, string | number | boolean>additionalProperties: string | number | booleanUp to 40 extra fields as text, number, or boolean values.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
FormSubmissionAccepted

A successful form-intake receipt.

contactIdrequired
stringformat=uuid
resultrequired
stringone of created, updated, duplicate
listTagrequired
stringThe source-derived list tag applied to the contact.
emailrequired
FormSubmissionChannel FormSubmissionChannel
smsrequired
FormSubmissionChannel FormSubmissionChannel
ignoredrequired
array<string>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
FormSubmissionConflict

An identity-conflict receipt. The email matched one contact and the phone matched a different contact; neither was changed.

errorrequired
string
coderequired
stringone of identity_conflict
resultrequired
stringone of identity_conflict
emailContactIdrequired
stringformat=uuid
phoneContactIdrequired
stringformat=uuid
externalId
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
FormSubmissionReceipt

A stored form-intake receipt: a successful created/updated/duplicate result or an identity-conflict refusal.

contactId
stringformat=uuid
result
stringone of created, updated, duplicate
listTag
stringThe source-derived list tag applied to the contact.
email
FormSubmissionChannel FormSubmissionChannel
sms
FormSubmissionChannel FormSubmissionChannel
ignored
array<string>
error
string
code
stringone of identity_conflict
emailContactId
stringformat=uuid
phoneContactId
stringformat=uuid
externalId
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
FormSubmissionReceiptRead
receiptrequired
FormSubmissionReceipt FormSubmissionReceipt
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TeamMemberList

The authorized organization's roster, safely projected. Each member's role and membership status come from THAT organization's canonical membership, so a member whose own selected organization is elsewhere is still shown with this organization's role. total is the true number of distinct members, not one page's length; hasMore is computed from the rows actually returned.

membersrequired
array<object>
paginationrequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TeamInvitationList

The authorized organization's CURRENT pending invitations. Excludes accepted, cancelled, dismissed, and expired invitations. Never includes an invitation token or copy-link value. total is the true count, not one page's length.

invitationsrequired
array<object>
paginationrequired
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactFieldList

The authorized organization's contact-field registry: explicit key/label/type definitions unioned with the keys that already appear in contacts' stored custom values, whose type is inferred from those values. key is preserved verbatim (including spaces and case); label is as stored. This is a bounded, read-only result returning the full registry and total count, not a single page, and it never returns contact values, contact ids, or the contacts that carry a field.

fieldsrequired
array<object>
totalrequired
integermin=0The true number of discovered fields.
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactFieldWriteRequest

One explicit contact-field definition to upsert, keyed by key. A caller-supplied tenant/provider/actor selector is refused, not stripped. This saves field METADATA only: it does not convert, clear, or repair any contact's stored value, and it does not change a stored value's type.

keyrequired
stringminLength=1, maxLength=120Field key, preserved verbatim. At most 120 characters.
labelrequired
stringminLength=1, maxLength=120Human-readable label, stored trimmed. At most 120 characters.
typerequired
stringone of text, number, date, boolean
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
ContactFieldWrite

The result of saving a contact-field definition. When confirmed is true, field is the ACTUAL stored row read back after the upsert. When confirmed is false the save committed but the stored row could not be read back; the definition was written, so do not treat it as a refusal and do not replay it blindly.

successrequired
boolean
confirmedrequired
booleanTrue when the stored row was read back after the save.
field
object
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SendingDomainDnsRecord

One required DNS record to publish for the organization's owned sending domain. The host is the absolute owner name without a final dot; the data is the absolute target.

typerequired
stringone of CNAME
hostrequired
string
relativeHostrequired
string
datarequired
string
requiredrequired
booleanone of true
purposerequired
stringone of dkim
validationrequired
stringone of identity_verified, not_confirmed
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SendingDomainRecommendation

An advisory TXT record suggesting SPF or DMARC, offered with a transactional domain. It is not required and is not a proven current DNS state.

typerequired
stringone of TXT
hostrequired
string
relativeHostrequired
string
datarequired
string
requiredrequired
booleanone of false
purposerequired
stringone of spf, dmarc
validationrequired
stringone of not_checked
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SendingDomainView

The organization's sending-domain authentication state and the exact records it must publish. An authenticated domain is never channel-ready, and MAIL FROM is outside this workflow.

domainrequired
string | nullnullable
fromEmailrequired
string | nullnullable
ownershiprequired
stringone of owned, not_linked, conflict
authenticatedrequired
boolean
statusrequired
stringone of authenticated, awaiting_dns, not_started, not_linked, unavailable, unknown, not_configured
operationCompleterequired
boolean
providerOutcomerequired
stringone of not_called, observed, unknown
persistencerequired
stringone of unchanged, committed, failed, unknown
observationrequired
objectWhere the current state was read from and whether it is stale.example {"source":"provider_readback","checkedAt":"2026-10-14T12:00:00.000Z","stale":false}
dnsrequired
array<SendingDomainDnsRecord> SendingDomainDnsRecord
recommendationsrequired
array<SendingDomainRecommendation> SendingDomainRecommendation
channelReadinessrequired
objectDomain authentication is not channel readiness.example {"status":"not_assessed","domainOnly":true}
mailFromrequired
objectCustom MAIL FROM is not managed by this workflow.example {"managedByThisWorkflow":false,"status":"not_assessed"}
nextActionrequired
stringone of publish_dns, verify, recover, update_organization_settings, resolve_ownership, none
messagerequired
string | nullnullable
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SendingDomainPreview

The result of previewing a sending-domain action. No claim, provider call, or persistence happened.

domainrequired
string | nullnullable
fromEmailrequired
string | nullnullable
profilerequired
stringone of campaign, transactional, registry
eligiblerequired
boolean
blockersrequired
array<string>
sideEffectsrequired
array<string>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SendingDomainPreviewRequest

A proposed sending-domain configuration to check. It takes no organization or user selector, no raw records, no URL, and no local path.

domain
string
from_email
string
profile
stringone of campaign, transactional, registry
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
SendingDomainConfigureRequest

A sending-domain configuration action. It takes no confirmation flag, no organization or user selector, no raw records, no URL, and no local path. action is required.

actionrequired
stringone of ensure, verify, recover
profile
stringone of campaign, transactional, registry
domain
string
from_email
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TestRecipientWrite

An address to allow for email test sends after it confirms.

emailrequired
stringformat=email
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TestRecipientList

Test recipients for this organization. Confirmation links are not included.

recipientsrequired
array<object>
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.
TestRecipientEnvelope

The saved test recipient, and whether a verification email was sent.

recipientrequired
object
verificationEmailSentrequired
boolean
message
string
Complete schema (JSON)
Loading schema. If it does not appear, open the schema bundle or /openapi.json.

Coverage & status

The reference below shows available agent operations and the dashboard workflows for account management and campaign setup. Follow each workflow's role, scope, and setup requirements.

Campaign (texting) registrationReading the stored campaign-registration readiness and running the free website-compliance preflight are available through get_texting_campaign_registration and check_texting_campaign_site. Paid campaign filing is available through submit_texting_campaign_registration (POST /api/v1/registration/campaign/submit) when the credential holds registration:submit and the active organization owner has completed setup. An uncertain carrier outcome is never retried blindly.
Member and team managementAn authorized owner/admin credential can read the organization's roster and its CURRENT pending invitations through list_team_members and list_team_invitations (scope team:read, owner/admin only), and can invite, re-queue, and cancel a team invitation and change, suspend, reactivate, or remove an ordinary (non-owner) member through a narrow set of team:manage tools and /api/v1/team operations. The management surface is ordinary organization authority only: the organization owner cannot be acted on, self-actions are refused, promotion to owner is refused, the last active admin cannot be suspended or removed, and platform is_admin alone is not authority. An invitation write queues a source email event, which is NOT proof of delivery. Two gaps remain: an invitee's own identity-plane actions (accepting, previewing, or dismissing their own invitation) and the credential lifecycle (creating, listing, rotating, or revoking API keys and OAuth connected apps) still have no tool and stay in the signed-in product. Do not present invitee-side acceptance or credential management as a runnable step.
Credentials and connected appsCreating, listing, rotating, or revoking API keys and OAuth connected apps has no tool. A key is minted and revoked by a signed-in owner in Account Settings.
Sending domain and DNS configurationReading an organization's sending-domain authentication state, previewing a configuration, and creating, rechecking, or resuming the domain identity are available through get_sending_domain, preview_sending_domain, and configure_sending_domain and the versioned /api/v1/communications/sending-domain operations. The Agent API returns the exact DNS records an owned domain requires. Publishing those records at the customer's own DNS host stays with the customer, and provider-hosted DNS changes, domain deletion or detach, and custom MAIL FROM are out of scope. Do not present MAIL FROM as configured.
Funding and payment-method managementBalance and ledger reads and existing Auto Top-Up configuration are available through billing tools. Adding or removing a payment method, initiating a deposit, and recording an offline payment have no tool. Card entry stays in the secure payment interface, never in a chat or tool argument.
Calling execution, media, and reachA member's connected agent can read the prepared calling queues it may work and save the member's own operator phone (calls:read and calls:operate). Placing, advancing, media, or billing a call, buying or provisioning a number, and the full personal-settings, key-management, and account portals remain unavailable to a member credential and stay in the signed-in product. Do not present starting, advancing, or billing a call as a runnable step for a member connection.
Phone numbers and defaultsPurchasing a toll-free or local number and setting the organization's default campaign phone are available through purchase_phone_number and set_default_phone_number. Local numbers are automatically attached to the organization's current 10DLC campaign when one is approved.
Import list cleaningA commit never cleans and never charges. Cleaning exactly the contacts a single import saved is a SEPARATE, bounded paid step: clean_import_cohort acts on the cohortId a preview-backed commit returns and on nothing else, so a file's cleaning permission never triggers a whole-organization run. A commit that asks for cleaning reports the channels as REQUESTED and NOT PERFORMED by the commit. An import that is not preview-backed captures no cohort, so there is nothing for the cohort-scoped step to act on.
Large import files and staged uploadsAn MCP contact import travels base64-encoded inside one JSON-RPC body, and the request body cap is 4.5 MB, so the inline aggregate is bound near 2.6 MiB decoded. A larger file can be sent in bounded chunks with stage_contact_import_upload, which stores the bytes and returns a durable staging id. Pass that staging_id to preview_contact_import or commit_contact_import in a JSON body to import the staged file. The dashboard multipart import and the multipart REST route remain available for callers that prefer them.
Form-intake write atomicityA website form submission commits its contact mutation and its stored receipt in a single serialized transaction per organization. It checks for an existing same-key receipt before mutating, re-validates the prepared contact and email/phone matches at commit time, and writes the receipt in the same transaction. A same-key concurrent duplicate commits a single mutation and replays the first winner's receipt, and a receipt failure rolls the contact write back. A stored receipt records the outcome of the first accepted write, not proof that the current contact still matches that request, as later edits can update the contact. After an interrupted keyed request, read the stored receipt for that external_id before retrying. Submissions without an external_id perform the contact action without deduplication or replay.
Member and volunteer delegated credentialsOperational portal credentials require an active owner or admin membership in the organization, matching the dashboard's access boundary. Eligible owners and admins can read and update their own personal profile and preferences, which apply across every organization they belong to. Members with calling access can use OAuth calling-workspace tools (calls:read and calls:operate), while broader member or volunteer credential delegation is not available. Do not present general member or volunteer operational access as available.
Contact-field value typing and advanced filter parityAn agent can DISCOVER the contact-field registry (list_contact_fields) and SAVE an explicit key/label/type definition (upsert_contact_field), and the versioned route GET|PUT /api/v1/contacts/fields backs both. But saving a definition changes field METADATA only: it does NOT convert, clear, or repair any contact's stored value, and it does not change a stored value's type; a value that no longer matches the new type keeps its stored text. Writing a TYPED field VALUE onto a contact, and the advanced typed-filter surface (typed operators such as gt/gte/lt/lte/neq/contains over typed values), still have no tool and no Agent API operation. Only the flat text/number custom-value write on create_contact/update_contact is available. Do not present a definition save as a value conversion, and do not present registry discovery or a definition save as advanced filter parity.

Requirements and availability

  • Connect through a host that supports remote MCP and OAuth 2.1. Sign in, choose your organization, and approve the requested scopes. After initialization and tool discovery, call get_capabilities to confirm your organization, granted scopes, and setup state. Configure the host connection once; tool access depends on your current role and granted scopes.
  • The self-service MCP connection uses OAuth authorization-code flow with PKCE S256 and public-client registration (token_endpoint_auth_method=none). No manually supplied client secret or manually minted API key is required. Use the host's connection settings to complete sign-in and consent.
  • Business access requires an organization-bound credential and eligible membership. Follow each tool's role, scope, setup, billing, and confirmation requirements; connecting does not grant additional permissions or complete business setup.
  • An authorized owner/admin credential can read the organization roster and current pending invitations and manage ordinary (non-owner) team members. An invitee's own identity-plane actions and credential lifecycle actions (creating, listing, rotating, or revoking API keys and OAuth connected apps) have no MCP tool. Billing balance, ledger and existing Auto Top-Up configuration tools are available. Consult each capability gap for its remaining limitation.
  • A registered texting brand alone is not SMS campaign approval or full texting readiness. Reading the stored campaign-registration readiness and running the free website-compliance preflight are available through get_texting_campaign_registration and check_texting_campaign_site; paid campaign filing is available through submit_texting_campaign_registration when the credential holds registration:submit. Check get_sms_readiness before treating a brand as ready to text.
  • For hosts that support API-key authentication, configure an existing valid Campaign Commander API key only in the host's secret settings, vault or environment. Hosts that require OAuth should use the MCP OAuth connection flow; no API-key entry field is assumed. Never paste a credential into chat or a tool argument, and do not treat an unauthenticated 401 as proof that an account is disconnected.
  • A campaign registration's already_filed flag means a carrier campaign reference is recorded, not approval, delivery, or a charge, and a missing reference does not prove the carrier received nothing. confirmation_required or submitting mean an existing attempt must not be filed again; reconcile it with support. None of these flags establish whether a review fee was charged, so a missing carrier identity is never permission to submit.
  • Each tool publishes its complete required scope set. An eligible active/full-access OAuth actor missing an in-role scope receives the standard HTTP 403 insufficient-scope challenge and may receive an optional matching tool-result hint. The host must support interactive OAuth reauthorization to request new, explicit, user-approved consent; use its connection settings if it does not start that flow automatically. Security policy is published in _meta.securitySchemes, not a top-level securitySchemes field; hosts that require the top-level field must support this metadata location to use it.

Connection requirements

Connect through a host that supports remote MCP and OAuth 2.1. Sign in, choose your organization, and approve the requested scopes. After initialization and tool discovery, call get_capabilities to confirm your organization, granted scopes, and setup state. Configure the host connection once; tool access depends on your current role and granted scopes.