## Messages

These endpoints let you send SMS messages and read the inbound messages received on your Guava numbers — for example, to poll your own inbox for replies.

All requests require an `Authorization: Bearer YOUR_GUAVA_API_KEY` header. See the [API Overview](/docs/api-overview) for details.

### Send an SMS

```http
POST /v1/send-sms
```

Send a single SMS from one of your Guava numbers.

#### Request body

A JSON object with the following fields:

| Name            | Type    | Required | Description                                                            |
|-----------------|---------|----------|------------------------------------------------------------------------|
| `from_number`   | string  | Yes      | One of your Guava numbers, in E.164 format. Must have SMS enabled.    |
| `to_number`     | string  | Yes      | The recipient's number, in E.164 format.                               |
| `message`       | string  | Yes      | The message body to send.                                             |

#### Response

On success, returns `201 Created`:

```json
{
  "status": "sent"
}
```

#### Errors

| Status | Description                                                                                                         |
|--------|---------------------------------------------------------------------------------------------------------------------|
| 400    | The `from_number` isn't owned by your organization, or doesn't have SMS configured.                                |
| 401    | Invalid authentication                                                                                              |
| 500    | The upstream carrier failed to accept the message.                                                                  |

#### Example

```bash
curl -X POST https://api.goguava.ai/v1/send-sms \
  -H 'Authorization: Bearer YOUR_GUAVA_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"from_number": "+15551230001", "to_number": "+15551234567", "message": "Hello from Guava!"}'
```

Sending SMS requires your organization to complete SMS brand and campaign registration. See [Outbound & SMS Permissions](/docs/outbound-and-sms-permissions) for details.

---

### List inbound messages

```http
GET /v1/messages
```

List the inbound messages received on one of your Guava numbers, oldest first. Poll this endpoint to watch for replies.

#### Parameters

| Name         | Type    | Required | Description                                                   |
|--------------|---------|----------|---------------------------------------------------------------|
| `to_number`  | string  | Yes      | The Guava number whose inbox you want to read, in E.164 format. Must be owned by your organization. |
| `start`      | string  | No       | Only return messages received at or after this time (ISO 8601, e.g. `2026-06-09T00:00:00Z`). |
| `from_number`| string  | No       | Only return messages sent from this number, in E.164 format. |
| `modality`   | string  | No       | Only return messages on this channel. Currently `"sms"`.    |
| `limit`      | integer | No       | Maximum number of messages to return, between 1 and 100. Defaults to 50. |

#### Response

A JSON object with the following fields:

| Field       | Type    | Description                                                    |
|-------------|---------|---------------------------------------------------------------|
| `messages`  | array   | The matching messages, oldest first.                          |
| `has_more`  | boolean | `true` if more messages match than were returned in this response. |

Each message has the following fields:

| Field        | Type    | Description                                                    |
|--------------|---------|---------------------------------------------------------------|
| `id`        | string  | Unique ID of the message                                      |
| `from_number`| string  | The number that sent the message                              |
| `to_number`  | string  | Your Guava number that received the message                   |
| `content`    | string  | The message body                                             |
| `received_at`| string  | When the message was received, in ISO 8601 format           |
| `modality`   | string  | The channel the message arrived on. Currently `"sms"`.     |
| `direction`  | string  | Always `"inbound"`                                         |

#### Pagination

Messages are returned oldest first. When `has_more` is `true`, request the next page by calling again with `start` set to the `received_at` of the **last** message you received. Because `start` is inclusive, that boundary message — and any others sharing its exact timestamp — will be returned again, so dedupe by `id`.

#### Errors

| Status | Description                                                                        |
|--------|------------------------------------------------------------------------------------|
| 400    | Invalid `start` timestamp or `limit` value                                       |
| 401    | Invalid authentication                                                             |
| 404    | The `to_number` isn't owned by your organization                                   |

#### Example

```bash
curl -G https://api.goguava.ai/v1/messages \
  -H 'Authorization: Bearer YOUR_GUAVA_API_KEY' \
  --data-urlencode 'to_number=+15551230001' \
  --data-urlencode 'start=2026-06-09T00:00:00Z'
```

Sample response:

```json
{
  "messages": [
    {
      "id": "6064ab9663dc4eb0",
      "from_number": "+15551234567",
      "to_number": "+15551230001",
      "content": "YES, see you then!",
      "received_at": "2026-06-09T00:12:04.518000+00:00",
      "modality": "sms",
      "direction": "inbound"
    }
  ],
  "has_more": false
}
```

The `+` in a phone number must be URL-encoded as `%2B` in query strings. The `curl -G --data-urlencode` form above handles this for you.
