> ## 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.

# Frequently asked questions

> Answers to common questions about integrating with the Phonovation API.

Find quick answers to common integration questions. For complete request and response schemas, use the API Reference.

<div className="phono-faq">
  ## Authentication

  <AccordionGroup>
    <Accordion title="How do I authenticate with the API?">
      Send either a Phonovation Personal Access Token (PAT) or an OAuth access token in the `Authorization` header:

      ```http theme={"dark"}
      Authorization: Bearer <token>
      ```

      See [Authentication](/phonovation-api/authentication) for setup guidance.
    </Accordion>

    <Accordion title="Are Personal Access Tokens supported?">
      Yes. PATs beginning with `phv_pat_` can authenticate campaign requests. Generate the token once, store it securely, and reuse it until it expires or is revoked.
    </Accordion>

    <Accordion title="What causes a 401 Unauthorized response?">
      The API returns `401` when authentication is missing or unsuccessful. The token may be missing, invalid, expired, or revoked.

      The response can have an empty body and include:

      ```http theme={"dark"}
      WWW-Authenticate: Bearer
      ```
    </Accordion>

    <Accordion title="What causes a 403 Forbidden response?">
      The API returns `403` when the token is valid but does not resolve to a recognized Phonovation client administrator.

      ```json theme={"dark"}
      {
        "title": "Forbidden",
        "status": 403,
        "detail": "Authenticated user is not a recognized client administrator"
      }
      ```
    </Accordion>

    <Accordion title="Can I use a PAT to create or revoke other PATs?">
      No. PAT-management operations reject PAT authentication. Use an OAuth-authenticated application session to manage PATs.
    </Accordion>

    <Accordion title="Which authentication method should I use?">
      Use a PAT for most server-to-server integrations. Use OAuth when your integration specifically needs an access-token and refresh-token lifecycle.
    </Accordion>
  </AccordionGroup>

  ## Creating campaigns

  <AccordionGroup>
    <Accordion title="What endpoint creates a campaign?">
      Send an authenticated JSON request to:

      ```http theme={"dark"}
      POST https://api.phonovation.com/v1/campaign
      Content-Type: application/json
      Authorization: Bearer <token>
      ```
    </Accordion>

    <Accordion title="What is the minimum request body?">
      ```json theme={"dark"}
      {
        "text": "Your message",
        "from": "Company",
        "recipientInfo": [
          {
            "msisdn": "353871234567"
          }
        ]
      }
      ```
    </Accordion>

    <Accordion title="Which request properties are supported?">
      A campaign can contain:

      * `text`, `from`, and `recipientInfo`
      * an optional `campaignName`
      * an optional Irish-local `sendAt` value
      * optional `createAsDraft` and `shouldSaveList` flags
      * an optional `ClientReference` for each recipient

      Review the [create campaign reference](/phonovation-api/api-reference/campaigns/create-campaign) for the complete schema.
    </Accordion>

    <Accordion title="Which properties are required?">
      `text`, `from`, and `recipientInfo` are required. Every recipient must have a valid `msisdn`, and the request must contain at least one recipient.
    </Accordion>

    <Accordion title="What happens if I omit campaignName?">
      It defaults to `API Broadcast`. If you explicitly supply `null`, an empty string, or whitespace, validation fails.
    </Accordion>

    <Accordion title="How long can the SMS text be?">
      `text` can contain up to 2,000 characters. It cannot be `null`, empty, or whitespace-only. Message encoding can affect the number of SMS parts sent and billed; use the [SMS Message Lab](/phonovation-api/tools/message-lab) to inspect it.
    </Accordion>

    <Accordion title="What are the Sender ID length limits?">
      Numeric Sender IDs can contain up to 20 digits. Other Sender IDs can contain up to 11 characters. Irish alphanumeric Sender IDs also follow ComReg registration rules. See [Sender IDs](/phonovation-api/sender-ids).
    </Accordion>

    <Accordion title="Does the Sender ID need to be registered?">
      Yes, when using an alphanumeric Sender ID to deliver SMS to Irish mobile numbers. An Irish recipient whose Sender ID is not permitted can be skipped. Register the Sender ID with ComReg, select Phonovation as its OPA, and ask Phonovation Support to assign it to your account.
    </Accordion>

    <Accordion title="What format should I use for recipient numbers?">
      Use the full international number as digits only, without a leading `+`, spaces, brackets, or hyphens. A submitted `msisdn` can contain up to 20 characters and must pass the API's parsing and normalization rules.
    </Accordion>

    <Accordion title="What is ClientReference?">
      `ClientReference` is an optional reference associated with one recipient. It can contain up to 30 characters and is returned unchanged in the delivery webhook, allowing you to match the receipt with your own customer, order, or appointment.

      It does not need to be unique. See [Client Reference](/phonovation-api/client-reference).
    </Accordion>

    <Accordion title="What format does sendAt accept?">
      `sendAt` is always interpreted as Irish local time in `Europe/Dublin`. Prefer `yyyy-MM-ddTHH:mm`, for example:

      ```json theme={"dark"}
      {
        "sendAt": "2030-07-08T14:30"
      }
      ```

      A space instead of `T` and optional seconds are also accepted. Supplied seconds are ignored. Do not include `Z` or a numeric timezone offset. See [Sending SMS](/phonovation-api/sending-sms) for international conversion examples.
    </Accordion>

    <Accordion title="What happens if sendAt is omitted?">
      Omit `sendAt` or send `null` to send immediately. Empty and whitespace-only strings are invalid.
    </Accordion>

    <Accordion title="Is there a maximum number of recipients?">
      The application does not publish a maximum recipient count. Hosting infrastructure may still impose request-size limits.
    </Accordion>

    <Accordion title="What happens when a recipient is invalid?">
      Invalid recipients are skipped during parsing. Campaign creation can continue if at least one valid recipient remains. The request fails with `400 Bad Request` if no valid recipient remains.
    </Accordion>

    <Accordion title="What happens to duplicate recipients?">
      Duplicate detection runs after phone-number normalization. The first occurrence and its `ClientReference` are kept. If no valid unique recipient remains, campaign creation fails with `400 Bad Request`.
    </Accordion>

    <Accordion title="What happens to opted-out or blocked recipients?">
      They are removed before the campaign is created. If no permitted recipient remains, the API returns `400 Bad Request`.
    </Accordion>

    <Accordion title="What happens if a prepaid account has insufficient credit?">
      The API returns `400 Bad Request` with a validation response:

      ```json theme={"dark"}
      {
        "title": "Validation Error",
        "status": 400,
        "detail": "Not enough credit"
      }
      ```
    </Accordion>
  </AccordionGroup>

  ## Campaign responses and status

  <AccordionGroup>
    <Accordion title="What does a successful create response look like?">
      A campaign accepted for background processing returns `202 Accepted`:

      ```json theme={"dark"}
      {
        "id": "ffd14db7-e526-4d69-b41e-ec5e38bc04dd",
        "message": "Campaign received to be processed"
      }
      ```

      A `202` confirms that the command was queued. It does not confirm that processing or handset delivery succeeded.
    </Accordion>

    <Accordion title="What does a validation response look like?">
      ```json theme={"dark"}
      {
        "title": "Validation Error",
        "status": 400,
        "detail": "<validation message>"
      }
      ```

      The `detail` value depends on the validation or campaign-creation failure.
    </Accordion>

    <Accordion title="Which create-campaign response codes are documented?">
      The public contract documents `202 Accepted`, `400 Bad Request`, `401 Unauthorized`, and `403 Forbidden`.
    </Accordion>

    <Accordion title="How do I retrieve a campaign summary?">
      Use the UUID returned by the create response:

      ```http theme={"dark"}
      GET https://api.phonovation.com/v1/campaign/{id}
      Authorization: Bearer <token>
      ```
    </Accordion>

    <Accordion title="What does the campaign summary contain?">
      ```json theme={"dark"}
      {
        "totalSent": 1,
        "delivered": 0,
        "undelivered": 0,
        "pending": 1
      }
      ```

      All four properties are integers.
    </Accordion>

    <Accordion title="Can I retrieve another customer's campaign?">
      No. The lookup uses both the supplied campaign UUID and the authenticated account. A campaign belonging to another account is not returned.
    </Accordion>

    <Accordion title="What happens when a campaign summary cannot be found?">
      The API returns `404 Not Found`. The campaign may be unknown, belong to another account, still be processing, or not yet have a summary.
    </Accordion>
  </AccordionGroup>

  ## Delivery webhooks

  <AccordionGroup>
    <Accordion title="When is a webhook sent?">
      Phonovation sends a delivery webhook when a delivery receipt is created and your account has an enabled webhook configuration.
    </Accordion>

    <Accordion title="What HTTP request is sent?">
      Phonovation sends JSON with an HTTP `POST` to the webhook URL configured in your developer settings.
    </Accordion>

    <Accordion title="What does the webhook payload look like?">
      ```json theme={"dark"}
      {
        "To": "353871234567",
        "From": "Company",
        "Status": "DELIVRD",
        "ClientReference": "customer-reference"
      }
      ```

      The documented property names use `To`, `From`, `Status`, and `ClientReference`.
    </Accordion>

    <Accordion title="What happens when no ClientReference was supplied?">
      The webhook still contains `ClientReference`, with a value of `null`.
    </Accordion>

    <Accordion title="Does ClientReference round-trip through the webhook?">
      Yes. The value submitted for a recipient is stored with that campaign recipient and returned in the webhook as `ClientReference`.
    </Accordion>

    <Accordion title="Which delivery status values can appear?">
      Confirmed examples include `DELIVRD`, `DELIVERED`, `DELIV`, `UNDELIV`, `REJECTD`, `EXPIRED`, `ABANDONED`, and `FAILED`.

      This is not a closed list. Treat `Status` as an open-ended string because raw provider status text can be returned when a normalized value cannot be extracted.
    </Accordion>

    <Accordion title="Should I only check for DELIVERED?">
      No. Confirmed delivered forms include `DELIVRD`, `DELIVERED`, and `DELIV`. The current implementation treats statuses beginning with `DELIV` as delivered.
    </Accordion>

    <Accordion title="Can Status contain a raw provider error?">
      Yes. Examples include `NACK/` and `NACK/0x000000ff/Unknown Error`. Do not restrict `Status` to a fixed enum.
    </Accordion>
  </AccordionGroup>

  ## Webhook signatures and retries

  <AccordionGroup>
    <Accordion title="How is a webhook authenticated?">
      When a webhook secret is configured, the request includes:

      ```http theme={"dark"}
      X-Signature: sha256=<lowercase hexadecimal signature>
      ```
    </Accordion>

    <Accordion title="How is X-Signature calculated?">
      Phonovation serializes the JSON payload, encodes that exact body as UTF-8, calculates an HMAC-SHA256 digest using the webhook secret, converts the result to lowercase hexadecimal, and prefixes it with `sha256=`.
    </Accordion>

    <Accordion title="Which bytes should I verify?">
      Verify the signature against the exact raw HTTP request-body bytes you received. Do not parse and rebuild the JSON before calculating the signature because whitespace or property-order changes produce a different HMAC.
    </Accordion>

    <Accordion title="Is X-Signature always present?">
      The header is omitted when no webhook secret is configured. Configure both a webhook URL and signing secret before enabling delivery.
    </Accordion>

    <Accordion title="What response should my webhook return?">
      Return any successful `2xx` status after you have safely stored or queued the event. The full `200`–`299` range is accepted.
    </Accordion>

    <Accordion title="Are failed webhook requests retried?">
      Yes. Phonovation retries network failures, `404 Not Found`, `408 Request Timeout`, and `5xx` responses. It configures three retries after approximately 2, 4, and 8 seconds.

      A circuit breaker opens for 30 seconds after two transient failures. While open, it can prevent configured retries from becoming actual HTTP requests.
    </Accordion>

    <Accordion title="Are other 4xx responses retried?">
      No. Ordinary `4xx` responses such as `400 Bad Request`, `401 Unauthorized`, and `403 Forbidden` are not retried.
    </Accordion>

    <Accordion title="Can my webhook receive duplicate deliveries?">
      Yes. A request may be processed even when Phonovation cannot receive the response, causing a retry. Make the handler idempotent so processing a duplicate does not repeat a business action or corrupt status.
    </Accordion>

    <Accordion title="Are webhook deliveries ordered?">
      No ordering guarantee is published. Do not depend on delivery receipts arriving in a particular order.
    </Accordion>
  </AccordionGroup>
</div>

Need another answer? Email [support@phonovation.com](mailto:support@phonovation.com).
