Hightouch Campaigns API

Trigger a campaign send to handle- or profile-based recipients and read back per-send status.

Business capability
Demand Generation Management BC-400.40

Operations 2

Each operation below carries the questions people ask an LLM about it and the instructions they give an agent to run it. Generated by API Evangelist overlay

POST /campaigns/{campaignId}/trigger Send an API-triggered campaign to recipients · Trigger an API campaign send #
Ask an LLM
“How do I send an API-triggered campaign to a list of recipients in Hightouch?”
“Can I share personalization properties across every recipient of a campaign send?”
Tell an agent
Trigger campaign {campaignId} for recipients {recipients}.
Send campaign {campaignId} to {recipients} with shared properties {properties}.
POST /campaigns/{campaignId}/sends/batch-get Get send delivery statuses #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/hightouch:hightouch-campaigns-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

hightouch-campaigns-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Hightouch Campaigns API
  version: 1.0.0
  description: Hightouch Public Rest API to access syncs, models, sources and destinations
  contact:
    name: Hightouch
    url: https://hightouch.com
servers:
- url: https://api.hightouch.com/api/v1
tags:
- name: Campaigns
paths:
  /campaigns/{campaignId}/trigger:
    post:
      operationId: TriggerCampaign
      responses:
        '200':
          description: Ok
          content:
            application/json:
              schema:
                anyOf:
                - $ref: '#/components/schemas/StartCampaignResponse'
                - $ref: '#/components/schemas/TriggerErrorResponse'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TriggerErrorResponse'
        '401':
          description: Unauthorized
        '404':
          description: Campaign not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TriggerErrorResponse'
        '422':
          description: Validation Failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidateErrorJSON'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TriggerErrorResponse'
        '500':
          description: Something went wrong
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalServerError'
      description: 'Start an API-triggered campaign: send to the given recipients.'
      summary: Trigger an API campaign send
      security:
      - bearerAuth: []
      parameters:
      - in: path
        name: campaignId
        required: true
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StartCampaignRequest'
      tags:
      - Campaigns
  /campaigns/{campaignId}/sends/batch-get:
    post:
      operationId: GetSendStatuses
      responses:
        '200':
          description: Ok
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchSendStatusResponse'
        '401':
          description: Unauthorized
        '422':
          description: Validation Failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidateErrorJSON'
        '500':
          description: Something went wrong
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalServerError'
      description: 'Get the delivery status of up to 100 sends in a single request, using the

        `sendId` values returned from the start endpoint. Prefer this over polling

        the single-send endpoint once per `sendId`.'
      summary: Get send delivery statuses
      security:
      - bearerAuth: []
      parameters:
      - in: path
        name: campaignId
        required: true
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchSendStatusRequest'
      tags:
      - Campaigns
