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

# Sending SMS

> Send SMS campaigns to one or more recipients using the Phonovation SMS API.

## Send a campaign

Use `POST /api/v2/Campaign` to send a message to one or more recipients.

```mermaid title="Campaign processing flow" theme={"dark"}
flowchart LR
  Request["Campaign request"] --> Validate["Validate sender and recipients"]
  Validate --> Queue["Queue valid recipients"]
  Validate --> Errors["Return invalid recipients in errors"]
  Queue --> Webhook["Webhook: processing result"]
  Queue --> DLR["DLR: network delivery result"]
```

<CodeGroup>
  ```bash title="cURL" icon="terminal" highlight={2,6-8} wrap theme={"dark"}
  curl -X POST https://api.interactsms.com/api/v2/Campaign \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "text": "Hello from Phonovation!",
      "from": "Phonovation",
      "recipientInfo": [
        { "msisdn": "353861234567" }
      ]
    }'
  ```

  ```python title="Python" icon="python" lines focus={4-15} theme={"dark"}
  import requests

  res = requests.post(
      "https://api.interactsms.com/api/v2/Campaign",
      headers={"Authorization": "Bearer YOUR_ACCESS_TOKEN"},
      json={
          "text": "Hello from Phonovation!",
          "from": "Phonovation",
          "recipientInfo": [
              {"msisdn": "353861234567"}
          ]
      }
  )

  print(res.json())
  ```

  ```csharp title="C#" icon="code" lines focus={8-19} theme={"dark"}
  using System.Net.Http.Headers;
  using System.Text;
  using System.Text.Json;

  using var client = new HttpClient();
  client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "YOUR_ACCESS_TOKEN");

  var campaign = new
  {
      text = "Hello from Phonovation!",
      from = "Phonovation",
      recipientInfo = new[] { new { msisdn = "353861234567" } }
  };

  var res = await client.PostAsync(
      "https://api.interactsms.com/api/v2/Campaign",
      new StringContent(JsonSerializer.Serialize(campaign), Encoding.UTF8, "application/json")
  );

  Console.WriteLine(await res.Content.ReadAsStringAsync());
  ```

  ```java title="Java" icon="java" lines focus={8-24} theme={"dark"}
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;

  String payload = """
  {
    "text": "Hello from Phonovation!",
    "from": "Phonovation",
    "recipientInfo": [
      { "msisdn": "353861234567" }
    ]
  }
  """;

  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://api.interactsms.com/api/v2/Campaign"))
      .header("Authorization", "Bearer YOUR_ACCESS_TOKEN")
      .header("Content-Type", "application/json")
      .POST(HttpRequest.BodyPublishers.ofString(payload))
      .build();

  HttpResponse<String> res = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
  System.out.println(res.body());
  ```

  ```php title="PHP" icon="php" lines focus={3-14} theme={"dark"}
  $client = new GuzzleHttp\Client();

  $res = $client->post('https://api.interactsms.com/api/v2/Campaign', [
      'headers' => ['Authorization' => 'Bearer YOUR_ACCESS_TOKEN'],
      'json' => [
          'text' => 'Hello from Phonovation!',
          'from' => 'Phonovation',
          'recipientInfo' => [
              ['msisdn' => '353861234567'],
          ],
      ],
  ]);

  echo $res->getBody();
  ```

  ```js title="JavaScript" icon="js" lines focus={1-14} theme={"dark"}
  const res = await fetch('https://api.interactsms.com/api/v2/Campaign', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer YOUR_ACCESS_TOKEN',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      text: 'Hello from Phonovation!',
      from: 'Phonovation',
      recipientInfo: [{ msisdn: '353861234567' }]
    })
  });

  console.log(await res.json());
  ```
</CodeGroup>

**Response:**

```json title="Campaign response" icon="code" highlight={2,4} wrap theme={"dark"}
{
  "success": true,
  "message": "Campaign scheduled",
  "errors": []
}
```

