Get a message
GET
/v1/messages/{message}The message msg_… of the account with the history of its statuses (events, oldest first). A message of another account is not found, nor a message of the other mode: a test key sees only the test messages (test true), a live key only the live ones. Keys with the status permission.
API key permission: status · Limit: 20 requests a second per key
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
message | string | yes |
Request
bash
curl "https://api.ace-send.com/v1/messages/msg_CgdWeHQN4sPaZnXfh7kP5" \
-H "Authorization: Bearer ak_live_YOUR_API_KEY"js
const response = await fetch('https://api.ace-send.com/v1/messages/msg_CgdWeHQN4sPaZnXfh7kP5', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.ACE_SEND_API_KEY}`,
},
})
const result = await response.json()
if (!response.ok) {
// application/problem+json: result.code is stable, result.title is for people
throw new Error(`${result.code}: ${result.title}`)
}
console.log(result)python
import os
import requests
headers = {
"Authorization": f"Bearer {os.environ['ACE_SEND_API_KEY']}",
}
response = requests.get(
"https://api.ace-send.com/v1/messages/msg_CgdWeHQN4sPaZnXfh7kP5",
headers=headers,
timeout=10,
)
result = response.json()
if not response.ok:
# application/problem+json: result["code"] is stable, result["title"] is for people
raise RuntimeError(f"{result['code']}: {result['title']}")
print(result)php
<?php
// composer require guzzlehttp/guzzle
$client = new GuzzleHttp\Client(['base_uri' => 'https://api.ace-send.com/v1/']);
$response = $client->request('GET', 'messages/msg_CgdWeHQN4sPaZnXfh7kP5', [
'headers' => [
'Authorization' => 'Bearer '.getenv('ACE_SEND_API_KEY'),
],
'http_errors' => false,
]);
$result = json_decode((string) $response->getBody(), true);
if ($response->getStatusCode() >= 400) {
// application/problem+json: $result['code'] is stable, $result['title'] is for people
throw new RuntimeException($result['code'].': '.$result['title']);
}
print_r($result);Response
200 OK
| Field | Type | Description |
|---|---|---|
data | Message |
json
{
"data": {
"id": "msg_CgdWeHQN4sPaZnXfh7kP5",
"status": "read",
"to": "+5521998120937",
"from": null,
"country": "BR",
"channel": "whatsapp",
"template": {
"name": "welcome_bonus",
"version": 3
},
"language": "pt",
"reference": "crm-42",
"text": "Olá Ana! Seu bônus BONUS10 já está ativo.",
"text_masked": false,
"segments": 1,
"encoding": null,
"price": {
"amount": "0.062500",
"currency": "USD"
},
"error": null,
"test": false,
"campaign": null,
"created_at": "2026-11-02T12:00:00+00:00",
"updated_at": "2026-11-02T12:00:09+00:00",
"events": [
{
"status": "accepted",
"at": "2026-11-02T12:00:00+00:00",
"error": null
},
{
"status": "queued",
"at": "2026-11-02T12:00:00+00:00",
"error": null
},
{
"status": "submitted",
"at": "2026-11-02T12:00:01+00:00",
"error": null
},
{
"status": "sent",
"at": "2026-11-02T12:00:02+00:00",
"error": null
},
{
"status": "delivered",
"at": "2026-11-02T12:00:04+00:00",
"error": null
},
{
"status": "read",
"at": "2026-11-02T12:00:09+00:00",
"error": null
}
]
}
}json
{
"data": {
"id": "msg_CgdWeHQNqtkmHvG3auyN5",
"status": "rejected",
"to": "+5521998120938",
"from": null,
"country": "BR",
"channel": "whatsapp",
"template": {
"name": "welcome_bonus",
"version": 3
},
"language": "pt",
"reference": "crm-43",
"text": "Olá Bruno! Seu bônus BONUS10 já está ativo.",
"text_masked": false,
"segments": 1,
"encoding": null,
"price": {
"amount": "0.062500",
"currency": "USD"
},
"error": {
"code": "no_whatsapp",
"text": "The number does not use WhatsApp"
},
"test": false,
"campaign": null,
"created_at": "2026-11-02T12:00:00+00:00",
"updated_at": "2026-11-02T12:00:02+00:00",
"events": [
{
"status": "accepted",
"at": "2026-11-02T12:00:00+00:00",
"error": null
},
{
"status": "queued",
"at": "2026-11-02T12:00:00+00:00",
"error": null
},
{
"status": "submitted",
"at": "2026-11-02T12:00:01+00:00",
"error": null
},
{
"status": "rejected",
"at": "2026-11-02T12:00:02+00:00",
"error": {
"code": "no_whatsapp",
"text": "The number does not use WhatsApp"
}
}
]
}
}Objects
Message object
| Field | Type | Description |
|---|---|---|
id | string | The message, msg_…. |
status | string | One of: accepted, queued, submitted, sent, delivered, read, rejected, failed, expired, cancelled. |
to | string | The number in E.164. |
from | string, nullable | The sender name of an SMS; null for WhatsApp (its number is not shown) and for a test SMS. |
country | string | ISO 3166-1 alpha-2 of the number. |
channel | string | One of: whatsapp, sms. |
template | object, nullable | The template and the number of the version the message was sent with; null for an own SMS text. |
template.name | string | |
template.version | integer | |
language | string, nullable | The language of the template; null for an own SMS text. |
reference | string, nullable | Your own id of the message, as you sent it. |
text | string, nullable | The text as sent; null once it is past its retention period (90 days, text_masked). |
text_masked | boolean | Whether text was erased after the retention period (90 days). |
segments | integer | The parts the SMS is sent and priced in (its price is the price of a segment times them); 1 for WhatsApp. |
encoding | string, nullable | The encoding of the SMS: gsm7 (160 characters, 153 a segment of a longer text) or ucs2 (70, 67); null for WhatsApp. One of: gsm7, ucs2. |
price | object, nullable | The price fixed at acceptance, in the currency of the account; for an SMS, the price of a segment times segments. Null for a test message. |
price.amount | string | |
price.currency | string | |
error | object, nullable | Why the message did not reach the recipient: a stable code and a text in the language of Accept-Language. Null while it is on its way or when delivered. |
error.code | string | |
error.text | string | |
test | boolean | Sent with a test key: through the sandbox, free. |
campaign | object, nullable | The console campaign that sent the message; null for a message of the API. |
campaign.id | string | |
campaign.name | string | |
created_at | string | When the message was accepted. |
updated_at | string | When the message last changed. |
events | object[], nullable | The history of statuses, oldest first. Only in GET /messages/{id}; null elsewhere. |
events[].status | string | |
events[].at | string | |
events[].error | object, nullable | |
events[].error.code | string | |
events[].error.text | string |
Errors
Errors are application/problem+json with a stable code (all codes). Besides the errors of every request (an invalid key, a missing permission, too many requests), this endpoint answers:
| Status | Code | Meaning |
|---|---|---|
| 404 | not_found | No such path, or no such object in the account (a message of another account or of the other key mode). |
json
{
"type": "about:blank",
"status": 404,
"code": "not_found",
"title": "Not found"
}