> ## Documentation Index
> Fetch the complete documentation index at: https://docs.forecastable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send Engage message (REST only)

> Unified multi-channel send with a discriminated source union (oneOff, template, draft) and a required sendIndividually flag. sendIndividually: true delivers one personalized message per recipient (all merge variables supported; recipients never see each other; cc/bcc require a single recipient). sendIndividually: false delivers a single email with every recipient together on the To line (email channel only; cc/bcc allowed): recipient-personalized variables ({{first_name}}, {{last_name}}, {{full_name}}) are rejected with 422, while account and sender variables remain available. Requires an Idempotency-Key header. Returns 200 only after an immediate provider send; returns 202 with queue IDs for scheduled, worker-queued, or approval-pending sends. This operation is intentionally not exposed as an MCP tool.



## OpenAPI

````yaml /openapi.json post /engage/messages/send
openapi: 3.0.3
info:
  title: Forecastable Integration API
  version: 1.0.0
  description: >-
    Partner-facing integration REST API at /api/v1. Authenticated requests
    require a bearer token and organization context via X-Organization-Id (or
    organizationId query param on read endpoints). Legacy X-Subscriber-Id and
    subscriberId are still accepted. Approved scopes: organizations:read,
    accounts:read/write/delete, contacts:read/write/delete,
    opportunities:read/write/delete, engage:read/write/send, feed:read,
    plans:read/write/delete, calendar:read/write.
servers:
  - url: https://app.forecastable.com/api/v1
    description: Production
security:
  - BearerAuth: []
tags:
  - name: meta
    description: Integration API foundation metadata.
  - name: organizations
    description: Organization (subscriber) discovery and settings.
  - name: accounts
    description: Account CRUD and bulk operations.
  - name: buying-groups
    description: >-
      Buying groups for an account. Account-level plans attach to the
      default/system buying group ("… Default Plan"). Use
      listAccountBuyingGroups or listBuyingGroups?accountId= before createPlan
      when you need a non-default group.
    x-group: Accounts
  - name: contacts
    description: Account contact CRUD.
  - name: opportunities
    description: Opportunity CRUD.
  - name: leads
    description: Lead CRUD and CRM upsert.
  - name: relationship-maps
    description: Buyer relationship map read and write.
  - name: plans
    description: >-
      Plans (MSPs) for accounts (via default buying group), opportunities,
      buying groups, and personal USER plans. A plan contains milestones, goals,
      and tasks. Use GET /plans/{planId} to load everything in one call. Account
      plans: entityType=ACCOUNT with entityId=<accountId>. Personal plans:
      entityType=USER with entityId=<ownerUserId>.
    x-group: Plans
  - name: plan-milestones
    description: >-
      Ordered phases within a plan. DELETE archives; POST .../restore
      un-archives.
    x-group: Milestones
  - name: plan-goals
    description: Targets attached to a plan. DELETE archives a goal (soft delete).
    x-group: Goals
  - name: plan-tasks
    description: >-
      Work items on a plan, optionally linked to a milestone. GET /tasks lists
      tasks assigned to you across all plans.
    x-group: Tasks
  - name: engage-templates
    description: Engage message templates (email, LinkedIn, Slack). DELETE archives.
    x-group: Engage Templates
  - name: engage-drafts
    description: Engage drafts. Create, read, update, and permanently delete.
    x-group: Engage Drafts
  - name: engage-lists
    description: >-
      Engage lists and members. Manual lists store explicit members; dynamic
      lists derive membership from criteria and are read-only for member
      mutations.
    x-group: Engage Lists
  - name: engage-campaigns
    description: >-
      Engage campaign (flow) definitions, bulk creation, execution status, and
      enrollment job status.
    x-group: Engage Campaigns
  - name: engage-queue
    description: >-
      Read-only outbound queue across channels with per-recipient delivery and
      engagement detail.
    x-group: Engage Queue
  - name: engage-replies
    description: >-
      Read-only inbound replies to Engage sends. Phase 1 exposes email/Nylas
      reply bodies with plain-text by default and optional HTML.
    x-group: Engage Queue
  - name: engage-messages
    description: >-
      Outbound send and campaign start. REST-only: these operations are excluded
      from the MCP tool surface and require an Idempotency-Key header.
    x-group: Engage Messaging
  - name: calendar
    description: >-
      Synced calendar events and linked meeting artifacts (summary, action
      items, transcript) for the authenticated user. Reads may include
      authorized teammate events; updates apply only to viewer-owned events and
      push through the connected calendar provider. Requires a user-backed
      token.
    x-group: Calendar
  - name: feed
    description: >-
      Account inbox (email, Slack, calendar) and dashboard communication
      analytics / needs-attention reads. Requires feed:read. Dashboard endpoints
      require a user-backed token.
    x-group: Feed
