UC-019 — Analyze Message History
| Field | Value |
|---|---|
| ID | UC-019 |
| Goal | Query message history and export data for reports and audits |
| Channel | All (SMS, RCS, WhatsApp), one channel per query |
| Complexity | Intermediate |
| Estimated time | 15 minutes |
| APIs involved | GET /api/partner-gateway/v1/messages/history, POST /api/partner-gateway/v1/messages/history/export, GET /api/partner-gateway/v1/exports, GET /api/partner-gateway/v1/exports/{exportId} |
Real-world scenarios
- Monthly report: The TravelDream marketing manager generates a monthly report with sending volumes by channel and delivery rate.
- Per-channel analysis: The BrandCo team compares SMS vs WhatsApp performance to optimize the communication strategy.
- Audit trail: The compliance officer exports the messages sent to a specific customer for a GDPR audit.
Analysis flow
The diagram shows the interactive query flow and the asynchronous export for large datasets.
Prerequisites
- Active API Key with the
MESSAGESandEXPORTSoperations - At least one message sent through the API
- For large volume exports: allow time for asynchronous processing
Step 1 — Query message history
channel, from and to are required. A date alone covers the whole day in UTC.
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/messages/history?channel=SMS&from=2026-04-01&to=2026-04-09&page=0&limit=20" \
-H "X-Api-Key: YOUR_API_KEY"
Response — Message history
The response is a JSON array, one entry per message:
[
{
"customerMessageId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"channel": "SMS",
"destination": "+393471234567",
"deliveryStatus": "DELIVERED",
"deliveryStatusDescription": "delivered",
"sendDate": "2026-04-09T08:15:00Z",
"deliveryDate": "2026-04-09T08:15:03Z",
"readDate": null
},
{
"customerMessageId": "a2c4e6f8-1234-5678-9abc-def012345678",
"channel": "SMS",
"destination": "+393489876543",
"deliveryStatus": "UNDELIVERABLE",
"deliveryStatusDescription": "undeliverable",
"sendDate": "2026-04-08T14:00:00Z",
"deliveryDate": null,
"readDate": null
}
]
from and to accept a date (2026-04-01, the whole UTC day), a date-time without offset (2026-04-01T10:30:00, read as UTC) or a full ISO 8601 date-time with offset (2026-04-01T00:00:00%2B02:00, 2026-04-09T23:59:59Z). Percent-encode a + as %2B. Any other shape is answered 400 with the list of accepted formats.
Behind the scenes — Filters and pagination
- One channel per query:
channelisSMS,RCSorWHATSAPP(case-insensitive). To cover several channels, run one query per channel. - Status filter: add
statuswith onedeliveryStatusname to keep a single delivery status. The names depend on the channel (see the status table): SMS usesACCEPTED,REJECTED,DELIVERED,EXPIRED,DELETED,UNDELIVERABLEandUNKNOWN; RCS usesDELIVERED,EXPIRED,ERROR,DISABLED,UNSUPPORTEDandUNKNOWN; WhatsApp uses the RCS ones plusCONVERSATION_CLOSED. A status the channel never uses (for exampleERRORon SMS) returns an empty array. - Pagination:
pagestarts at 0 andlimitdefaults to 20. The response is a plain array: you are on the last page when it holds fewer items thanlimit. - Required range:
fromandtoare mandatory, andfrommust not be later thanto; otherwise the API answers400. - Sender and recipient filters are available on the export, not on the query.
Step 2 — Export data for reports
For large datasets, queue an asynchronous CSV export. Dates are ISO 8601 with offset; sender and recipient are optional filters.
curl -X POST https://api.qlara.ai/api/partner-gateway/v1/messages/history/export \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"startDateTime": "2026-03-01T00:00:00+01:00",
"endDateTime": "2026-03-31T23:59:59+02:00"
}'
Response — Export queued
202 Accepted with an empty body. The export covers every channel and only the messages sent through the API.
The file is generated in the background. Track it through the export endpoints: the list tells you when it is ready, the detail gives you the download URL.
# List your exports, newest first
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/exports?page=0&limit=10" \
-H "X-Api-Key: YOUR_API_KEY"
Response — Export list
{
"data": [
{
"id": 369,
"type": null,
"detail": {
"type": "DELIVERY_REPORT",
"exportFormat": "CSV",
"startDateTime": "2026-02-28T23:00:00Z",
"endDateTime": "2026-03-31T21:59:59Z",
"sendType": "API"
},
"status": null,
"createdAt": "2026-04-09 14:00:12.200+0000",
"expiresAt": "2026-04-16 14:00:12.199+0000",
"isAvailableForDownload": true
}
],
"page": 0,
"limit": 10,
"totalCount": 1,
"totalPages": 1
}
A history export appears as a DELIVERY_REPORT with sendType API. Once isAvailableForDownload is true, fetch the download URL:
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/exports/369" \
-H "X-Api-Key: YOUR_API_KEY"
Response — Download URL
{
"url": "https://storage.example.com/exports/369/delivery-report-2026-03.csv?X-Amz-Expires=3600&X-Amz-Signature=..."
}
Behind the scenes — Export process
- Queue: the request is placed on a dedicated queue so that it does not affect the real-time API.
- Scope: the export covers all channels (SMS, RCS, WhatsApp) but only the messages sent through the API, the same ones
GET /messages/historyshows. - Storage: the file is stored behind a signed URL that expires;
expiresAttells you until when. An expired export can be regenerated withPOST /exports/{exportId}. - Format: CSV only.
Expected result
| Step | Action | Result |
|---|---|---|
| 1 | GET /messages/history | Array of messages for the channel and date range |
| 2 | POST /messages/history/export | 202 Accepted, export queued |
| 3 | GET /exports | The export appears with isAvailableForDownload: true |
| 4 | GET /exports/{exportId} | Download URL |
Complete end-to-end example
Scenario TravelDream: monthly SMS report for March.
BASE="https://api.qlara.ai/api/partner-gateway/v1"
# 1. Data preview (first 5 messages)
echo "=== March History Preview ==="
curl -s -X GET "$BASE/messages/history?channel=SMS&from=2026-03-01&to=2026-03-31&page=0&limit=5" \
-H "X-Api-Key: YOUR_API_KEY" | jq '.[] | {destination, deliveryStatus, sendDate}'
# 2. Queue the full export (202, empty body)
curl -s -o /dev/null -w "export queued: HTTP %{http_code}\n" -X POST "$BASE/messages/history/export" \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{"startDateTime": "2026-03-01T00:00:00+01:00", "endDateTime": "2026-03-31T23:59:59+02:00"}'
# 3. Wait, then take the newest export once it is ready
sleep 60
EXPORT_ID=$(curl -s -X GET "$BASE/exports?page=0&limit=1" \
-H "X-Api-Key: YOUR_API_KEY" | jq -r '.data[0] | select(.isAvailableForDownload) | .id')
# 4. Download
DOWNLOAD_URL=$(curl -s -X GET "$BASE/exports/${EXPORT_ID}" \
-H "X-Api-Key: YOUR_API_KEY" | jq -r '.url')
echo "Download: $DOWNLOAD_URL"
Variants
Only failed messages
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/messages/history?channel=SMS&from=2026-04-01&to=2026-04-09&status=UNDELIVERABLE" \
-H "X-Api-Key: YOUR_API_KEY"
An SMS can also fail as REJECTED or EXPIRED: run one query per status to cover them all. ERROR is an RCS and WhatsApp status, so status=ERROR on SMS always returns an empty array.
Messages sent to one recipient (GDPR audit)
The query endpoint has no recipient filter; use the export with recipient:
curl -X POST https://api.qlara.ai/api/partner-gateway/v1/messages/history/export \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"startDateTime": "2025-01-01T00:00:00+01:00",
"endDateTime": "2026-04-09T23:59:59+02:00",
"recipient": "+393471234567"
}'
Common errors
400 Bad Request — Missing parameters
{
"status": "fail",
"data": "Required query params: 'channel' (RCS, WHATSAPP, SMS), 'from' and 'to' (yyyy-MM-dd (a whole day, UTC), yyyy-MM-ddTHH:mm:ss (UTC) or ISO-8601 with an offset such as 2025-01-15T00:00:00+01:00 or 2025-01-15T00:00:00Z)"
}
Solution: pass all three parameters. channel is one of SMS, RCS, WHATSAPP.
400 Bad Request — Date in an unknown format
{
"status": "fail",
"data": "Invalid 'from': '27/08/2026'. Accepted formats: yyyy-MM-dd (a whole day, UTC), yyyy-MM-ddTHH:mm:ss (UTC) or ISO-8601 with an offset such as 2025-01-15T00:00:00+01:00 or 2025-01-15T00:00:00Z"
}
Solution: use one of the formats listed in the message, and percent-encode a + in the offset as %2B.
Next steps
- UC-011 — Export Delivery Reports: Export detailed delivery reports
- UC-018 — Manage the Inbox: Manage conversations in real time
- UC-016 — Monitor Credit and Subscription: Check costs in the context of history