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

# Create and send an SMS campaign

> Send an SMS campaign immediately or schedule it for later.

<Warning>
  This operation uses the live messaging service and can consume message credits. Use an approved Sender ID and message only recipients you are permitted to contact.
</Warning>

<Warning>
  `sendAt` is always interpreted as Irish local time (`Europe/Dublin`). Do not include `Z` or a numeric UTC offset. For example, `2030-07-08T15:00` schedules delivery for 15:00 in Ireland, regardless of where the request originates. Convert the intended time to Irish local time before sending the request.
</Warning>

## Scheduling from outside Ireland

Phonovation does not use your device, server, account, or recipient timezone. It reads the date and clock time in `sendAt` as the time in Ireland.

Prefer `yyyy-MM-ddTHH:mm`. A space instead of `T` and optional seconds are also accepted. Supplied seconds are ignored, and the campaign is scheduled at the start of the minute.

| Desired local delivery time                         | Irish time to submit | `sendAt`           |
| --------------------------------------------------- | -------------------- | ------------------ |
| UK: 8 July 2030 at 15:00 (`Europe/London`)          | 8 July at 15:00      | `2030-07-08T15:00` |
| China: 8 July 2030 at 15:00 (`Asia/Shanghai`)       | 8 July at 08:00      | `2030-07-08T08:00` |
| China: 15 January 2030 at 15:00 (`Asia/Shanghai`)   | 15 January at 07:00  | `2030-01-15T07:00` |
| New York: 8 July 2030 at 15:00 (`America/New_York`) | 8 July at 20:00      | `2030-07-08T20:00` |

Use the IANA timezone `Europe/Dublin` in your date-time library. Do not hard-code an offset: Ireland changes offset during the year, and other countries may change clocks on different dates.

<Info>
  Omit `sendAt` or send `null` to send immediately. Empty and whitespace-only strings are invalid.
</Info>


## OpenAPI

