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

# PHP SDK SMS service

> Use the AvraAPI PHP SDK to send SMS or read the configured SMS balance.

Use `$avraapi->sms()` for the four released SMS operations. All return an
`ApiResponse`. Sending is a real external action: a successful response means
the configured QuickSend integration accepted the request, not that a handset
received it. Do not automatically retry an uncertain send.

<Note>
  Every SMS operation can use the shared one-request privacy control:
  `$avraapi->sms()->withPrivacyMode()->getBalance()`. It sends
  `X-Privacy-Mode: 1` only for that next request, then clears automatically.
  Privacy Mode keeps normal routing, billing, and usage tracking while
  suppressing request and response payload storage.
</Note>

<Warning>
  Send messages only to recipients you own or are permitted to contact. Keep
  any send workflow in your backend, record the returned `requestId`, and make
  retry decisions only after checking whether the provider accepted the first
  request.
</Warning>

## Send one SMS

`sendSingle(string $to, string $message): ApiResponse` sends one message to a
QuickSend-compatible Sri Lankan local `07XXXXXXXX` or E.164 `+947XXXXXXXX`
number. A Managed SMS integration supports this method.

**SDK function**

```php title="Copy the SDK call" theme={null}
$response = $avraapi->sms()->sendSingle(
    to: 'RECIPIENT_NUMBER',
    message: 'Text message',
);
```

| Argument | Use |
| - | - |
| `to` | One compatible recipient number. |
| `message` | Text message for that recipient. |

```php title="Send one SMS and capture acceptance" theme={null}
<?php

// AvraAPI SDK call.
$response = $avraapi->sms()->sendSingle(
    to: 'RECIPIENT_NUMBER',
    message: 'Text message',
);

// Your application code.
$messageUnits = $response->data['message_count'];
$providerId = $response->data['provider_response']['id'] ?? null;
$requestId = $response->requestId;
```

### Response

```json theme={null}
{
  "success": true,
  "request_id": "1af26040-c878-472f-88bd-6c5158905637",
  "data": {
    "send_method": "single",
    "message_count": 1,
    "credits_charged": 2000,
    "provider_response": {
      "status": "success",
      "id": "4726abaf7ab34f31378"
    }
  }
}
```

## Send one message to a bulk list

`sendBulkSame(array $recipients, string $message, bool $checkCost = false):
ApiResponse` sends the same text to 1–10,000 recipients. It requires a Manual
(BYOK) QuickSend integration. Set `checkCost` to `true` to request a campaign
cost estimate instead of sending that bulk campaign.

**SDK function**

```php title="Copy the SDK call" theme={null}
$response = $avraapi->sms()->sendBulkSame(
    recipients: ['FIRST_RECIPIENT_NUMBER', 'SECOND_RECIPIENT_NUMBER'],
    message: 'Text message',
    checkCost: true,
);
```

| Argument | Use |
| - | - |
| `recipients` | Array of one to 10,000 compatible numbers. |
| `message` | Shared text message. |
| `checkCost` | Optional; `true` estimates cost without dispatching. |

```php title="Check the cost before a bulk campaign" theme={null}
<?php

// AvraAPI SDK call. true requests an estimate; it does not dispatch this campaign.
$response = $avraapi->sms()->sendBulkSame(
    recipients: ['FIRST_RECIPIENT_NUMBER', 'SECOND_RECIPIENT_NUMBER'],
    message: 'Text message',
    checkCost: true,
);

// Your application code.
$campaign = $response->data['provider_response']['campaign_data'] ?? null;
$messageUnits = $response->data['message_count'];
```

### Response

```json theme={null}
{
  "success": true,
  "request_id": "d5ca2bbb-9cab-42ef-932a-62ef61470447",
  "data": {
    "send_method": "bulk_same",
    "message_count": 2,
    "credits_charged": 0,
    "provider_response": {
      "status": "success",
      "campaign_data": {
        "campaign_method": "Same Message To Bulk",
        "campaign_type": "Transactional",
        "sender_id": "APIX SENDER",
        "campaign_total_cost": "1.12 LKR (0.56×2)",
        "campaign_total_numbers": "2 Numbers",
        "sms_msg_data": [
          {
            "msg": "BULK TRANSACTION TEST",
            "unicode": "NO",
            "msg_size": "1 SMS",
            "per_sms_cost": "0.56 LKR",
            "msg_cost": "0.56 LKR (1×0.56)"
          }
        ]
      }
    }
  }
}
```

