---
title: "Send SMS to Contacts"
description: "Send SMS to one or more recipients using your Bulkit sender ID and available account credit."
---

# Send SMS to Contacts

Use this endpoint to send SMS to one or more contact phone numbers from your application.

It is suitable for:

- transactional SMS
- operational alerts
- scheduled notifications
- sending one message to multiple saved contact numbers

## Endpoint title

Send SMS to Contacts

## What this endpoint does

Queues an SMS message for one or more recipient numbers using a sender ID assigned to your account.

## Endpoints

```http
POST /api/v2/messages/sms/bulk
```

## Authorization

Bulkit recommends authenticating requests using a single Bearer token in the `Authorization` HTTP header:

```http
Authorization: Bearer <your_api_key>
```

<Note>
**Legacy compatibility**: Passing `apikey` and `apisecret` directly in the JSON body, or via legacy `X-API-Key` and `X-API-Secret` headers, remains supported for existing integrations.
</Note>

## HTTP method and path

```http
POST /api/v2/messages/sms/bulk
```

## Authorization requirements

- **Recommended**: `Authorization: Bearer <your_api_key>` in the HTTP header.
- **Legacy**: `apikey` and `apisecret` provided in the JSON body or custom headers.

## Endpoint code block

```http
POST https://api.bulkitsms.com/api/v2/messages/sms/bulk
Authorization: Bearer bk_live_8n6JQv3K1h9Lp0Md
Content-Type: application/json
```

## Authorization header example

```http
Authorization: Bearer bk_live_8n6JQv3K1h9Lp0Md
```

## Error response

```json
{
  "status": "error",
  "message": "Invalid number"
}
```

## Suggested usage

Use this endpoint for both single-recipient and multi-recipient SMS sends when you want one consistent integration pattern.

## Request examples

<CodeGroup>

```bash curl
curl -X POST "https://api.bulkitsms.com/api/v2/messages/sms/bulk" \
  -H "Authorization: Bearer bk_live_8n6JQv3K1h9Lp0Md" \
  -H "Content-Type: application/json" \
  -d '{
    "sender": "BULK_IT",
    "mobiles": [
      "254700000001",
      "254733000002"
    ],
    "message": "Hello John, your order #BK-2041 has been dispatched.",
    "scheduled_at": "2026-03-10T09:15:00+03:00"
  }'
```

```python python.py
import requests

headers = {
    "Authorization": "Bearer bk_live_8n6JQv3K1h9Lp0Md",
    "Content-Type": "application/json",
}

payload = {
    "sender": "BULK_IT",
    "mobiles": [
        "254700000001",
        "254733000002"
    ],
    "message": "Hello John, your order #BK-2041 has been dispatched.",
    "scheduled_at": "2026-03-10T09:15:00+03:00"
}

response = requests.post(
    "https://api.bulkitsms.com/api/v2/messages/sms/bulk",
    headers=headers,
    json=payload,
    timeout=30,
)
response.raise_for_status()

print(response.json())
```

```go main.go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
)

type BulkSMSRequest struct {
	Sender      string   `json:"sender"`
	Mobiles     []string `json:"mobiles"`
	Message     string   `json:"message"`
	ScheduledAt string   `json:"scheduled_at,omitempty"`
}

func main() {
	payload := BulkSMSRequest{
		Sender:      "BULK_IT",
		Mobiles:     []string{"254700000001", "254733000002"},
		Message:     "Hello John, your order #BK-2041 has been dispatched.",
		ScheduledAt: "2026-03-10T09:15:00+03:00",
	}

	body, err := json.Marshal(payload)
	if err != nil {
		panic(err)
	}

	req, err := http.NewRequest(
		http.MethodPost,
		"https://api.bulkitsms.com/api/v2/messages/sms/bulk",
		bytes.NewReader(body),
	)
	if err != nil {
		panic(err)
	}

	req.Header.Set("Authorization", "Bearer bk_live_8n6JQv3K1h9Lp0Md")
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	fmt.Println("Status:", resp.StatusCode)

	var result map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", result)
}
```

```php php
<?php

$payload = [
    "sender" => "BULK_IT",
    "mobiles" => [
        "254700000001",
        "254733000002"
    ],
    "message" => "Hello John, your order #BK-2041 has been dispatched.",
    "scheduled_at" => "2026-03-10T09:15:00+03:00"
];

$ch = curl_init("https://api.bulkitsms.com/api/v2/messages/sms/bulk");

curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer bk_live_8n6JQv3K1h9Lp0Md",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode($payload, JSON_THROW_ON_ERROR),
]);

$response = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if ($response === false) {
    throw new Exception(curl_error($ch));
}

curl_close($ch);

echo $statusCode . PHP_EOL;
echo $response . PHP_EOL;
```

</CodeGroup>

## Parameters

| Parameter | Required | Type | Description | Validation |
| --- | --- | --- | --- | --- |
| `sender` | Yes | string | Sender ID name assigned to your account (e.g. `BULK_IT`) | Must exist, be active, and belong to your account |
| `mobiles` | Yes | array of strings | One or more recipient mobile numbers | Use normalized Kenyan numbers such as `254700000001` |
| `message` | Yes | string | SMS body to send to all recipients in the request | Cannot be blank |
| `scheduled_at` | No | string | Future send time | Use timezone-aware ISO 8601 such as `2026-03-10T09:15:00+03:00` |
| `sender_id` | Legacy | string / int | Legacy UUID or numeric Sender ID | Backward-compatible alternative to `sender` |
| `apikey` | Legacy | string | Legacy body authentication key | Optional when using `Authorization: Bearer` |
| `apisecret` | Legacy | string | Legacy secret paired with API key | Optional when using `Authorization: Bearer` |

## Success response example

```json
{
  "status": "success",
  "message": "Bulk SMS processed",
  "data": {
    "requested": 2,
    "queued": 2,
    "failed": []
  }
}
```

## Error response examples

### Invalid credentials

```json
{
  "status": "error",
  "message": "Invalid credentials"
}
```

### Insufficient balance

```json
{
  "status": "error",
  "message": "Insufficient balance"
}
```

### Invalid number

```json
{
  "status": "error",
  "message": "Invalid number"
}
```

### Invalid sender ID

```json
{
  "status": "error",
  "message": "Invalid sender ID"
}
```

### Invalid message

```json
{
  "status": "error",
  "message": "Invalid message"
}
```

### Restricted send time

```json
{
  "status": "error",
  "message": "Restricted send time"
}
```

### Partial bulk failure example

```json
{
  "status": "success",
  "message": "Bulk SMS processed",
  "data": {
    "requested": 3,
    "queued": 2,
    "failed": [
      {
        "mobile": "12345",
        "message": "Invalid number"
      }
    ]
  }
}
```

## Notes and best practices

- validate and normalize phone numbers before sending
- keep sender IDs mapped to the right environment and use case
- check balance before high-volume sends
- use `scheduled_at` with timezone offsets to avoid ambiguity
- if you use a promotional sender ID, avoid scheduling Safaricom traffic outside 8:00 AM to 6:00 PM Africa/Nairobi time

## Single-recipient alternative

If you are sending to one recipient only, Bulkit also provides:

```http
POST /api/v2/messages/sms
```

Use the bulk endpoint when you want one consistent integration for both single and multi-recipient sends.