paths:
  /engage/messages/send:
    post:
      tags:
        - engage-messages
      summary: Send Engage message (REST only)
      description: >-
        Unified multi-channel send with a discriminated source union (oneOff,
        template, draft) and a required sendIndividually flag. sendIndividually:
        true delivers one personalized message per recipient (all merge
        variables supported; recipients never see each other; cc/bcc require a
        single recipient). sendIndividually: false delivers a single email with
        every recipient together on the To line (email channel only; cc/bcc
        allowed): recipient-personalized variables ({{first_name}},
        {{last_name}}, {{full_name}}) are rejected with 422, while account and
        sender variables remain available. Requires an Idempotency-Key header.
        Returns 200 only after an immediate provider send; returns 202 with
        queue IDs for scheduled, worker-queued, or approval-pending sends. This
        operation is intentionally not exposed as an MCP tool.
      operationId: sendEngageMessage
      parameters:
        - $ref: '#/components/parameters/OrganizationIdHeader'
        - $ref: '#/components/parameters/OrganizationIdQuery'
        - $ref: '#/components/parameters/IdempotencyKeyHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EngageMessageSendRequest'
      responses:
        '200':
          description: Message sent immediately.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EngageMessageSendResponse'
        '202':
          description: Message accepted for scheduled or approval-pending delivery.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EngageMessageSendResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - OAuth2:
            - engage:send
