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

# SMS Gateways API — Configure Providers and Send Messages

> Manage SMS gateway configurations and send messages via REST API. LaraCopilot supports multiple SMS gateway providers with DLR callback support.

LaraCopilot's SMS gateway API lets you configure outbound messaging providers, send SMS messages, and inspect delivery history — all in a single resource. Each gateway holds its own connection credentials and sender identity, and every message sent through the API is recorded as an `SmsMessage` record that tracks status from `queued` through to `delivered`.

<Warning>
  All SMS gateway endpoints require an active admin session. Requests without a valid session cookie return `401 Unauthorized`.
</Warning>

***

## List SMS gateways

Retrieve all configured SMS gateways. Pass `search` to filter by name, host, or provider type. Each result includes a `messages_count` field with the number of messages sent through that gateway.

```http theme={null}
GET /api/sms-gateways
```

**Query parameters**

<ParamField query="search" type="string">
  Filter gateways by `name`, `server_host`, or `provider_type`. Matches partial strings.
</ParamField>

**Response**

<ResponseField name="message" type="string">
  Human-readable status. Always `"SMS gateways fetched successfully."` on success.
</ResponseField>

<ResponseField name="data" type="object[]">
  Array of SMS gateway objects.

  <Expandable title="Gateway object properties">
    <ResponseField name="id" type="integer">
      Unique gateway identifier.
    </ResponseField>

    <ResponseField name="name" type="string">
      Display name for this gateway.
    </ResponseField>

    <ResponseField name="provider_type" type="string">
      Gateway provider identifier (e.g. `"jasmin"`, `"smpp"`).
    </ResponseField>

    <ResponseField name="server_host" type="string">
      Hostname or IP address of the gateway server.
    </ResponseField>

    <ResponseField name="server_port" type="integer">
      TCP port the gateway listens on.
    </ResponseField>

    <ResponseField name="api_path" type="string">
      Path appended to the host and port to form the send URL.
    </ResponseField>

    <ResponseField name="username" type="string">
      Authentication username for the gateway.
    </ResponseField>

    <ResponseField name="default_sender_id" type="string">
      Default originating address shown to recipients.
    </ResponseField>

    <ResponseField name="callback_token" type="string">
      Token used to validate inbound DLR callbacks from the gateway.
    </ResponseField>

    <ResponseField name="is_active" type="boolean">
      Whether this gateway is enabled for sending.
    </ResponseField>

    <ResponseField name="use_ssl" type="boolean">
      Whether to connect to the gateway over HTTPS.
    </ResponseField>

    <ResponseField name="notes" type="string">
      Free-text notes for internal reference.
    </ResponseField>

    <ResponseField name="meta" type="object">
      Arbitrary key-value metadata stored alongside the gateway.
    </ResponseField>

    <ResponseField name="messages_count" type="integer">
      Total number of messages sent through this gateway.
    </ResponseField>

    <ResponseField name="created_at" type="string">
      ISO 8601 timestamp when the gateway was created.
    </ResponseField>

    <ResponseField name="updated_at" type="string">
      ISO 8601 timestamp of the last update.
    </ResponseField>
  </Expandable>
</ResponseField>

```bash title="Example request" theme={null}
curl https://your-instance.laracopilot.com/api/sms-gateways \
  -b cookies.txt
```

```bash title="Filter by name" theme={null}
curl "https://your-instance.laracopilot.com/api/sms-gateways?search=jasmin" \
  -b cookies.txt
```

```json title="200 response" theme={null}
{
  "message": "SMS gateways fetched successfully.",
  "data": [
    {
      "id": 1,
      "name": "Jasmin Primary",
      "provider_type": "jasmin",
      "server_host": "sms.example.com",
      "server_port": 8080,
      "api_path": "send",
      "username": "admin",
      "default_sender_id": "LaraCopilot",
      "callback_token": "tok_abc123",
      "is_active": true,
      "use_ssl": false,
      "notes": null,
      "meta": null,
      "messages_count": 142,
      "created_at": "2024-01-15T10:00:00.000000Z",
      "updated_at": "2024-03-01T14:22:10.000000Z"
    }
  ]
}
```

