Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.truagents.com/llms.txt

Use this file to discover all available pages before exploring further.

Work in Progress — This API design is under active development. The current per-organization unsubscribe model may conflict with multi-org setups where clients expect a unified suppression list across all their organizations, with optional per-org overrides. The final design needs to account for this before implementation.

Summary

The Unsubscribe API lets external systems query and update contact communication preferences (email, SMS, phone) across multiple TruAgents organizations through a single authenticated API key. This is the right integration path when a client manages several organizations and needs to programmatically sync suppression lists or manage unsubscribe state across channels.

Who this is for

Technical admins and developers integrating external compliance or suppression systems with TruAgents.

Where it fits in the product

  • Administration → API Keys for key creation and management
  • Contacts for the underlying unsubscribe preferences being read and written

Prerequisites

Before using the Unsubscribe API:
  1. A teammate account with access to the target organizations (via managed organizations)
  2. An API key created through the admin UI, scoped to the desired organizations
  3. The API key token (shown once at creation — store it securely)

Authentication

All requests require a Bearer token in the Authorization header:
Authorization: Bearer <api_token>
The API key determines which organizations the caller can access. Requests targeting an organization outside the key’s scope return 403 Forbidden.
Future versions may support additional authentication methods such as OAuth 2.0 (client credentials) and mutual TLS (mTLS) for clients with specific security requirements.

Endpoints

Base URL: https://app.truagents.com/api/v1/unsubscribe

Query unsubscribed contacts

curl -X GET "https://app.truagents.com/api/v1/unsubscribe?channel=email&limit=50" \
  -H "Authorization: Bearer <api_token>"
Returns contacts that are unsubscribed from at least one channel, across the key’s authorized organizations. Query parameters
ParameterTypeRequiredDescription
org_slugstringNoFilter to a specific organization. Omit to query all orgs in the key’s scope.
channelstringNoFilter by channel: email, sms, or phone. Only returns contacts unsubscribed from this channel.
sinceISO 8601NoOnly return contacts whose unsubscribe status changed on or after this timestamp.
untilISO 8601NoOnly return contacts whose unsubscribe status changed on or before this timestamp.
cursorstringNoCursor for pagination. Use next_cursor from the previous response.
limitintegerNoResults per page (default: 100, max: 1000).
Response
{
  "data": [
    {
      "org_slug": "acme-corp",
      "email": "john@example.com",
      "phone": "+15551234567",
      "unsubscribed_from_email": true,
      "unsubscribed_from_sms": false,
      "unsubscribed_from_phone": false,
      "unsubscribed_at": "2026-04-15T10:30:00Z"
    }
  ],
  "next_cursor": "eyJpZCI6ImNseDEyMyIsIm9yZyI6ImFjbWUtY29ycCJ9",
  "has_more": true
}
  • Only contacts with at least one true unsubscribe field are returned.
  • Results are ordered by unsubscribed_at descending (most recent changes first).
  • unsubscribed_at is the timestamp of the most recent unsubscribe status change.
  • next_cursor is null when there are no more results.

Update unsubscribe status

curl -X POST "https://app.truagents.com/api/v1/unsubscribe" \
  -H "Authorization: Bearer <api_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "email": "john@example.com",
        "unsubscribed_from_email": true,
        "unsubscribed_from_sms": true
      },
      {
        "phone": "+15559876543",
        "org_slug": "acme-west",
        "unsubscribed_from_phone": true
      }
    ]
  }'
Sets unsubscribe status for one or more contacts. Supports batch operations up to 10,000 items per request. Request body
FieldTypeRequiredDescription
itemsarrayYesArray of unsubscribe operations (max 10,000).
Each item in the items array:
FieldTypeRequiredDescription
emailstringYes*Contact email. At least one of email or phone is required. Contact is matched by email within the organization.
phonestringYes*Contact phone. At least one of email or phone is required. Used for matching if email is not provided.
org_slugstringNoTarget organization. Omit to apply across all orgs in the key’s scope.
unsubscribed_from_emailbooleanNoSet email unsubscribe status. Omit to leave unchanged.
unsubscribed_from_smsbooleanNoSet SMS unsubscribe status. Omit to leave unchanged.
unsubscribed_from_phonebooleanNoSet phone unsubscribe status. Omit to leave unchanged.
At least one unsubscribe field must be provided per item. Response
{
  "processed": 2,
  "updated": [
    { "org_slug": "acme-corp", "email": "john@example.com" },
    { "org_slug": "acme-west", "phone": "+15559876543" }
  ],
  "not_found": [
    { "org_slug": "acme-east", "email": "john@example.com" }
  ],
  "skipped_items": []
}
  • The operation is not atomic — each item is processed independently. Partial failures do not roll back successful updates.
  • processed is the total number of successful operations.
  • updated lists contacts where a match was found and unsubscribe status was changed.
  • not_found lists organizations where no matching contact exists. This is not an error — the contact may simply not exist in that org.
  • skipped_items lists items that were skipped due to conflicts (see below).

Contact matching and conflicts

Contacts are matched within each organization using the same rules as the Contacts API:
  • If email is provided, the contact is matched by email (unique per organization).
  • If only phone is provided, the contact is matched by phone (unique per organization).
  • If both email and phone are provided and they match different existing contacts within the same organization, the item is skipped as a conflict.
Skipped items appear in the skipped_items array with a reason:
{
  "skipped_items": [
    {
      "email": "john@example.com",
      "phone": "+15559999999",
      "org_slug": "acme-corp",
      "reason": "email and phone match different existing contacts"
    }
  ]
}

Error responses

StatusDescription
401Missing, invalid, expired, or inactive API key.
403The requested org_slug is not in the key’s authorized scope.
400Missing required fields, invalid parameters, or batch size exceeds 10,000.
422No unsubscribe fields provided in one or more items.

API key management

API keys are created and managed through the TruAgents admin UI.

Creating an API key

  1. Navigate to Administration → API Keys.
  2. Enter a label (e.g., “Production Suppression Sync”).
  3. Select the organizations this key should have access to. Only organizations in your managed organizations list are available.
  4. Optionally set an expiration date.
  5. Copy the generated token immediately — it is shown only once and cannot be retrieved later.

Key details visible in admin

  • Label and token prefix (e.g., abcdef12...) for identification
  • Scoped organizations
  • Created date and last used timestamp
  • Active/inactive status

Teammate deactivation

When a teammate account is deactivated, all API keys owned by that teammate are automatically deactivated. Re-activating the teammate does not restore the keys — new keys must be created.

Security best practices

  • Store API tokens in a secrets manager, not in code or configuration files.
  • Scope keys to the minimum set of organizations needed.
  • Set expiration dates and rotate keys periodically.
  • Deactivate unused keys rather than deleting them, to preserve the audit trail.
  • Monitor last_used_at to identify stale keys.

Common mistakes

  • Forgetting to copy the API token at creation time — it cannot be shown again.
  • Using an API key scoped to one organization and expecting it to work across others.
  • Omitting all unsubscribe fields in a POST item — at least one of unsubscribed_from_email, unsubscribed_from_sms, or unsubscribed_from_phone is required per item.
  • Sending both email and phone that belong to different contacts in the same org — the item is skipped as a conflict.