## Multiple recipients

```json title="Multiple recipients payload" icon="code" highlight={5-6} wrap theme={"dark"}
{
  "text": "Your order is on the way!",
  "from": "Phonovation",
  "campaignName": "Order Notifications",
  "recipientInfo": [
    { "msisdn": "353861234567", "notifyId": "order-001" },
    { "msisdn": "353871234567", "notifyId": "order-002" }
  ]
}
```

The `notifyId` field is echoed back in webhooks and DLRs, letting you match every callback to the right record in your system. See [notifyId](/interactsms-api/guides/notify-id) for use cases and full flow examples.

## Partial delivery

If a campaign contains a mix of valid and invalid numbers, **the valid numbers will still be sent to** — the request is not rejected as a whole. Invalid numbers are skipped and reported in the `errors` array of the response. Always check the response payload to identify any numbers that failed validation.

## Recipient limit

A single campaign request supports up to approximately **400,000 recipients**. For very large sends, split your audience into batches below this limit.

## Schedule for later

Add `sendAt` using the date and clock time when the campaign should be sent in Ireland:

<Warning>
  `sendAt` is an Irish local wall-clock time. The API persists the date and clock time as submitted and does not convert the value from UTC or from the caller's timezone. Convert the intended send time to `Europe/Dublin` before constructing this value.
</Warning>

```json title="Scheduled campaign payload" icon="calendar" highlight={7} wrap theme={"dark"}
{
  "text": "Don't miss our sale tomorrow!",
  "from": "Phonovation",
  "recipientInfo": [
    { "msisdn": "353861234567" }
  ],
  "sendAt": "2030-06-01T09:00"
}
```

Prefer the format `yyyy-MM-ddTHH:mm` without `Z` or a numeric UTC offset. For example, `2030-06-01T09:00` schedules the campaign for 09:00 in Ireland. A timezone suffix does not cause the API to convert the submitted clock time.

Ireland changes between GMT (UTC+0) and Irish Standard Time (UTC+1). Use a timezone-aware library with the IANA timezone `Europe/Dublin` instead of hard-coding an offset.

## Phone number format

| Format                  | Accepted                    |
| ----------------------- | --------------------------- |
| Irish with prefix       | `353871234567` ✓            |
| Irish with leading zero | `0871234567` ✓              |
| UK                      | `447911123456` ✓            |
| Other international     | Must include country code ✓ |

## Message length & credits

SMS messages are billed per **message part**. Understanding how parts work helps avoid unexpected credit usage.

### Standard GSM characters (recommended)

| Length        | Parts   |
| ------------- | ------- |
| 1–160 chars   | 1 part  |
| 161–306 chars | 2 parts |
| 307–459 chars | 3 parts |
| 460–612 chars | 4 parts |

Messages longer than 4 parts are not supported.

<Info>
  Long messages are delivered as a single seamless message on the recipient's device — they will not see separate parts.
</Info>

### Unicode characters

The API supports Unicode, which includes characters outside the standard GSM alphabet — accented characters (é, ü, ñ), non-Latin scripts, and emojis.

<Warning>
  **Unicode reduces the characters per part.** A standard SMS holds 160 GSM characters, but only **70 Unicode characters** per part. A short message with a single emoji can consume 2–4 credits.

  Additionally, some Unicode characters — particularly emojis — **may not display correctly** on all handsets. For reliable delivery, stick to standard GSM characters where possible.
</Warning>

## Sending hours

There are no system-enforced sending hour restrictions. However, you are responsible for adhering to Irish marketing regulations — see [Compliance](/interactsms-api/guides/compliance) for details.

## Limits & billing

There are no rate limits on API calls themselves. Throughput is governed by:

* **Payload size** — very large batches may take longer to process
* **Account credits** — messages will not be sent if your account has insufficient credit
* **Billing tier** — contact [support@phonovation.com](mailto:support@phonovation.com) for details on your account limits
