UC-011 — Export Delivery Reports and History
| Field | Value |
|---|---|
| ID | UC-011 |
| Goal | Export delivery reports, message history and contacts as CSV |
| Channel | All (SMS, RCS, WhatsApp) |
| Complexity | ⭐⭐⭐ Advanced |
| Estimated time | 15 minutes |
| APIs involved | POST /api/partner-gateway/v1/exports/delivery-reports, GET /exports, GET /exports/{exportId}, POST /exports/{exportId}, POST /exports/contacts, GET /messages/history, POST /messages/history/export |
Real-world scenarios
- Banca Adriatica — Monthly billing report: On the first day of each month, the finance team exports all the delivery reports of the previous month to reconcile SMS and WhatsApp sending costs.
- FashionOutlet — Campaign performance analysis: After the Black Friday campaign, marketing exports the reports to compute delivery, open and conversion rates per channel.
- FarmaExpress — Compliance audit: For GDPR requirements, the DPO exports the full history of messages sent in a quarter, with recipient details.
Prerequisites
Before you begin, make sure you have:
- Active API Key → How to get one
- Messages to export → messages sent in the period you want to report on, or a
campaignId
Export flow
Step-by-step guide
Step 1 — Request the delivery-report export
Export the delivery reports for a date range. Dates use the format yyyy-MM-dd HH:mm:ss.SSSZ:
curl -X POST "https://api.qlara.ai/api/partner-gateway/v1/exports/delivery-reports" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"startDateTime": "2026-03-01 00:00:00.000+0100",
"endDateTime": "2026-03-31 23:59:59.000+0200",
"sendType": "API",
"exportFormat": "CSV"
}'
Response: 202 Accepted -- the export job is queued.
You can also export a specific campaign instead of a date range:
curl -X POST "https://api.qlara.ai/api/partner-gateway/v1/exports/delivery-reports" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"campaignId": 1584,
"exportFormat": "CSV"
}'
| Parameter | Type | Description |
|---|---|---|
startDateTime | string | Start of the range (yyyy-MM-dd HH:mm:ss.SSSZ) |
endDateTime | string | End of the range |
sender | string | Filter by sender |
recipient | string | Filter by recipient |
campaignId | integer | Campaign ID (alternative to the date range) |
sendType | string | Send type: WEB, WEB_API, API |
subAccountId | string | Filter by sub-account |
exportFormat | string | Format: CSV (default) or EXCEL |
A request with neither campaignId nor a date range, or with a date in the wrong format, is answered 400.
Step 2 — List the exports
Check the status of your exports. The list is paginated with page (0-based) and limit (default 10):
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/exports?page=0&limit=10" \
-H "X-Api-Key: YOUR_API_KEY"
Response:
{
"data": [
{
"id": 42,
"type": "DELIVERY_REPORT",
"detail": {
"startDateTime": "2026-03-01T00:00:00+01:00",
"endDateTime": "2026-03-31T23:59:59+02:00",
"sendType": "API",
"exportFormat": "CSV"
},
"status": "COMPLETED",
"createdAt": "2026-04-01 08:15:00.000+0200",
"expiresAt": "2026-04-08 08:15:00.000+0200",
"isAvailableForDownload": true
},
{
"id": 41,
"type": "CONTACTS",
"detail": {
"listIds": [10, 11],
"exportFormat": "CSV"
},
"status": "COMPLETED",
"createdAt": "2026-03-28 14:30:00.000+0100",
"expiresAt": "2026-04-04 14:30:00.000+0200",
"isAvailableForDownload": false
}
],
"page": 0,
"limit": 10,
"totalCount": 2,
"totalPages": 1
}
| Status | Meaning |
|---|---|
PENDING | The export is queued or being processed |
COMPLETED | The file is ready for download |
FAILED | The export ran into an error |
Step 3 — Check availability
Before downloading, check that isAvailableForDownload is true. If the link has expired (isAvailableForDownload: false), regenerate it:
curl -X POST "https://api.qlara.ai/api/partner-gateway/v1/exports/41" \
-H "X-Api-Key: YOUR_API_KEY"
Response: 202 Accepted -- the link will be regenerated. Wait a few seconds and check again with GET /exports. An export that has not expired yet is answered 400 (just download it), an unknown exportId 404.
Step 4 — Download the file
When the status is COMPLETED and isAvailableForDownload is true:
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/exports/42" \
-H "X-Api-Key: YOUR_API_KEY"
Response:
{
"url": "https://storage.example.com/exports/42.csv?token=abc123def456&expires=1712570100"
}
Use the returned URL to download the CSV file:
curl -o delivery-report-march-2026.csv "https://storage.example.com/exports/42.csv?token=abc123def456&expires=1712570100"
Export contacts
You can also export contact lists:
curl -X POST "https://api.qlara.ai/api/partner-gateway/v1/exports/contacts" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"listIds": [10, 11],
"exportFormat": "CSV"
}'
Response: 202 Accepted
| Parameter | Type | Description |
|---|---|---|
listIds | array[int] | IDs of the lists to export (alternative to contactIds) |
contactIds | array[int] | IDs of the specific contacts to export |
excludeContactIds | array[int] | IDs of contacts to exclude (only with listIds) |
exportFormat | string | Format: CSV or EXCEL |
If you specify neither listIds nor contactIds, all the contacts of your account are exported.
Message history
Browse the history
To browse your sending history without exporting it, use pagination. channel, from and to are required:
curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/messages/history?channel=SMS&from=2026-03-01T00:00:00%2B01:00&to=2026-03-31T23:59:59%2B02:00&page=0&limit=50" \
-H "X-Api-Key: YOUR_API_KEY"
Export the history as CSV
For large volumes, export the history asynchronously. Dates are ISO 8601 with an offset; sender and recipient are optional filters:
curl -X POST "https://api.qlara.ai/api/partner-gateway/v1/messages/history/export" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"startDateTime": "2026-03-01T00:00:00+01:00",
"endDateTime": "2026-03-31T23:59:59+02:00",
"sender": "TechStore",
"recipient": "+393471234567"
}'
Response: 202 Accepted with an empty body.
The export covers every channel (SMS, RCS, WhatsApp) and only the messages sent through the API; it has no channel or status filter. The job follows the same flow: check GET /exports and download with GET /exports/{exportId}.
Endpoint summary
| Action | Method | Endpoint |
|---|---|---|
| Export delivery reports | POST | /exports/delivery-reports |
| Export contacts | POST | /exports/contacts |
| Export message history | POST | /messages/history/export |
| List exports | GET | /exports |
| Download URL | GET | /exports/{exportId} |
| Regenerate expired link | POST | /exports/{exportId} |
| Browse history | GET | /messages/history |
Behind the scenes
Exports are designed to handle large data volumes without blocking the API:
- Queueing -- The
POSTrequest creates an asynchronous job and answers202 Acceptedwithin milliseconds. - Processing -- A background worker collects the data, formats it as CSV/EXCEL and uploads the file to secure storage.
- Status -- The status moves from
PENDINGtoCOMPLETED(orFAILED). PollGET /exportsto check it. - Download -- The download URL is a pre-signed link with an expiry. Once it has expired, you can regenerate it with
POST /exports/{exportId}without resubmitting the request. - Retention -- Exports stay available until
expiresAt(typically 7 days). After that the file is removed, but the original parameters are kept for regeneration.
Expected result
| Aspect | Detail |
|---|---|
| Action completed | Delivery reports, message history or contacts exported as a CSV/Excel file |
| Channel used | All (SMS, RCS, WhatsApp) |
| Delivery confirmation | Export status changes from PENDING to COMPLETED; download URL available |
Common errors
| Problem | Probable cause | Solution |
|---|---|---|
HTTP 401 | Missing or invalid API Key | Check X-Api-Key header |
HTTP 400 on the export request | Neither campaignId nor a date range, or a date in the wrong format | Pass campaignId or startDateTime/endDateTime (yyyy-MM-dd HH:mm:ss.SSSZ for delivery reports, ISO 8601 with offset for the history export) |
Export FAILED | The background job ran into an error | Request the export again; if it fails again, contact support quoting the X-Request-Id of the request |
isAvailableForDownload: false or HTTP 400 on GET /exports/{exportId} | Download link has expired | Regenerate the link with POST /exports/{exportId} |
HTTP 404 on /exports/{exportId} | Wrong exportId, or an export of another account | Take the id from GET /exports |
| Empty CSV | No messages found for the specified filters | Verify the date range, campaignId, sender and recipient filters |
Next steps
- Exports Guide -- Complete overview of the export system
- Contacts and Lists Guide -- Manage contacts and lists
- Webhooks Guide -- Configure webhooks for real-time tracking
- UC-010: Scheduled Messages -- Schedule sends, then export the reports