***

## Create a gateway

Register a new SMS gateway. The `password` field is stored and used for Basic Auth when dispatching messages.

```http theme={null}
POST /api/sms-gateways
```

**Request body**

<ParamField body="name" type="string" required>
  Display name for this gateway. Maximum 255 characters.
</ParamField>

<ParamField body="provider_type" type="string" required>
  Gateway provider identifier. Maximum 100 characters (e.g. `"jasmin"`, `"smpp"`).
</ParamField>

<ParamField body="server_host" type="string" required>
  Hostname or IP address of the gateway server. Maximum 255 characters.
</ParamField>

<ParamField body="server_port" type="integer" required>
  TCP port the gateway listens on. Minimum value: `1`.
</ParamField>

<ParamField body="api_path" type="string">
  Path segment appended after the host and port when building the send URL. Defaults to `send` when omitted. Maximum 255 characters.
</ParamField>

<ParamField body="username" type="string" required>
  Authentication username for Basic Auth. Maximum 255 characters.
</ParamField>

<ParamField body="password" type="string" required>
  Authentication password for Basic Auth. Maximum 255 characters.
</ParamField>

<ParamField body="default_sender_id" type="string">
  Default originating address (alphanumeric sender ID or phone number). Maximum 30 characters.
</ParamField>

<ParamField body="callback_token" type="string">
  Token included in DLR callback validation. Maximum 255 characters. See [Webhooks](/api/webhooks) for security guidance.
</ParamField>

<ParamField body="is_active" type="boolean" default="false">
  Set to `true` to enable this gateway for outbound sending.
</ParamField>

<ParamField body="use_ssl" type="boolean" default="false">
  Set to `true` to connect to the gateway over HTTPS.
</ParamField>

<ParamField body="notes" type="string">
  Free-text internal notes. No length limit enforced by the API.
</ParamField>

<ParamField body="meta" type="object">
  Arbitrary key-value object for custom metadata. Stored as JSON.
</ParamField>

**Response**

Returns the newly created gateway object at HTTP `201`.

```bash title="Example request" theme={null}
curl -X POST https://your-instance.laracopilot.com/api/sms-gateways \
  -b cookies.txt \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Jasmin Primary",
    "provider_type": "jasmin",
    "server_host": "sms.example.com",
    "server_port": 8080,
    "api_path": "send",
    "username": "admin",
    "password": "s3cur3p4ss",
    "default_sender_id": "LaraCopilot",
    "callback_token": "tok_abc123",
    "is_active": true,
    "use_ssl": false
  }'
```

```json title="201 response" theme={null}
{
  "message": "SMS gateway created successfully.",
  "data": {
    "id": 1,
    "name": "Jasmin Primary",
    "provider_type": "jasmin",
    "server_host": "sms.example.com",
    "server_port": 8080,
    "api_path": "send",
    "username": "admin",
    "default_sender_id": "LaraCopilot",
    "callback_token": "tok_abc123",
    "is_active": true,
    "use_ssl": false,
    "notes": null,
    "meta": null,
    "created_at": "2024-03-20T09:15:00.000000Z",
    "updated_at": "2024-03-20T09:15:00.000000Z"
  }
}
```

***

## Get a gateway

Fetch a single gateway by ID. The response includes `messages_count`.

```http theme={null}
GET /api/sms-gateways/{smsGateway}
```

**Path parameters**

<ParamField path="smsGateway" type="integer" required>
  The ID of the SMS gateway to retrieve.
</ParamField>

```bash title="Example request" theme={null}
curl https://your-instance.laracopilot.com/api/sms-gateways/1 \
  -b cookies.txt
```

```json title="200 response" theme={null}
{
  "message": "SMS gateway loaded successfully.",
  "data": {
    "id": 1,
    "name": "Jasmin Primary",
    "provider_type": "jasmin",
    "server_host": "sms.example.com",
    "server_port": 8080,
    "api_path": "send",
    "username": "admin",
    "default_sender_id": "LaraCopilot",
    "callback_token": "tok_abc123",
    "is_active": true,
    "use_ssl": false,
    "notes": null,
    "meta": null,
    "messages_count": 142,
    "created_at": "2024-01-15T10:00:00.000000Z",
    "updated_at": "2024-03-01T14:22:10.000000Z"
  }
}
```

