Skip to main content

UC-019 — Analyze Message History

FieldValue
IDUC-019
GoalQuery message history and export data for reports and audits
ChannelAll (SMS, RCS, WhatsApp), one channel per query
ComplexityIntermediate
Estimated time15 minutes
APIs involvedGET /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 MESSAGES and EXPORTS operations
  • 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://lora-api.agiletelecom.com/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": "Message delivered to handset",
"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": "ERROR",
"deliveryStatusDescription": "Undeliverable",
"sendDate": "2026-04-08T14:00:00Z",
"deliveryDate": null,
"readDate": null
}
]

:::tip Accepted date formats 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
  1. One channel per query: channel is SMS, RCS or WHATSAPP (case-insensitive). To cover several channels, run one query per channel.
  2. Status filter: add status=DELIVERED, ERROR, EXPIRED, SENT, RECEIVED or UNKNOWN to keep a single delivery status.
  3. Pagination: page starts at 0 and limit defaults to 20. The response is a plain array: you are on the last page when it holds fewer items than limit.
  4. Required range: from and to are mandatory, and from must not be later than to; otherwise the API answers 400.
  5. 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://lora-api.agiletelecom.com/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.

:::info Asynchronous export 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://lora-api.agiletelecom.com/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://lora-api.agiletelecom.com/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
  1. Queue: the request is placed on a dedicated queue so that it does not affect the real-time API.
  2. Scope: the export covers all channels (SMS, RCS, WhatsApp) but only the messages sent through the API, the same ones GET /messages/history shows.
  3. Storage: the file is stored behind a signed URL that expires; expiresAt tells you until when. An expired export can be regenerated with POST /exports/{exportId}.
  4. Format: CSV only.

Expected result​

StepActionResult
1GET /messages/historyArray of messages for the channel and date range
2POST /messages/history/export202 Accepted, export queued
3GET /exportsThe export appears with isAvailableForDownload: true
4GET /exports/{exportId}Download URL

Complete end-to-end example​

Scenario TravelDream: monthly SMS report for March.

BASE="https://lora-api.agiletelecom.com/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://lora-api.agiletelecom.com/api/partner-gateway/v1/messages/history?channel=SMS&from=2026-04-01&to=2026-04-09&status=ERROR" \
-H "X-Api-Key: YOUR_API_KEY"

Messages sent to one recipient (GDPR audit)​

The query endpoint has no recipient filter; use the export with recipient:

curl -X POST https://lora-api.agiletelecom.com/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​

References​