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

# SMS Programs

> Bulk SMS campaigns with audience targeting and scheduling

Manage bulk SMS campaigns that send messages to audience contacts.

**Related APIs:**

* [Audience API](/core-concepts/audiences) - Manage audiences and contacts
* [Contact API](/core-concepts/contacts) - Contact management
* [Credit API](/features/credits) - Credit management and billing

***

## Types

<Accordion title="Type Definitions">
  ```typescript theme={null}
  // ============================================
  // BRANDED TYPES
  // ============================================

  type SmsProgramId = string & { readonly __brand: 'SmsProgramId' };

  // ============================================
  // STATUS
  // ============================================

  type SmsProgramStatus =
    | 'draft'      // Not yet launched, can be edited
    | 'pending'    // Job queued, waiting to start
    | 'sending'    // Currently processing
    | 'completed'  // All messages sent
    | 'cancelled'  // Cancelled by user
    | 'failed';    // Processing failed

  // ============================================
  // SMS PROGRAM ENTITY
  // ============================================

  interface SenderIdDetail {
    id: string;        // Sender ID UUID
    senderId: string;  // The actual sender text (e.g. "GoMobile")
    country: string;   // ISO country code (e.g. "MA")
  }

  interface SmsProgram {
    id: SmsProgramId;
    organizationId: string;
    name: string;
    description: string | null;
    status: SmsProgramStatus;

    // Configuration
    audienceId: string;
    senderId: string;                         // Sender ID UUID (from GET /sender-ids/available)
    resolvedSenderId: SenderIdDetail | null;  // Resolved sender details (null if deleted)
    messageTemplate: string;                  // Template with {{ $contact.* }} placeholders

    // BullMQ job tracking
    jobId: string | null;

    // Progress tracking
    totalContacts: number;

    // Execution timestamps
    startedAt: string | null;
    completedAt: string | null;

    // Error tracking
    errorMessage: string | null;

    // Audit columns
    createdBy: string | null;
    createdAt: string;
    updatedAt: string;
  }

  interface SmsProgramWithProgress extends SmsProgram {
    progress: {
      sent: number;
      failed: number;
      pending: number;
    };
  }

  // ============================================
  // TEMPLATE SYNTAX
  // ============================================

  /**
   * Message templates support {{ $contact.* }} placeholders:
   *
   * Contact fields:
   * - {{ $contact.phone }}
   * - {{ $contact.firstName }}
   * - {{ $contact.lastName }}
   * - {{ $contact.fullName }}
   * - {{ $contact.email }}
   * - {{ $contact.address }}
   * - {{ $contact.city }}
   * - {{ $contact.state }}
   * - {{ $contact.zip }}
   * - {{ $contact.occupation }}
   * - {{ $contact.gender }}
   * - {{ $contact.preferredChannel }}
   *
   * Custom attributes:
   * - {{ $contact.customAttributes.fieldName }}
   *
   * Example:
   * "Hello {{ $contact.firstName }}, your balance is {{ $contact.customAttributes.balance }} DH"
   */
  ```
</Accordion>

***

## API Endpoints

<Info>
  **Base path: `/sms-programs`**
</Info>

### Request/Response Types

```typescript theme={null}
// ============================================
// QUERY DTOs
// ============================================

interface SmsProgramQueryDto {
  page?: number;        // default: 1
  limit?: number;       // default: 20, max: 100
  search?: string;      // Search in name/description
  sortBy?: string;      // Field to sort by (e.g., 'createdAt', 'name')
  sortOrder?: 'asc' | 'desc';  // default: 'desc'
  status?: SmsProgramStatus;   // Filter by status
}

// ============================================
// CREATE / UPDATE DTOs
// ============================================

interface CreateSmsProgramInput {
  name: string;           // max: 255 chars
  description?: string;
  audienceId: string;     // UUID
  senderId: string;       // UUID (from GET /sender-ids/available)
  messageTemplate: string;
}

interface UpdateSmsProgramInput {
  name?: string;
  description?: string;
  audienceId?: string;
  senderId?: string;      // UUID (from GET /sender-ids/available)
  messageTemplate?: string;
}

// ============================================
// RESPONSE DTOs
// ============================================

interface SmsProgramListResponse {
  data: SmsProgram[];
  meta: {
    page: number;
    limit: number;
    total: number;
    totalPages: number;
    hasNextPage: boolean;
    hasPreviousPage: boolean;
  };
}

interface LaunchSmsProgramResponse {
  id: SmsProgramId;
  status: 'pending';
  totalContacts: number;
  jobId: string;
}
```

***

### Create a new SMS program

```bash theme={null}
curl -X POST https://api.gomobile.ma/api/sms-programs \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '
{
  "name": "Winter Promo Campaign",
  "description": "Promotional SMS for winter sale",
  "audienceId": "aud_123",
  "senderId": "123e4567-e89b-12d3-a456-426614174000",
  "messageTemplate": "Hello {{ $contact.firstName }}, enjoy 20% off with code WINTER20!"
}
'
```

Response:

