# The message object

The message object represents a single SMS message sent through Postman. It contains all information about the message content, delivery status, and attempts.

### Quick reference

{% code expandable="true" %}

```json
{
  "id": "message_19e23cf4-6f0f-47ed-8856-4623817684b1",
  "recipient": "6599999999",
  "language": "english",
  "values": {
    "name": "John Doe",
    "fruit": "apple"
  },
  "fullMessage": "Hello John Doe, enjoy your apple!",
  "latestStatus": "success",
  "campaignId": "<YOUR_CAMPAIGN_ID>",
  "creatorId": "<USER_ID_OF_MESSAGE_CREATOR>",
  "creatorEmail": "campaign_93530a5f-9efd-4d4a-8b27-6a3770b815c2@postman.gov.sg",
  "createdAt": "2024-05-16T10:30:50.904+08:00",
  "updatedAt": "2024-05-16T10:30:50.965+08:00",
  "templateBodyId": "<YOUR_TEMPLATE_BODY_ID>",
  "templateBody": {
    "id": "<YOUR_TEMPLATE_BODY_ID>",
    "templateId": "<YOUR_TEMPLATE_ID>",
    "body": "{{body}}",
    "language": "english",
    "createdAt": "2024-05-16T10:13:15.111+08:00",
    "updatedAt": "2024-05-16T10:13:15.111+08:00",
    "creatorId": "user_200972fc-2aa5-42f5-b6fd-4023d96afcd4"
  },
  "attempts": [
    {
      "status": "success",
      "createdAt": "2024-05-16T10:57:52.534+08:00"
    },
    {
      "status": "failure",
      "createdAt": "2024-05-16T10:30:50.906+08:00",
      "error": {
        "type": "server_error",
        "code": "server_unknown_error"
      }
    }
  ],
  "batches": []
}
```

{% endcode %}

### Attributes

#### Core fields

**`id`** ***string***

Unique identifier for the message. Use this to:

* Retrieve message details and delivery status
* Retry a failed message

**`recipient`** ***string*****&#x20;Required**

The phone number of the message recipient.

**Format**: Country code + phone number (no leading `+`)

**Example**: `6599999999` (Singapore mobile number)

**Sending via NRIC**

For selected agencies, you can send to NRIC numbers instead of phone numbers:

```json
{
  "recipient": {
    "value": "S1234567A",
    "type": "nric"
  }
}
```

> **Note**: This is a legacy feature, new capaigns created will not be able to send via NRIC.

**`language`** ***string*****&#x20;Required**

The language of the message template. One of:

* `english`
* `chinese`
* `malay`
* `tamil`

**`values`** ***object*****&#x20;Required**

Template variables and their values that were inserted into the message.

```json
{
  "values": {
    "name": "John Doe",
    "recipient_name": "Jane",
    "topic": "tax filing"
  }
}
```

> **Important**: Avoid using `recipient` and `language` as value keys, as these are reserved mandatory fields.

#### Message content

**`fullMessage`** ***string***

The complete message as sent, including SMS header and footer.

**`templateBody`** ***object***

The template definition used to generate this message.

```json
{
  "id": "template_body_123",
  "templateId": "template_456",
  "body": "{{name}}, your application status: {{status}}",
  "language": "english"
}
```

#### Campaign & tracking

**`campaignId`** ***string***

Identifier linking this message to its campaign.

**`creatorId`** ***string***

User ID of the person who created this message on the first attempt.

**`creatorEmail`** ***string***

Email address of the creator.

#### Status & delivery

**`latestStatus`** ***string***

The current delivery status of the message.

**`attempts`** ***array of objects***

Delivery history showing each send attempt with status and timestamp.

```json
{
  "status": "success",
  "createdAt": "2024-05-16T10:57:52.534+08:00"
}
```

If a delivery failed, the attempt includes an `error` object:

```json
{
  "status": "failure",
  "createdAt": "2024-05-16T10:30:50.906+08:00",
  "error": {
    "type": "server_error",
    "code": "server_unknown_error"
  }
}
```

#### Timestamps

**`createdAt`** ***string***

ISO 8601 timestamp when the message was created.

**`updatedAt`** ***string***

ISO 8601 timestamp of the last status update.

***

### Message statuses

The table below shows all possible message statuses and what they mean:

| Status          | UI Label | Meaning                                                                                                  |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `created`       | Pending  | Message recorded in system, but not yet queued for sending                                               |
| `enqueued`      | Pending  | Message is in the send queue waiting to be processed                                                     |
| `sending`       | Pending  | Message is being sent to the messaging service provider                                                  |
| `sent`          | Sent     | Request sent to provider, awaiting delivery confirmation                                                 |
| `sent_to_telco` | Sent     | Message delivered to telco, awaiting device delivery. *May not reach device if recipient's phone is off* |
| `success`       | Success  | ✓ Message delivered to recipient's phone (terminal status)                                               |
| `failure`       | Failure  | ✗ Message failed to send (terminal status)                                                               |

#### Understanding `sent_to_telco`

When a message reaches `sent_to_telco` status:

* The message has successfully reached the recipient's telco
* The recipient's device may not have received it yet
* The device may be off, in airplane mode, or unreachable

> **48-hour limit**: After 48 hours in `sent_to_telco` status, you're unlikely to receive further updates from the telco. This is a telco limitation. If needed, compose a new message—the recipient may receive both versions.

***

### Message content guidelines

#### Supported characters

Postman supports the **GSM-7 character set**. All other characters are unsupported and should be excluded from message content.

> **Why this matters**: Unsupported characters significantly increase character count and segment count per SMS, which impacts:
>
> * Delivery cost
> * Send queue performance (affects all agencies)
> * Reliability (unsupported beyond 7 segments due to telco limits)

#### Best practices

**Avoid leading/trailing spaces**

The `values` object must not have content that starts or ends with whitespace. This will cause a `400 Bad Request` error.

```json
// ❌ Bad
{
  "values": {
    "name": " John Doe "
  }
}

// ✅ Good
{
  "values": {
    "name": "John Doe"
  }
}
```

**Keep messages concise**

* Limit to under 7 message segments
* Use supported characters only
* Test message length with the [Postman message segment calculator](https://message-segment-calculator.postman.gov.sg/)

***

### Error handling

When a message fails, the `attempts` array includes an error object with two fields:

**Error types**

| Type             | Meaning                                                        |
| ---------------- | -------------------------------------------------------------- |
| `delivery_error` | Message failed to deliver (recipient, routing, or telco issue) |
| `server_error`   | Postman system error                                           |

**Error codes**

| Code                     | Description                             |
| ------------------------ | --------------------------------------- |
| `recipient_invalid`      | Invalid phone number or NRIC format     |
| `recipient_unavailable`  | Recipient not reachable                 |
| `content_invalid`        | Message content failed validation       |
| `routing_error`          | Could not route to appropriate provider |
| `delivery_unknown_error` | Delivery failed for unknown reason      |
| `server_unknown_error`   | Postman system error                    |

***


---

# Agent Instructions: 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:

```
GET https://postman-v2.guides.gov.sg/technical-users-api/api-reference/the-message-object.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