With `checkCost: false`, the same method submits the campaign and
`provider_response` instead contains the provider acceptance result. Manual
(BYOK) sends return `credits_charged: 0`; the connected provider can charge its
own account.

## Send different messages to a bulk list

`sendBulkDifferent(array $messages): ApiResponse` sends a different message to
each recipient through a Manual (BYOK) QuickSend integration. Supply 1–20
entries; each entry has exactly `to` and `msg` values.

**SDK function**

```php title="Copy the SDK call" theme={null}
$response = $avraapi->sms()->sendBulkDifferent([
    ['to' => 'FIRST_RECIPIENT_NUMBER', 'msg' => 'First text message'],
]);
```

| Argument | Use |
| - | - |
| `messages` | Array of one to 20 `{to, msg}` entries. |

```php title="Send recipient-specific SMS messages" theme={null}
<?php

// AvraAPI SDK call. This is a real send operation.
$response = $avraapi->sms()->sendBulkDifferent([
    ['to' => 'FIRST_RECIPIENT_NUMBER', 'msg' => 'First text message'],
    ['to' => 'SECOND_RECIPIENT_NUMBER', 'msg' => 'Second text message'],
]);

// Your application code.
$acceptedUnits = $response->data['message_count'];
$providerId = $response->data['provider_response']['id'] ?? null;
```

### Response

```json theme={null}
{
  "success": true,
  "request_id": "5bf45f1d-e0ee-4293-8a47-f033d1fb0c4a",
  "data": {
    "send_method": "bulk_different",
    "message_count": 2,
    "credits_charged": 0,
    "provider_response": {
      "status": "success",
      "id": "4726abafafabbb0a378"
    }
  }
}
```

`checkCost` is not an argument of `sendBulkDifferent()`. A cost estimate is
available only through `sendBulkSame(..., checkCost: true)`.

## Check the configured SMS balance

`getBalance(): ApiResponse` reads the balance for the active SMS integration.
It does not deduct AvraAPI credits.

**SDK function**

```php title="Copy the SDK call" theme={null}
$response = $avraapi->sms()->getBalance();
```

```php title="Read the SMS balance" theme={null}
<?php

// AvraAPI SDK call.
$response = $avraapi->sms()->getBalance();

// Your application code.
$source = $response->data['source'];
$balance = $response->data['balance_formatted'];
$providerBalance = $response->data['provider_response']['balance'] ?? null;
```

### Response — Manual (BYOK)

```json theme={null}
{
  "success": true,
  "request_id": "7a5b17fa-0716-45e1-b109-378322b8769f",
  "data": {
    "source": "quicksend_direct",
    "balance_formatted": "473.52",
    "provider_response": {"balance": "473.52"}
  }
}
```

### Response — Managed

```json theme={null}
{
  "success": true,
  "request_id": "3251caf2-3d8a-4232-a1fb-b4cfc4846888",
  "data": {
    "source": "apix_wallet",
    "balance_formatted": "285,417,005 credits"
  }
}
```

For a Managed integration, `balance_formatted` reports AvraAPI wallet credits:
**1 USD equals 1,000,000 API credits**. For a Manual integration it reports
the connected QuickSend account balance.

## SMS units and errors

`message_count` is SMS units, not API request count. Use up to **153 GSM-7**
characters or **67 Unicode (UCS-2)** characters per unit. Each recipient
message is limited to three units. The [SMS REST API Reference](/api-reference/sms/send)
contains the full method restrictions and error contract; use the typed SDK
exception pattern from [PHP Overview and setup](/sdk/php/overview-and-setup#handle-errors-safely)
for failures.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.