components:
  schemas:
    CampaignRecipient:
      anyOf:
      - $ref: '#/components/schemas/HandleCampaignRecipient'
      - $ref: '#/components/schemas/ProfileCampaignRecipient'
      description: 'A single send target. Provide either `handle` (inline delivery address) or

        `id` (Personalization API profile ID), but not both.'
    StartCampaignResponse:
      description: 'Response body for a campaign trigger request. Results are returned in the

        same order as the input `recipients` array.'
      properties:
        results:
          items:
            $ref: '#/components/schemas/CampaignSendResult'
          type: array
          description: 'Per-recipient outcomes. Accepted recipients are queued for delivery;

            rejected recipients were not sent.'
      required:
      - results
      type: object
      additionalProperties: false
    TriggerErrorResponse:
      description: 'Body returned on a request-level failure (400/404/409/429) so the caller

        knows why the request was rejected.'
      properties:
        error:
          type: string
          description: Human-readable description of why the request failed.
      required:
      - error
      type: object
      additionalProperties: false
    InternalServerError:
      type: string
      enum:
      - Internal Server Error
    SendStatusReasonCode:
      type: string
      enum:
      - suppression_list
      - role_based_address_suppression
      - suspicious_domain_suppression
      - frequency_cap
      - quiet_hours
      - missing_channel_data
      - no_locale
      - unsubscribed
      - render_error
      - other
      - send_failed
      - delivery_failed
      description: 'Stable machine-readable reason a send was dropped or failed. Branch on this

        value; the wording of `reason` may change.'
    ValidateErrorJSON:
      properties:
        message:
          type: string
          enum:
          - Validation failed
        details:
          properties: {}
          additionalProperties: {}
          type: object
      required:
      - message
      - details
      type: object
      additionalProperties: false
    CampaignSendResult:
      description: 'Per-recipient result returned synchronously after the trigger request.

        Accepted recipients are queued for delivery; check the send status endpoint

        for delivery confirmation.'
      properties:
        handle:
          type: string
          description: Delivery address of the recipient, present for inline (`handle`) recipients.
        id:
          type: string
          description: 'Primary key of the recipient as configured on the Personalization API sync,

            present for profile (`id`) recipients.'
        status:
          type: string
          enum:
          - accepted
          - rejected
          description: Whether this recipient was accepted for delivery or rejected at validation time.
        sendId:
          type: string
          description: 'Unique identifier for this send, present when `status` is `"accepted"`.

            Use with `POST /campaigns/{id}/sends/batch-get` to poll for delivery

            status; it accepts up to 100 `sendId` values per request.'
        reason:
          type: string
          enum:
          - invalid_handle
          - missing_variables
          - invalid_id
          - missing_handle_or_id
          - invalid_locale
          - whatsapp_marketing_us_number
          description: "Reason for rejection, present when `status` is `\"rejected\"`.\n- `invalid_handle` — the delivery address is not a valid email or phone number\n- `missing_variables` — one or more required template variables are absent\n  (`handle` recipients only; `id` recipients are checked at send time)\n- `invalid_id` — the profile ID is empty or missing\n- `missing_handle_or_id` — the recipient has neither `handle` nor `id`\n- `invalid_locale` — the `locale` is empty or longer than 7 characters\n- `whatsapp_marketing_us_number` — the message uses a marketing WhatsApp template, which Meta does not deliver to US phone numbers"
        missingVariables:
          items:
            type: string
          type: array
          description: 'Names of the required template variables absent from the recipient''s data,

            present when `reason` is `"missing_variables"`.'
      required:
      - status
      type: object
      additionalProperties: false
    StartCampaignRequest:
      description: Request body for triggering an API campaign send.
      properties:
        properties:
          properties: {}
          additionalProperties: {}
          type: object
          description: 'Shared personalization properties applied to all recipients. Keys must

            match the variable names shown in the message editor. Per-recipient

            `properties` take precedence when a key appears in both.'
        draft:
          type: boolean
          description: 'When `true`, sends the campaign even if it has not been activated.

            Intended for test sends against draft campaigns only.'
          default: 'false'
        recipients:
          items:
            $ref: '#/components/schemas/CampaignRecipient'
          type: array
          description: 'List of recipients to send to. Each entry must include either a `handle`

            (delivery address) or an `id` (Personalization API based profile ID).'
          minItems: 1
          maxItems: 100
      required:
      - recipients
      type: object
      additionalProperties: false
    ProfileCampaignRecipient:
      description: 'A recipient identified by their Personalization API Cached profile ID.

        Template variables are checked at send time, after the cached profile is

        merged with `properties`. A required variable (one without a Liquid default)

        missing from both drops the send, which the send status endpoint reports as

        `dropped`. A variable present with a null or empty value renders blank.'
      properties:
        id:
          type: string
          description: 'Primary key of the recipient as configured on the Personalization API sync.

            The delivery address is resolved from the cache at send time.'
        properties:
          properties: {}
          additionalProperties: {}
          type: object
          description: 'Per-recipient personalization overrides. Merged with the top-level

            `properties` and the cached profile; these values take precedence when a

            key appears in multiple sources.'
        locale:
          type: string
          description: 'The recipient''s locale as a BCP 47 language tag, such as `es-ES`, matched

            against the locales the message is localized into (case-insensitive). When

            omitted, the recipient gets the message''s source language. A locale the

            message is not localized into follows the workspace''s localization fallback

            setting. At most 7 characters.'
      type: object
      additionalProperties: false
    BatchSendStatusResponse:
      description: 'Response body for the batch send status endpoint. Results are returned in the

        same order as the requested `sendIds`.'
      properties:
        results:
          items:
            $ref: '#/components/schemas/BatchSendStatusResult'
          type: array
          description: Per-send outcomes, in request order.
      required:
      - results
      type: object
      additionalProperties: false
    BatchSendStatusResult:
      description: Delivery status for one requested send.
      properties:
        sendId:
          type: string
          description: The `sendId` this result is for, echoed from the request.
        status:
          $ref: '#/components/schemas/SendStatus'
        reason:
          type: string
          description: 'Readable explanation for why this send was dropped or failed. Present

            when `status` is `"dropped"` or `"failed"`.'
        reasonCode:
          $ref: '#/components/schemas/SendStatusReasonCode'
          description: Stable code for `reason`. Present whenever `reason` is.
        updatedAt:
          type: string
          description: 'ISO 8601 time the status last changed. Absent when `status` is

            `"not_found"`.'
      required:
      - sendId
      - status
      type: object
      additionalProperties: false
    BatchSendStatusRequest:
      description: Request body for the batch send status endpoint.
      properties:
        sendIds:
          items:
            type: string
          type: array
          description: '`sendId` values returned by the trigger endpoint.'
          minItems: 1
          maxItems: 100
      required:
      - sendIds
      type: object
      additionalProperties: false
    SendStatus:
      type: string
      enum:
      - sent
      - delivered
      - bounced
      - failed
      - dropped
      - not_found
      description: 'Delivery status of a send. `not_found` means no send with this id exists on

        the campaign, including a send that has not been processed yet.'
    HandleCampaignRecipient:
      description: 'A recipient identified by their delivery address (email or phone number).

        Personalization data is provided inline in the request.'
      properties:
        handle:
          type: string
          description: 'Delivery address for this recipient. Must be a valid email address for

            email campaigns, or an E.164-formatted phone number for SMS and WhatsApp campaigns.'
        properties:
          properties: {}
          additionalProperties: {}
          type: object
          description: 'Per-recipient personalization properties. Keys must match the variable

            names shown in the message editor. These are merged with the top-level

            `properties` and take precedence when a key appears in both.'
        locale:
          type: string
          description: 'The recipient''s locale as a BCP 47 language tag, such as `es-ES`, matched

            against the locales the message is localized into (case-insensitive). When

            omitted, the recipient gets the message''s source language. A locale the

            message is not localized into follows the workspace''s localization fallback

            setting. At most 7 characters.'
      type: object
      additionalProperties: false
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Bearer
x-provenance:
  method: harvested
  publisher: Hightouch
  source: https://api.hightouch.com/api/swagger.json
  note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
    stamped by stamp-openapi-provenance.py (roadmap#793)