components:
  parameters:
    OrganizationIdHeader:
      name: X-Organization-Id
      in: header
      required: false
      description: >-
        Active organization UUID. Required for authenticated requests when the
        principal has access to multiple organizations.
      schema:
        type: string
        format: uuid
        pattern: >-
          ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$
    OrganizationIdQuery:
      name: organizationId
      in: query
      required: false
      description: >-
        Read-only convenience alias for X-Organization-Id. Legacy subscriberId
        query param is also accepted.
      schema:
        type: string
        format: uuid
        pattern: >-
          ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$
    IdempotencyKeyHeader:
      name: Idempotency-Key
      in: header
      required: true
      description: >-
        Unique client-generated key for safe retries. Replaying the same key
        with the same payload returns the stored result; reuse with a different
        payload returns 409.
      schema:
        type: string
        minLength: 1
        maxLength: 255
  schemas:
    EngageMessageSendRequest:
      type: object
      additionalProperties: false
      required:
        - source
        - sendIndividually
      properties:
        source:
          oneOf:
            - $ref: '#/components/schemas/EngageSendSourceOneOff'
            - $ref: '#/components/schemas/EngageSendSourceTemplate'
            - $ref: '#/components/schemas/EngageSendSourceDraft'
          discriminator:
            propertyName: type
        sendIndividually:
          type: boolean
          description: >-
            Required. true sends one personalized message per recipient: all
            merge variables are supported, recipients never see each other, and
            cc/bcc require a single recipient. false sends one email with every
            recipient together on the To line (email channel only; cc/bcc
            allowed for any recipient count): recipient-personalized variables
            ({{first_name}}, {{last_name}}, {{full_name}}) are rejected with 422
            because all recipients share one body, while account and sender
            variables such as {{account_name}} and {{sender_first_name}} remain
            available.
        senderUserId:
          type: string
          format: uuid
          pattern: >-
            ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$
          description: >-
            Organization user to send as. Required for client-credential tokens;
            user tokens default to the authenticated user.
        accountId:
          type: string
          format: uuid
          pattern: >-
            ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$
        to:
          type: array
          maxItems: 100
          items:
            $ref: '#/components/schemas/EngageSendRecipient'
        cc:
          type: array
          maxItems: 50
          items:
            $ref: '#/components/schemas/EngageSendRecipient'
        bcc:
          type: array
          maxItems: 50
          items:
            $ref: '#/components/schemas/EngageSendRecipient'
        engageListId:
          type: string
          format: uuid
          pattern: >-
            ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$
        sendAt:
          type: string
          format: date-time
        needsApproval:
          type: boolean
        trackingOptions:
          type: object
          additionalProperties: false
          properties:
            opens:
              type: boolean
            links:
              type: boolean
            threadReplies:
              type: boolean
        simulate:
          type: boolean
          description: >-
            Validate and render the send without performing any outbound
            provider call or writing queue rows.
    EngageMessageSendResponse:
      type: object
      additionalProperties: false
      required:
        - status
        - queueIds
        - simulated
      properties:
        status:
          type: string
          enum:
            - sent
            - scheduled
            - queued
            - pending_approval
            - simulated
        queueIds:
          type: array
          items:
            type: string
        scheduledAt:
          type: string
          format: date-time
          nullable: true
        simulated:
          type: boolean
    EngageSendSourceOneOff:
      type: object
      additionalProperties: false
      required:
        - type
        - channel
        - body
      properties:
        type:
          type: string
          enum:
            - oneOff
        channel:
          $ref: '#/components/schemas/EngageChannel'
        subject:
          type: string
          maxLength: 998
        body:
          type: string
          minLength: 1
          maxLength: 500000
    EngageSendSourceTemplate:
      type: object
      additionalProperties: false
      required:
        - type
        - templateId
      properties:
        type:
          type: string
          enum:
            - template
        templateId:
          type: string
          format: uuid
          pattern: >-
            ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$
        variableOverrides:
          type: object
          additionalProperties:
            type: string
    EngageSendSourceDraft:
      type: object
      additionalProperties: false
      required:
        - type
        - draftId
      properties:
        type:
          type: string
          enum:
            - draft
        draftId:
          type: string
          format: uuid
          pattern: >-
            ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$
        variableOverrides:
          type: object
          additionalProperties:
            type: string
    EngageSendRecipient:
      type: object
      additionalProperties: false
      properties:
        email:
          type: string
          maxLength: 320
        name:
          type: string
          maxLength: 300
        contactId:
          type: string
          format: uuid
          pattern: >-
            ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$
        linkedinUrl:
          type: string
          maxLength: 500
        slackUserId:
          type: string
          maxLength: 100
    ErrorEnvelope:
      type: object
      additionalProperties: false
      required:
        - error
      properties:
        error:
          type: object
          additionalProperties: false
          required:
            - code
            - message
            - details
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: object
              additionalProperties: true
    EngageChannel:
      type: string
      enum:
        - email
        - linkedin
        - slack
  responses:
    BadRequest:
      description: Validation error or missing subscriber context.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Unauthorized:
      description: Missing or invalid bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Forbidden:
      description: Insufficient scope or organization access.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    NotFound:
      description: Resource not found in organization scope.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    Conflict:
      description: Conflict such as duplicate CRM ID.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    UnprocessableEntity:
      description: Semantic validation error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    RateLimited:
      description: Rate limit exceeded.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: api-key or OAuth access token
      description: >-
        Partner integration API key issued from developer settings, or OAuth2
        access token.
    OAuth2:
      type: oauth2
      description: >-
        Partner OAuth2 flows for integration API access tokens. Claude MCP
        custom connectors use authorization code with PKCE S256.
      flows:
        authorizationCode:
          authorizationUrl: /api/v1/oauth/authorize
          tokenUrl: /api/v1/oauth/token
          scopes:
            organizations:read: organizations:read scope for Forecastable Integration API
            accounts:read: accounts:read scope for Forecastable Integration API
            accounts:write: accounts:write scope for Forecastable Integration API
            accounts:delete: accounts:delete scope for Forecastable Integration API
            contacts:read: contacts:read scope for Forecastable Integration API
            contacts:write: contacts:write scope for Forecastable Integration API
            contacts:delete: contacts:delete scope for Forecastable Integration API
            opportunities:read: opportunities:read scope for Forecastable Integration API
            opportunities:write: opportunities:write scope for Forecastable Integration API
            opportunities:delete: opportunities:delete scope for Forecastable Integration API
            engage:read: engage:read scope for Forecastable Integration API
            engage:write: engage:write scope for Forecastable Integration API
            engage:send: engage:send scope for Forecastable Integration API
            feed:read: feed:read scope for Forecastable Integration API
            plans:read: plans:read scope for Forecastable Integration API
            plans:write: plans:write scope for Forecastable Integration API
            plans:delete: plans:delete scope for Forecastable Integration API
            calendar:read: calendar:read scope for Forecastable Integration API
            calendar:write: calendar:write scope for Forecastable Integration API
        clientCredentials:
          tokenUrl: /api/v1/oauth/token
          scopes:
            organizations:read: organizations:read scope for Forecastable Integration API
            accounts:read: accounts:read scope for Forecastable Integration API
            accounts:write: accounts:write scope for Forecastable Integration API
            accounts:delete: accounts:delete scope for Forecastable Integration API
            contacts:read: contacts:read scope for Forecastable Integration API
            contacts:write: contacts:write scope for Forecastable Integration API
            contacts:delete: contacts:delete scope for Forecastable Integration API
            opportunities:read: opportunities:read scope for Forecastable Integration API
            opportunities:write: opportunities:write scope for Forecastable Integration API
            opportunities:delete: opportunities:delete scope for Forecastable Integration API
            engage:read: engage:read scope for Forecastable Integration API
            engage:write: engage:write scope for Forecastable Integration API
            engage:send: engage:send scope for Forecastable Integration API
            feed:read: feed:read scope for Forecastable Integration API
            plans:read: plans:read scope for Forecastable Integration API
            plans:write: plans:write scope for Forecastable Integration API
            plans:delete: plans:delete scope for Forecastable Integration API
            calendar:read: calendar:read scope for Forecastable Integration API
            calendar:write: calendar:write scope for Forecastable Integration API

````