````yaml openapi/phonovation-api.yaml POST /v1/campaign
openapi: 3.1.2
info:
  title: Phonovation SMS API
  version: 1.0.0
  summary: >-
    Build SMS into your product, workflow, or platform with a straightforward,
    developer-friendly API.
  description: >
    **Build fast. Send with confidence.**


    Add application-to-person (A2P) SMS to your product, workflow, or platform

    with Phonovation. Use this API to send or schedule campaigns, track each

    recipient in your own system, receive delivery updates, and review campaign

    results.


    From appointment reminders and service alerts to customer campaigns, you get

    a clear integration path and the delivery visibility needed to keep every

    message accountable.


    ## Account access


    [Log in or create your Phonovation account](https://app.phonovation.com/) to

    manage your messaging setup and developer settings.


    A typical integration has three steps:


    1. Authenticate with a bearer token.

    2. Create a campaign with your message, sender ID, and recipients.

    3. Track delivery through campaign summaries and signed webhooks.


    ## Authentication


    Every campaign request needs a bearer token — the credential that tells

    Phonovation which account is making the request. Add it to the

    `Authorization` header:


    `Authorization: Bearer <token>`


    ### Recommended: a UI-generated Personal Access Token


    For most integrations, the simplest and preferred option is a Phonovation

    Personal Access Token (PAT) generated in the Phonovation UI. PATs begin with

    `phv_pat_`; keep the casing exactly as shown when sending one:


    `Authorization: Bearer phv_pat_...`


    [Generate and manage your
    PATs](https://app.phonovation.com/developer?tab=pat-tokens)

    in the Phonovation developer settings.


    Generate the PAT once, store it securely, and reuse it for your API
    requests.

    **You do not need to obtain or refresh an OAuth token every time you send an

    SMS.** Replace the PAT only when it expires, is revoked, or you
    intentionally

    rotate it.


    ### Optional: OAuth access tokens


    OAuth/OIDC JWT access tokens remain available for integrations that
    specifically

    require an OAuth token lifecycle. The `/token` endpoint can exchange user

    credentials for an access token and refresh token, or exchange a refresh
    token

    for a new access token.


    Even when using OAuth, request an access token once and reuse it until it is
    close

    to expiry. Use the refresh token to obtain the next access token — do not
    request

    a new token before every SMS.


    ## Campaign processing


    Campaign requests are accepted and queued for background processing. A
    successful

    request returns `202 Accepted` with the campaign ID.


    A `202` response confirms receipt, not final campaign creation. Allow time
    for

    processing before requesting the campaign summary.


    ## Scheduling timezone


    The `sendAt` value is always interpreted as Irish local time in the

    `Europe/Dublin` timezone. Phonovation does not interpret it as UTC and does

    not use the timezone of the caller, server, account, or recipient.


    Do not include a timezone designator such as `Z` or a numeric UTC offset.

    International integrations must convert the intended send time to Irish

    local time before making the request. Ireland observes daylight saving time,

    so use a timezone-aware library and the `Europe/Dublin` timezone instead of

    a fixed UTC offset.
servers:
  - url: https://api.phonovation.com
    description: Phonovation production API
  - url: https://auth.phonovation.com
    description: Phonovation authentication server
security:
  - BearerAuth: []
tags:
  - name: Authentication
    description: >-
      Use a UI-generated PAT where possible, or obtain OAuth tokens for
      integrations that require them.
  - name: Health
    description: Check whether the Phonovation API is available and responding.
  - name: Campaigns
    description: Send now or schedule ahead, then track delivery from one integration.
paths:
  /v1/campaign:
    post:
      tags:
        - Campaigns
      summary: Create and send an SMS campaign
      description: >
        Send an SMS campaign to one or more recipients. You can send
        immediately,

        schedule it for later, or save it as a draft.


        If you omit `sendAt`, Phonovation uses the current Irish local time when

        creating the recipients.


        **Scheduling always uses Irish local time (`Europe/Dublin`).**
        Phonovation

        reads the date and clock time in `sendAt` as Irish time. It does not
        convert

        from UTC or from the caller's timezone. For example,

        `2030-07-08T15:00` means 15:00 in Ireland, even when the request is sent

        from China or another country.


        Do not append `Z` or a numeric UTC offset. Convert the intended send
        time

        to `Europe/Dublin` before submitting the request. Account for Irish
        daylight

        saving time rather than using a fixed offset.


        One invalid number does not have to stop the whole campaign. Invalid,

        duplicate, or unpermitted recipients may be skipped while valid
        recipients

        continue to be processed.


        Duplicate detection happens after phone-number normalization. If two
        entries

        resolve to the same number, Phonovation keeps the first entry and its

        `ClientReference`.


        A valid request returns `202 Accepted` when it has been queued for
        background

        processing.
      operationId: createCampaign
      requestBody:
        required: true
        description: |
          The message, sender, recipients, and optional campaign settings. Any
          `sendAt` value must contain the intended Irish local date and time.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateCampaignRequest'
            examples:
              oneRecipient:
                $ref: '#/components/examples/SingleRecipientCampaign'
              oneRecipientWithClientReference:
                $ref: >-
                  #/components/examples/SingleRecipientCampaignWithClientReference
              multipleRecipients:
                $ref: '#/components/examples/MultipleRecipientCampaign'
              multipleRecipientsWithClientReferences:
                $ref: >-
                  #/components/examples/MultipleRecipientCampaignWithClientReferences
              scheduled:
                $ref: '#/components/examples/ScheduledCampaign'
      responses:
        '202':
          description: The campaign is accepted for background processing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateCampaignResponse'
              examples:
                queued:
                  summary: Queued campaign
                  value:
                    id: ffd14db7-e526-4d69-b41e-ec5e38bc04dd
                    message: Campaign received to be processed
          links:
            GetCampaignSummary:
              operationId: getCampaignSummary
              parameters:
                id: $response.body#/id
              description: >
                Use the returned ID to request the campaign summary. Processing
                may

                still be in progress, so a summary might not be available
                immediately.
        '400':
          description: Request validation or immediate campaign creation fails.
          content:
            application/problem+json:
              schema:
                type: object
                required:
                  - title
                  - status
                  - detail
                properties:
                  title:
                    type: string
                    const: Validation Error
                  status:
                    type: integer
                    const: 400
                  detail:
                    type: string
                    description: Dynamic validation or campaign failure message.
              example:
                title: Validation Error
                status: 400
                detail: <dynamic validation or campaign failure message>
        '401':
          description: >-
            Authentication is missing or unsuccessful. No response body is
            returned.
          headers:
            WWW-Authenticate:
              description: Bearer authentication challenge.
              schema:
                type: string
                const: Bearer
              example: Bearer
        '403':
          description: >-
            Authentication succeeds, but the identity is not a recognized client
            administrator.
          content:
            application/problem+json:
              schema:
                type: object
                required:
                  - title
                  - status
                  - detail
                properties:
                  title:
                    type: string
                    const: Forbidden
                  status:
                    type: integer
                    const: 403
                  detail:
                    type: string
                    const: >-
                      Authenticated user is not a recognized client
                      administrator
              example:
                title: Forbidden
                status: 403
                detail: Authenticated user is not a recognized client administrator
      servers:
        - url: https://api.phonovation.com
          description: Phonovation production API
components:
  schemas:
    CreateCampaignRequest:
      type: object
      title: Create Campaign Request
      description: >-
        Everything Phonovation needs to create, schedule, or save an SMS
        campaign.
      required:
        - text
        - from
        - recipientInfo
      properties:
        text:
          type: string
          minLength: 1
          maxLength: 2000
          pattern: \S
          description: >
            The message your recipients will receive. It must include at least
            one

            visible character.


            Phonovation automatically detects the message encoding and
            calculates how

            many SMS parts will be sent and billed:


            - GSM-7: up to 160 characters in one part, then 153 per part.

            - UTF-16: up to 70 characters in one part, then 67 per part.

            - GSM-7 extended characters count as two character units.


            To improve handset compatibility, Phonovation replaces these
            typographic

            characters before sending:


            - typographic single quotes to `'`

            - typographic double quotes to `"`

            - en/em dashes to `-`

            - ellipsis to `.`

            - bullet to `*`


            The API does not automatically add opt-out or footer text, so
            include any

            wording required for your use case and compliance obligations.
          examples:
            - Your appointment is tomorrow at 10:30.
        from:
          type: string
          minLength: 1
          pattern: \S
          allOf:
            - if:
                pattern: ^[0-9]+$
              then:
                maxLength: 20
              else:
                maxLength: 11
          description: >
            The sender name or number recipients see on their phone.


            Leading and trailing spaces are removed automatically.


            - Numbers-only sender IDs may contain up to 20 digits.

            - All other sender IDs may contain up to 11 characters.

            - Numbers from `50000` through `59999` are reserved and cannot be
            used.


            Non-numeric sender IDs are not limited to letters and numbers by
            this API.


            For Irish recipients, the sender ID must be on the permitted sender
            list.

            Recipients for whom the sender is not permitted are skipped.
          examples:
            - CompanyName
            - '3531234567'
        recipientInfo:
          type: array
          minItems: 1
          description: >
            One or more people who should receive the campaign. The API does not
            set a

            maximum recipient count.


            Invalid or duplicate numbers may be skipped while valid recipients
            continue.

            Duplicate detection happens after phone-number normalization, and
            the first

            occurrence is kept.
          items:
            $ref: '#/components/schemas/Recipient'
        campaignName:
          type: string
          minLength: 1
          maxLength: 30
          pattern: \S
          default: API Broadcast
          description: >
            A short name to help you identify the campaign in reporting. If
            omitted,

            it defaults to `API Broadcast`.


            Keep the name to 30 characters or fewer. `null`, empty, and
            spaces-only

            values are rejected. Valid names are stored exactly as supplied.
          examples:
            - Summer Promotion
        sendAt:
          type:
            - string
            - 'null'
          pattern: ^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(:\d{2})?$
          description: >
            When the campaign should be sent, interpreted exclusively as Irish
            local

            time in the `Europe/Dublin` timezone.


            Phonovation reads the date and clock portion exactly as Irish time.
            It

            does not use the timezone of the caller, server, account, or
            recipient,

            and it does not convert the value from UTC. A request sent from
            China

            with `2030-07-08T15:00` schedules the campaign for 15:00 in Ireland,

            not 15:00 in China.


            Prefer `yyyy-MM-ddTHH:mm`, for example `2030-07-08T14:30`.

            These forms are accepted:


            - `yyyy-MM-ddTHH:mm`

            - `yyyy-MM-ddTHH:mm:ss`

            - `yyyy-MM-dd HH:mm`

            - `yyyy-MM-dd HH:mm:ss`


            If seconds are supplied, they are ignored and the scheduled time is

            normalized to the start of the minute.


            Example conversions for 8 July 2030 at 15:00 in the source country:


            - United Kingdom (`Europe/London`) becomes
              `2030-07-08T15:00` in Ireland.
            - China (`Asia/Shanghai`) becomes `2030-07-08T08:00` in Ireland.

            - New York, United States (`America/New_York`) becomes
              `2030-07-08T20:00` in Ireland.

            - Do not include `Z`, another timezone designator, or a numeric UTC
            offset.

            - If the intended send time is outside Ireland, convert it to
              `Europe/Dublin` before constructing this value.
            - Ireland uses GMT (UTC+0) during part of the year and Irish
            Standard
              Time (UTC+1) during part of the year. Use a timezone-aware library;
              do not hard-code a single UTC offset.
            - Omit the field or send `null` to send immediately. Empty and
              whitespace-only strings are invalid.
            - Past dates are accepted.

            - The API does not set a maximum scheduling horizon.
          examples:
            - 2030-07-08T14:30
            - '2030-07-08T14:30:45'
            - 2030-07-08 14:30
            - '2030-07-08 14:30:45'
        createAsDraft:
          type: boolean
          default: false
          description: >
            Set to `true` to save the campaign as a draft. A draft has no
            delivery

            summary until it is marked ready.
        shouldSaveList:
          type: boolean
          default: false
          description: >
            Optional saved-list flag. It is passed through as `shouldSaveList`
            and

            defaults to `false`. Saved-list behaviour is not part of the current

            public API contract, so leave this as `false` unless Phonovation has

            enabled the feature for your integration.
    CreateCampaignResponse:
      type: object
      title: Create Campaign Response
      description: Confirms that the campaign request was accepted and queued.
      required:
        - id
        - message
      properties:
        id:
          type: string
          format: uuid
          description: >-
            Public campaign UUID. Store it so you can request delivery totals
            later.
          examples:
            - ffd14db7-e526-4d69-b41e-ec5e38bc04dd
        message:
          type: string
          const: Campaign received to be processed
          description: >
            Human-readable confirmation for logs or troubleshooting. A
            successful

            `202` response returns `Campaign received to be processed`.
          examples:
            - Campaign received to be processed
    Recipient:
      type: object
      title: Campaign Recipient
      description: A mobile number to message, with an optional reference from your system.
      required:
        - msisdn
      properties:
        msisdn:
          type: string
          minLength: 1
          maxLength: 20
          description: >
            The recipient's mobile number (also called an MSISDN). Use digits
            with an

            optional leading `+`; do not include spaces, brackets, or hyphens.


            The API normalizes supported Irish and UK formats, but it does
            **not**

            perform full international E.164 validation.


            Accepted Irish examples include:


            - `0871234567`

            - `353871234567`

            - `+353871234567`

            - `00353871234567`


            Supported Irish numbers are stored as `353...`; supported UK numbers
            are

            stored as `44...`. Other digits-only values are accepted unchanged,
            but

            the API does not confirm their country or whether they can receive
            SMS.
          examples:
            - '353871234567'
            - '0871234567'
        ClientReference:
          type:
            - string
            - 'null'
          maxLength: 30
          description: >
            Your optional reference for this recipient — for example, a
            customer,

            order, or appointment ID.


            Phonovation stores the value unchanged and returns it in delivery
            webhooks

            as `ClientReference`. It does not need to be unique. If omitted,

            `ClientReference` is `null`.
          examples:
            - customer-123
  examples:
    SingleRecipientCampaign:
      summary: Send SMS to one recipient
      value:
        text: Your appointment is tomorrow at 10:30.
        from: CompanyName
        recipientInfo:
          - msisdn: '353871234567'
    SingleRecipientCampaignWithClientReference:
      summary: Send SMS to one recipient with a ClientReference
      value:
        text: Your appointment is tomorrow at 10:30.
        from: CompanyName
        recipientInfo:
          - msisdn: '353871234567'
            ClientReference: appointment-001
    MultipleRecipientCampaign:
      summary: Send SMS to multiple recipients
      value:
        text: Service update
        from: CompanyName
        campaignName: Service Update
        recipientInfo:
          - msisdn: '353871234567'
          - msisdn: '353851112222'
    MultipleRecipientCampaignWithClientReferences:
      summary: Send SMS to multiple recipients with ClientReferences
      value:
        text: Service update
        from: CompanyName
        campaignName: Service Update
        recipientInfo:
          - msisdn: '353871234567'
            ClientReference: customer-001
          - msisdn: '353851112222'
            ClientReference: customer-002
    ScheduledCampaign:
      summary: Schedule a campaign for 14:30 Irish local time
      value:
        text: Reminder about your scheduled appointment
        from: CompanyName
        campaignName: Appointment Reminders
        sendAt: 2030-07-08T14:30
        recipientInfo:
          - msisdn: '353871234567'
            ClientReference: appointment-001
          - msisdn: '353851112222'
            ClientReference: appointment-002
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >
        A UI-generated Phonovation Personal Access Token (PAT) is the
        recommended

        option for most integrations. OAuth/OIDC JWT access tokens are also
        accepted

        when an OAuth lifecycle is required.


        Send either token as:


        `Authorization: Bearer <token>`


        PAT values begin with `phv_pat_`. Generate a PAT once in the Phonovation
        UI,

        store it securely, and reuse it across requests. You do not need to
        generate

        or refresh a token for every SMS. Preserve the exact casing in

        `Bearer phv_pat_...`.

````