***

## Update a gateway

Replace all fields on an existing gateway. Every required field from [Create a gateway](#create-a-gateway) must be included. Use `PATCH /api/sms-gateways/{smsGateway}` for partial updates with the same field rules.

```http theme={null}
PUT /api/sms-gateways/{smsGateway}
```

**Path parameters**

<ParamField path="smsGateway" type="integer" required>
  The ID of the SMS gateway to update.
</ParamField>

**Request body**

Accepts the same fields as [Create a gateway](#create-a-gateway). All required fields must be present.

```bash title="Example request" theme={null}
curl -X PUT https://your-instance.laracopilot.com/api/sms-gateways/1 \
  -b cookies.txt \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "Jasmin Primary (updated)",
    "provider_type": "jasmin",
    "server_host": "sms2.example.com",
    "server_port": 8080,
    "username": "admin",
    "password": "n3wp4ss",
    "is_active": true,
    "use_ssl": true
  }'
```

```json title="200 response" theme={null}
{
  "message": "SMS gateway updated successfully.",
  "data": {
    "id": 1,
    "name": "Jasmin Primary (updated)",
    "provider_type": "jasmin",
    "server_host": "sms2.example.com",
    "server_port": 8080,
    "api_path": null,
    "username": "admin",
    "default_sender_id": "LaraCopilot",
    "callback_token": "tok_abc123",
    "is_active": true,
    "use_ssl": true,
    "notes": null,
    "meta": null,
    "created_at": "2024-01-15T10:00:00.000000Z",
    "updated_at": "2024-03-20T11:45:00.000000Z"
  }
}
```

***

## Delete a gateway

Permanently delete a gateway. This action cannot be undone. Associated `SmsMessage` records are not automatically removed.

```http theme={null}
DELETE /api/sms-gateways/{smsGateway}
```

**Path parameters**

<ParamField path="smsGateway" type="integer" required>
  The ID of the SMS gateway to delete.
</ParamField>

```bash title="Example request" theme={null}
curl -X DELETE https://your-instance.laracopilot.com/api/sms-gateways/1 \
  -b cookies.txt
```

```json title="200 response" theme={null}
{
  "message": "SMS gateway deleted successfully."
}
```

***

## List messages for a gateway

Return all `SmsMessage` records associated with a gateway, ordered newest first. Use this to inspect delivery history for a specific gateway.

```http theme={null}
GET /api/sms-gateways/{smsGateway}/messages
```

**Path parameters**

<ParamField path="smsGateway" type="integer" required>
  The ID of the SMS gateway whose messages you want to list.
</ParamField>

**Response**

<ResponseField name="message" type="string">
  Always `"SMS messages fetched successfully."` on success.
</ResponseField>

<ResponseField name="data" type="object[]">
  Array of SMS message objects ordered by `created_at` descending.

  <Expandable title="Message object properties">
    <ResponseField name="id" type="integer">
      Unique message identifier.
    </ResponseField>

    <ResponseField name="sms_gateway_id" type="integer">
      ID of the gateway that handled this message.
    </ResponseField>

    <ResponseField name="tenant_id" type="integer">
      Tenant that originated the message, or `null` for platform-level sends.
    </ResponseField>

    <ResponseField name="to_number" type="string">
      Destination phone number.
    </ResponseField>

    <ResponseField name="from_sender" type="string">
      Originating address used for this message.
    </ResponseField>

    <ResponseField name="message" type="string">
      SMS body text.
    </ResponseField>

    <ResponseField name="external_message_id" type="string">
      Message ID returned by the gateway, or a generated UUID if the gateway did not return one.
    </ResponseField>

    <ResponseField name="delivery_status" type="string">
      Current delivery status: `queued`, `submitted`, `delivered`, or `failed`.
    </ResponseField>

    <ResponseField name="direction" type="string">
      Always `"outbound"` for messages sent via this API.
    </ResponseField>

    <ResponseField name="callback_url" type="string">
      URL the gateway will POST the DLR to.
    </ResponseField>

    <ResponseField name="remote_response" type="object">
      Raw JSON response body returned by the gateway, merged with subsequent DLR payloads.
    </ResponseField>

    <ResponseField name="error_message" type="string">
      Error detail when `delivery_status` is `failed`, otherwise `null`.
    </ResponseField>

    <ResponseField name="requested_at" type="string">
      ISO 8601 timestamp when the send request was received.
    </ResponseField>

    <ResponseField name="submitted_at" type="string">
      ISO 8601 timestamp when the gateway accepted the message.
    </ResponseField>

    <ResponseField name="delivered_at" type="string">
      ISO 8601 timestamp when the DLR confirmed delivery.
    </ResponseField>
  </Expandable>
</ResponseField>

```bash title="Example request" theme={null}
curl https://your-instance.laracopilot.com/api/sms-gateways/1/messages \
  -b cookies.txt
```

```json title="200 response" theme={null}
{
  "message": "SMS messages fetched successfully.",
  "data": [
    {
      "id": 57,
      "sms_gateway_id": 1,
      "tenant_id": 4,
      "to_number": "+447911123456",
      "from_sender": "LaraCopilot",
      "message": "Your verification code is 849201.",
      "external_message_id": "gw-msg-00992",
      "delivery_status": "delivered",
      "direction": "outbound",
      "callback_url": "https://your-instance.laracopilot.com/api/sms-gateways/1/dlr",
      "remote_response": {"message_id": "gw-msg-00992", "status": 0},
      "error_message": null,
      "requested_at": "2024-03-20T10:00:00.000000Z",
      "submitted_at": "2024-03-20T10:00:01.000000Z",
      "delivered_at": "2024-03-20T10:00:08.000000Z"
    }
  ]
}
```

***

## Send an SMS

Dispatch an outbound SMS through the specified gateway. LaraCopilot creates an `SmsMessage` record with `delivery_status: "queued"`, forwards the message to the gateway over HTTP(S) with Basic Auth, then updates the record to `submitted` or `failed` based on the gateway's response. The final `SmsMessage` object — with its current `delivery_status` — is returned synchronously.

```http theme={null}
POST /api/sms-gateways/{smsGateway}/send
```

**Path parameters**

<ParamField path="smsGateway" type="integer" required>
  The ID of the SMS gateway to send through.
</ParamField>

**Request body**

<ParamField body="to_number" type="string" required>
  Destination phone number in E.164 format (e.g. `"+447911123456"`). Maximum 30 characters.
</ParamField>

<ParamField body="from_sender" type="string" required>
  Originating address shown to the recipient — alphanumeric sender ID or E.164 phone number. Maximum 30 characters.
</ParamField>

<ParamField body="message" type="string" required>
  SMS body text. Maximum 1000 characters.
</ParamField>

<ParamField body="tenant_id" type="integer">
  ID of the tenant on whose behalf the message is sent. Stored on the `SmsMessage` record for attribution. Optional.
</ParamField>

<ParamField body="callback_url" type="string">
  URL where the gateway should POST delivery receipts. Must be a valid URL. Defaults to `https://your-instance.laracopilot.com/api/sms-gateways/{id}/dlr` when omitted.
</ParamField>

**Send flow**

<Steps>
  <Step title="Record created">
    An `SmsMessage` record is created with `delivery_status: "queued"` and `requested_at` set to the current time.
  </Step>

  <Step title="Dispatch to gateway">
    LaraCopilot POSTs to `{scheme}://{server_host}:{server_port}/{api_path}` using Basic Auth credentials from the gateway. The payload includes `to`, `from`, `content`, `dlr-url`, `dlr-level`, and `dlr-method`.
  </Step>

  <Step title="Status updated">
    On a successful gateway response the record is updated to `delivery_status: "submitted"` and `submitted_at` is set. On any HTTP error or network exception the status is set to `"failed"` and `error_message` is populated.
  </Step>

  <Step title="Response returned">
    The refreshed `SmsMessage` record is returned. Poll [GET /api/sms-gateways/{id}/messages](#list-messages-for-a-gateway) or wait for the [DLR webhook](/api/webhooks) to confirm final delivery.
  </Step>
</Steps>

**Response**

<ResponseField name="message" type="string">
  Always `"SMS request processed."`.
</ResponseField>

<ResponseField name="data" type="object">
  The `SmsMessage` record after the gateway interaction.

  <Expandable title="Message object properties">
    <ResponseField name="id" type="integer">
      Unique message identifier.
    </ResponseField>

    <ResponseField name="sms_gateway_id" type="integer">
      Gateway that handled this message.
    </ResponseField>

    <ResponseField name="tenant_id" type="integer">
      Tenant attribution, or `null`.
    </ResponseField>

    <ResponseField name="to_number" type="string">
      Destination phone number.
    </ResponseField>

    <ResponseField name="from_sender" type="string">
      Originating address used.
    </ResponseField>

    <ResponseField name="message" type="string">
      SMS body text.
    </ResponseField>

    <ResponseField name="external_message_id" type="string">
      Message ID from the gateway response (`message_id` or `id` field), or a generated UUID.
    </ResponseField>

    <ResponseField name="delivery_status" type="string">
      `"submitted"` if the gateway accepted the request, `"failed"` if the gateway returned an error or the request timed out.
    </ResponseField>

    <ResponseField name="direction" type="string">
      Always `"outbound"`.
    </ResponseField>

    <ResponseField name="callback_url" type="string">
      DLR callback URL sent to the gateway.
    </ResponseField>

    <ResponseField name="remote_response" type="object">
      Parsed JSON body from the gateway response, or `{"body": "<raw text>"}` if the response was not valid JSON.
    </ResponseField>

    <ResponseField name="error_message" type="string">
      Error detail when `delivery_status` is `"failed"`, otherwise `null`.
    </ResponseField>

    <ResponseField name="requested_at" type="string">
      ISO 8601 timestamp when the send was initiated.
    </ResponseField>

    <ResponseField name="submitted_at" type="string">
      ISO 8601 timestamp when the gateway accepted the message, or `null` on failure.
    </ResponseField>

    <ResponseField name="delivered_at" type="string">
      ISO 8601 timestamp populated by the DLR webhook after delivery confirmation. `null` at this stage.
    </ResponseField>
  </Expandable>
</ResponseField>

```bash title="Example request" theme={null}
curl -X POST https://your-instance.laracopilot.com/api/sms-gateways/1/send \
  -b cookies.txt \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "to_number": "+447911123456",
    "from_sender": "LaraCopilot",
    "message": "Your verification code is 849201.",
    "tenant_id": 4,
    "callback_url": "https://your-instance.laracopilot.com/api/sms-gateways/1/dlr"
  }'
```

```json title="200 response — submitted" theme={null}
{
  "message": "SMS request processed.",
  "data": {
    "id": 58,
    "sms_gateway_id": 1,
    "tenant_id": 4,
    "to_number": "+447911123456",
    "from_sender": "LaraCopilot",
    "message": "Your verification code is 849201.",
    "external_message_id": "gw-msg-00993",
    "delivery_status": "submitted",
    "direction": "outbound",
    "callback_url": "https://your-instance.laracopilot.com/api/sms-gateways/1/dlr",
    "remote_response": {"message_id": "gw-msg-00993", "status": 0},
    "error_message": null,
    "requested_at": "2024-03-20T12:00:00.000000Z",
    "submitted_at": "2024-03-20T12:00:01.000000Z",
    "delivered_at": null
  }
}
```

```json title="200 response — failed" theme={null}
{
  "message": "SMS request processed.",
  "data": {
    "id": 59,
    "sms_gateway_id": 1,
    "tenant_id": null,
    "to_number": "+447911999000",
    "from_sender": "LaraCopilot",
    "message": "Test message.",
    "external_message_id": "3f2a1c4b-...",
    "delivery_status": "failed",
    "direction": "outbound",
    "callback_url": "https://your-instance.laracopilot.com/api/sms-gateways/1/dlr",
    "remote_response": {"exception": "Connection refused"},
    "error_message": "Connection refused",
    "requested_at": "2024-03-20T12:05:00.000000Z",
    "submitted_at": null,
    "delivered_at": null
  }
}
```