```json theme={null}
{
  "id": "sms_abc123",
  "organizationId": "org_xyz",
  "name": "Winter Promo Campaign",
  "description": "Promotional SMS for winter sale",
  "status": "draft",
  "audienceId": "aud_123",
  "senderId": "123e4567-e89b-12d3-a456-426614174000",
  "resolvedSenderId": { "id": "123e4567-e89b-12d3-a456-426614174000", "senderId": "GoMobile", "country": "MA" },
  "messageTemplate": "Hello {{ $contact.firstName }}, enjoy 20% off with code WINTER20!",
  "jobId": null,
  "totalContacts": 0,
  "startedAt": null,
  "completedAt": null,
  "errorMessage": null,
  "createdBy": "user_123",
  "createdAt": "2025-01-09T10:00:00.000Z",
  "updatedAt": "2025-01-09T10:00:00.000Z"
}
```

**Error Responses:**

| Code | Error                        | Description                                     |
| ---- | ---------------------------- | ----------------------------------------------- |
| 404  | `SenderIdNotFoundError`      | Sender ID not found                             |
| 400  | `SenderIdNotActiveError`     | Sender ID is not active                         |
| 400  | `SenderIdNotAccessibleError` | Sender ID is not available to this organization |

***

### List all SMS programs

```bash theme={null}
curl -X GET https://api.gomobile.ma/api/sms-programs?page=1&limit=10&status=draft \
  -H "x-api-key: YOUR_API_KEY"
```

Response:

```json theme={null}
{
  "data": [
    {
      "id": "sms_abc123",
      "name": "Winter Promo Campaign",
      "status": "draft",
      ...
    }
  ],
  "meta": {
    "page": 1,
    "limit": 10,
    "total": 25,
    "totalPages": 3,
    "hasNextPage": true,
    "hasPreviousPage": false
  }
}
```

***

### Get SMS program by ID with progress information

```bash theme={null}
curl -X GET https://api.gomobile.ma/api/sms-programs/sms_abc123 \
  -H "x-api-key: YOUR_API_KEY"
```

Response:

```json theme={null}
{
  "id": "sms_abc123",
  "name": "Winter Promo Campaign",
  "status": "sending",
  "totalContacts": 1500,
  "progress": {
    "sent": 850,
    "failed": 12,
    "pending": 638
  },
  ...
}
```

**Error Responses:**

| Code | Description           |
| ---- | --------------------- |
| 404  | SMS Program not found |

***

### Update an SMS program

**Error Responses:**

| Code | Description                           |                                                 |
| ---- | ------------------------------------- | ----------------------------------------------- |
| 400  | Cannot update - status is not `draft` |                                                 |
| 404  | `SenderIdNotFoundError`               | Sender ID not found                             |
| 400  | `SenderIdNotActiveError`              | Sender ID is not active                         |
| 400  | `SenderIdNotAccessibleError`          | Sender ID is not available to this organization |
| 404  | SMS Program not found                 |                                                 |

***

### Delete an SMS program

**Error Responses:**

| Code | Description                           |
| ---- | ------------------------------------- |
| 400  | Cannot delete - status is not `draft` |
| 404  | SMS Program not found                 |

***

### Launch an SMS program

**Notes:**

* Only programs in `draft` status can be launched
* **Requires sufficient credits** - estimated cost = contacts × 1.887
* If insufficient credits, returns `InsufficientCreditsError`
* On success, status transitions to `pending`, then `sending` when job starts
* Credits are deducted at campaign completion

```bash theme={null}
curl -X POST https://api.gomobile.ma/api/sms-programs/sms_abc123/launch \
  -H "x-api-key: YOUR_API_KEY"
```

Response:

```json theme={null}
{
  "id": "sms_abc123",
  "status": "pending",
  "totalContacts": 1500,
  "jobId": "job_xyz789"
}
```

**Error Responses:**

| Code | Error                          | Description                                  |
| ---- | ------------------------------ | -------------------------------------------- |
| 400  | `SmsProgramInvalidStatusError` | Status is not `draft`                        |
| 400  | `SmsProgramNoContactsError`    | Audience has no contacts with phone numbers  |
| 400  | `InsufficientCreditsError`     | Not enough credits to send all messages      |
| 400  | `SenderIdDeletedError`         | Sender ID was deleted since program creation |
| 404  | `SmsProgramNotFoundError`      | SMS Program not found                        |

***

### Cancel a running SMS program

**Notes:**

* Only programs in `pending` or `sending` status can be cancelled
* Best-effort cancellation - some messages may still be sent
* Already sent messages are not affected
* Credits for already sent messages are still charged

**Error Responses:**

| Code | Description                                          |
| ---- | ---------------------------------------------------- |
| 400  | Cannot cancel - status is not `pending` or `sending` |
| 404  | SMS Program not found                                |

***

## Billing

SMS programs use the same cost as SMS nodes in call flows:

**Pre-launch credit check:**

* Before launching, the system calculates: `estimatedCost = contactCount × 1.887`
* If `balance < estimatedCost`, launch is rejected with `InsufficientCreditsError`
* Unlike calls (which can go negative due to unpredictable duration), SMS programs require credits upfront

**Billing at completion:**

* Credits are deducted at campaign completion based on actual messages sent
* Transaction type in credit history: `sms_charge`
* Failed messages are not charged

***

## Status Lifecycle

```
draft ──► pending ──► sending ──► completed
  │          │           │
  │          │           └──► failed
  │          │
  │          └──► cancelled
  │
  └──► (deleted)
```
