> 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-a-single-message.md).

# GET - Retrieve a single message

Retrieves a single message and its delivery status.

Postman does not support pushing delivery status to your server via webhooks when the status of a message changes. You must poll this endpoint to get the message `latestStatus`.

```
GET /campaigns/<campaignId>/messages/<messageId>
```

***

**Path Parameters**

| Parameter    | Type   | Required | Description                                                                                                        |
| ------------ | ------ | -------- | ------------------------------------------------------------------------------------------------------------------ |
| `campaignId` | string | Yes      | The ID of the campaign the message belongs to.                                                                     |
| `messageId`  | string | Yes      | The ID of the message to retrieve. This is the `id` returned from the Single Send or Single Send - Retry response. |

***

**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 the message object with full delivery status, template information, and attempt history.

```json
{
  "createdAt": "2024-05-16T10:30:50.904+08:00",
  "updatedAt": "2024-05-16T10:30:50.965+08:00",
  "id": "<YOUR_MESSAGE_ID>",
  "recipient": "6599999999",
  "values": {
    "name": "John Doe",
    "fruit": "apple"
  },
  "fullMessage": "<YOUR_FULL_MESSAGE>",
  "latestStatus": "success",
  "templateBodyId": "<YOUR_TEMPLATE_BODY_ID>",
  "campaignId": "<YOUR_CAMPAIGN_ID>",
  "templateBody": {
    "createdAt": "2024-05-16T10:13:15.111+08:00",
    "updatedAt": "2024-05-16T10:13:15.111+08:00",
    "id": "<YOUR_TEMPLATE_BODY_ID>",
    "templateId": "<YOUR_TEMPLATE_ID>",
    "language": "english",
    "body": "Dear {{name}}, here is your {{fruit}}.",
    "creatorId": "<YOUR_CREATOR_ID>"
  },
  "batches": [],
  "language": "english",
  "creatorEmail": "<YOUR_CREATOR_EMAIL>",
  "creatorId": "<USER_ID_OF_MESSAGE_CREATOR>",
  "attempts": [
    {
      "status": "success",
      "createdAt": "2024-05-16T10:57:52.534+08:00"
    }
  ]
}
```

**Response 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 (see below).                                                                    |
| `batches`        | array  | Array of batch objects if the message was sent as part of a batch. Empty array for single send messages. |
| `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.                                                                      |
| `attempts`       | array  | Array of delivery attempt objects (see below).                                                           |

**`templateBody` object**

| Field        | Type   | Description                                                 |
| ------------ | ------ | ----------------------------------------------------------- |
| `createdAt`  | string | ISO 8601 timestamp of when the template body was created.   |
| `updatedAt`  | string | ISO 8601 timestamp of the last update to the template body. |
| `id`         | string | The template body ID.                                       |
| `templateId` | string | The parent template ID.                                     |
| `language`   | string | The language of this template body.                         |
| `body`       | string | The raw template body with `{{variables}}` placeholders.    |
| `creatorId`  | string | The user ID of the template creator.                        |

**`attempts` array**

Each attempt object contains the status and timestamp for a delivery attempt. If the status is `failure`, there will be an additional `error` object.

| Field         | Type           | Description                                                                                     |
| ------------- | -------------- | ----------------------------------------------------------------------------------------------- |
| `status`      | string         | The status of this attempt: `success` or `failure`.                                             |
| `createdAt`   | string         | ISO 8601 timestamp of when the attempt was created.                                             |
| `sentAt`      | string         | ISO 8601 timestamp of when the message was sent to the provider. Present on `failure` attempts. |
| `deliveredAt` | string or null | ISO 8601 timestamp of when the message was delivered. `null` if not delivered.                  |
| `error`       | object         | Present only on `failure` attempts. Contains `type` and `code` fields.                          |

**`error` object (within an attempt)**

| Field  | Type   | Description                                                    |
| ------ | ------ | -------------------------------------------------------------- |
| `type` | string | The error type: `delivery_error` or `server_error`.            |
| `code` | string | The error code. See Message Delivery Errors for the full list. |

**Example response with a failed attempt followed by a successful retry:**

```json
{
  "createdAt": "2024-05-16T10:30:50.904+08:00",
  "updatedAt": "2024-05-16T10:57:52.534+08:00",
  "id": "<YOUR_MESSAGE_ID>",
  "recipient": "6599999999",
  "values": {
    "name": "John Doe",
    "fruit": "apple"
  },
  "fullMessage": "<YOUR_FULL_MESSAGE>",
  "latestStatus": "success",
  "templateBodyId": "<YOUR_TEMPLATE_BODY_ID>",
  "campaignId": "<YOUR_CAMPAIGN_ID>",
  "templateBody": {
    "createdAt": "2024-05-16T10:13:15.111+08:00",
    "updatedAt": "2024-05-16T10:13:15.111+08:00",
    "id": "<YOUR_TEMPLATE_BODY_ID>",
    "templateId": "<YOUR_TEMPLATE_ID>",
    "language": "english",
    "body": "Dear {{name}}, here is your {{fruit}}.",
    "creatorId": "<YOUR_CREATOR_ID>"
  },
  "batches": [],
  "language": "english",
  "creatorEmail": "<YOUR_CREATOR_EMAIL>",
  "creatorId": "<USER_ID_OF_MESSAGE_CREATOR>",
  "attempts": [
    {
      "status": "success",
      "createdAt": "2024-05-16T10:57:52.534+08:00"
    },
    {
      "status": "failure",
      "createdAt": "2024-05-16T10:30:50.906+08:00",
      "sentAt": "2024-05-16T10:31:50.187+08:00",
      "deliveredAt": null,
      "error": {
        "type": "server_error",
        "code": "server_unknown_error"
      }
    }
  ]
}
```

In this example, the first attempt failed with `server_unknown_error`. After a retry via the [Single Send - Retry](https://postman-v2.guides.gov.sg/endpoints-for-api-users/single-send-retry) endpoint, the second attempt succeeded. The `latestStatus` reflects the most recent outcome.

***

**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 message 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>/messages/<YOUR_MESSAGE_ID> \
  -H "Authorization: Bearer YOUR_API_KEY"
```

***

**Notes**

* Webhooks for delivery status updates are not currently supported. You must poll this endpoint to check for status changes.
* The `attempts` array shows the full history of delivery attempts, including any retries. The most recent attempt is listed first.
* The `latestStatus` field reflects the outcome of the most recent attempt.
* Telcos do not provide read statuses. The terminal statuses are `success` (delivered) and `failure` (failed).
* SMSes with `failure` as the `latestStatus` will not be charged.
* If `latestStatus` is `sent_to_telco` beyond 48 hours, it is unlikely that a further status update will be received. This is a telco limitation.


---

# 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-a-single-message.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.
