> For the complete documentation index, see [llms.txt](https://postman-v2.guides.gov.sg/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://postman-v2.guides.gov.sg/technical-users-api/api-reference/get-retrieve-batch-messages.md).

# GET - Retrieve batch messages

Retrieves messages and their delivery statuses for a given batch ID. Use this endpoint to check the delivery outcome of messages sent via Batch Send.

```
GET /campaigns/<campaignId>/batch/<batchId>/messages
```

***

**Path Parameters**

| Parameter    | Type   | Required | Description                                                                                   |
| ------------ | ------ | -------- | --------------------------------------------------------------------------------------------- |
| `campaignId` | string | Yes      | The ID of the campaign the batch belongs to.                                                  |
| `batchId`    | string | Yes      | The ID of the batch to retrieve. This is the `batchId` returned from the Batch Send response. |

***

**Query Parameters**

This endpoint supports cursor-based pagination and search.

| Parameter | Type   | Required | Description                                                                                                 |
| --------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------- |
| `limit`   | number | No       | Number of results per page.                                                                                 |
| `search`  | string | No       | Filter by recipient phone number. This is a substring match (e.g. `"11"` would match `"91122233"`).         |
| `after`   | string | No       | Cursor for fetching the next page. Use the `endCursor` value from the previous response's `pageData`.       |
| `before`  | string | No       | Cursor for fetching the previous page. Use the `startCursor` value from the previous response's `pageData`. |

***

**Request Headers**

| Header          | Value                 | Required |
| --------------- | --------------------- | -------- |
| `Authorization` | `Bearer YOUR_API_KEY` | Yes      |

***

**Request Body**

This endpoint does not require a request body.

***

**Response**

**HTTP 200 OK**

Returns a paginated list of message objects with delivery statuses.

```json
{
  "data": [
    {
      "createdAt": "2024-05-16T16:34:06.582+08:00",
      "updatedAt": "2024-05-16T16:36:05.595+08:00",
      "id": "<YOUR_MESSAGE_ID>",
      "recipient": "6599999999",
      "values": {
        "body": "test"
      },
      "fullMessage": "<YOUR_FULL_MESSAGE>",
      "latestStatus": "success",
      "templateBodyId": "<YOUR_TEMPLATE_BODY_ID>",
      "campaignId": "<YOUR_CAMPAIGN_ID>",
      "templateBody": {
        "createdAt": "2024-05-06T11:00:03.467+08:00",
        "updatedAt": "2024-05-06T11:00:03.467+08:00",
        "id": "<YOUR_TEMPLATE_BODY_ID>",
        "templateId": "<YOUR_TEMPLATE_ID>",
        "language": "english",
        "body": "{{body}}",
        "creatorId": "<YOUR_CREATOR_ID>"
      },
      "messageAttempts": [
        {
          "sentAt": "2024-05-16T16:35:43.009+08:00",
          "deliveredAt": null,
          "createdAt": "2024-05-16T16:34:06.604+08:00",
          "updatedAt": "2024-05-16T16:36:05.593+08:00",
          "id": "<YOUR_MESSAGE_ATTEMPT_ID>",
          "messageId": "<YOUR_MESSAGE_ID>",
          "externalAttemptId": "<YOUR_EXTERNAL_ATTEMPT_ID>",
          "status": "success",
          "errorType": null,
          "errorCode": null,
          "metadata": {},
          "creatorId": "<YOUR_CREATOR_ID>",
          "creator": {
            "email": "<YOUR_CREATOR_EMAIL>"
          }
        }
      ],
      "language": "english",
      "creatorEmail": "<YOUR_CREATOR_EMAIL>",
      "creatorId": "<USER_ID_OF_MESSAGE_CREATOR>",
      "numAttempts": 1
    },
    {
      "createdAt": "2024-05-16T16:34:06.582+08:00",
      "updatedAt": "2024-05-16T16:35:13.122+08:00",
      "id": "<YOUR_MESSAGE_ID>",
      "recipient": "6522222222",
      "values": {
        "body": "test"
      },
      "fullMessage": "<YOUR_FULL_MESSAGE>",
      "latestStatus": "failure",
      "templateBodyId": "<YOUR_TEMPLATE_BODY_ID>",
      "campaignId": "<YOUR_CAMPAIGN_ID>",
      "templateBody": {
        "createdAt": "2024-05-06T11:00:03.467+08:00",
        "updatedAt": "2024-05-06T11:00:03.467+08:00",
        "id": "<YOUR_TEMPLATE_BODY_ID>",
        "templateId": "<YOUR_TEMPLATE_ID>",
        "language": "english",
        "body": "{{body}}",
        "creatorId": "<YOUR_CREATOR_ID>"
      },
      "messageAttempts": [
        {
          "sentAt": "2024-05-16T16:35:13.118+08:00",
          "deliveredAt": null,
          "createdAt": "2024-05-16T16:34:06.604+08:00",
          "updatedAt": "2024-05-16T16:35:13.118+08:00",
          "id": "<YOUR_MESSAGE_ATTEMPT_ID>",
          "messageId": "<YOUR_MESSAGE_ID>",
          "externalAttemptId": "",
          "status": "failure",
          "errorType": "server_error",
          "errorCode": "server_unknown_error",
          "metadata": {},
          "creatorId": "<YOUR_CREATOR_ID>",
          "creator": {
            "email": "<YOUR_CREATOR_EMAIL>"
          }
        }
      ],
      "language": "english",
      "creatorEmail": "<YOUR_CREATOR_EMAIL>",
      "creatorId": "<USER_ID_OF_MESSAGE_CREATOR>",
      "numAttempts": 1
    }
  ],
  "pageData": {
    "hasNextPage": false,
    "hasPreviousPage": false,
    "startCursor": "WyIyMDI0LTA1LTE2VDE2OjM0OjA2LjU5MCswODowMCIsIjMwMjE5Il0=",
    "endCursor": "WyIyMDI0LTA1LTE2VDE2OjM0OjA2LjU5MCswODowMCIsIjMwMjE3Il0="
  }
}
```

**Top-level response fields**

| Field      | Type   | Description                      |
| ---------- | ------ | -------------------------------- |
| `data`     | array  | Array of message objects.        |
| `pageData` | object | Pagination metadata (see below). |

**Message object fields**

| Field             | Type   | Description                                                                                  |
| ----------------- | ------ | -------------------------------------------------------------------------------------------- |
| `createdAt`       | string | ISO 8601 timestamp of when the message was created.                                          |
| `updatedAt`       | string | ISO 8601 timestamp of the last update to the message.                                        |
| `id`              | string | The unique message ID.                                                                       |
| `recipient`       | string | The recipient's phone number.                                                                |
| `values`          | object | The template parameter values used in the message.                                           |
| `fullMessage`     | string | The full rendered message text, including Postman's header and footer.                       |
| `latestStatus`    | string | The current delivery status. See Message Statuses for all possible values.                   |
| `templateBodyId`  | string | The ID of the template body used.                                                            |
| `campaignId`      | string | The campaign ID the message belongs to.                                                      |
| `templateBody`    | object | The template body object containing `id`, `templateId`, `language`, `body`, and `creatorId`. |
| `messageAttempts` | array  | Array of delivery attempt objects (see below).                                               |
| `language`        | string | The language used for the message.                                                           |
| `creatorEmail`    | string | The email address of the message creator.                                                    |
| `creatorId`       | string | The user ID of the message creator.                                                          |
| `numAttempts`     | number | Total number of delivery attempts for this message.                                          |

**`messageAttempts` array**

Each attempt object contains the delivery attempt details.

| Field               | Type           | Description                                                                                              |
| ------------------- | -------------- | -------------------------------------------------------------------------------------------------------- |
| `sentAt`            | string         | ISO 8601 timestamp of when the message was sent to the provider.                                         |
| `deliveredAt`       | string or null | ISO 8601 timestamp of when the message was delivered. `null` if not delivered.                           |
| `createdAt`         | string         | ISO 8601 timestamp of when the attempt was created.                                                      |
| `updatedAt`         | string         | ISO 8601 timestamp of the last update to the attempt.                                                    |
| `id`                | string         | The unique attempt ID.                                                                                   |
| `messageId`         | string         | The message ID this attempt belongs to.                                                                  |
| `externalAttemptId` | string         | The external attempt ID from the messaging service provider. May be empty.                               |
| `status`            | string         | The status of this attempt (e.g. `success`, `failure`, `sent`).                                          |
| `errorType`         | string or null | The error type if the attempt failed: `delivery_error` or `server_error`. `null` if no error.            |
| `errorCode`         | string or null | The error code if the attempt failed. See Message Delivery Errors for the full list. `null` if no error. |
| `metadata`          | object         | Additional metadata for the attempt.                                                                     |
| `creatorId`         | string         | The user ID of the message creator.                                                                      |
| `creator`           | object         | Object containing the `email` of the message creator.                                                    |

**`pageData` object**

| Field             | Type    | Description                                                                             |
| ----------------- | ------- | --------------------------------------------------------------------------------------- |
| `hasNextPage`     | boolean | Whether there is a next page of results.                                                |
| `hasPreviousPage` | boolean | Whether there is a previous page of results.                                            |
| `startCursor`     | string  | Cursor for the first record on the current page. Use with the `before` query parameter. |
| `endCursor`       | string  | Cursor for the last record on the current page. Use with the `after` query parameter.   |

***

**Error Responses**

**HTTP 401 Unauthorized**

| Error Code                 | Message                                          | Cause                                           |
| -------------------------- | ------------------------------------------------ | ----------------------------------------------- |
| `invalid_api_key_provided` | The API key provided is invalid.                 | API key is incorrect, expired, or deleted.      |
| `invalid_ip_address_error` | The IP address used for this request is invalid. | Request sent from a non-whitelisted IP address. |

**HTTP 404 Not Found**

The batch ID does not exist or belongs to a campaign you do not have access to.

**HTTP 429 Too Many Requests**

| Error Code          | Message           | Cause                                                                                                                      |
| ------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `too_many_requests` | Too many requests | Rate limit exceeded. Default is 10 TPS per campaign, shared across all endpoints. Implement exponential backoff and retry. |

***

**Example: cURL**

```bash
curl -X GET \
  "https://postman.gov.sg/api/v2/campaigns/<YOUR_CAMPAIGN_ID>/batch/<YOUR_BATCH_ID>/messages" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**With pagination and search:**

```bash
curl -X GET \
  "https://postman.gov.sg/api/v2/campaigns/<YOUR_CAMPAIGN_ID>/batch/<YOUR_BATCH_ID>/messages?limit=10&search=9999&after=<END_CURSOR>" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

***

**Notes**

* Results are sorted by `createdAt` followed by `id`.
* The `search` parameter performs a substring match on the recipient phone number. For example, searching for `"11"` will match `"91122233"`.
* Webhooks for delivery status updates are not currently supported. You must poll this endpoint to check for status changes.
* Telcos do not provide read statuses. The terminal statuses are `success` (delivered) and `failure` (failed).
* To retry failed messages in the batch, use the Retry Batch Send endpoint.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://postman-v2.guides.gov.sg/technical-users-api/api-reference/get-retrieve-batch-messages.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
