Skip to main content

UC-029 — Complete Campaign Report

FieldValue
IDUC-029
GoalCreate a campaign, monitor its statistics and download the complete CSV report
ChannelSMS (applicable to all channels)
Complexity⭐⭐⭐ Advanced
Estimated time25 minutes
APIs involvedPOST /api/partner-gateway/v1/campaigns, PUT /api/partner-gateway/v1/campaigns/{id}/confirm, GET /api/partner-gateway/v1/campaigns/{id}/stats, POST /api/partner-gateway/v1/exports/delivery-reports, GET /api/partner-gateway/v1/exports/{exportId}

Real-world scenarios

  • FashionOutlet — Black Friday ROI analysis: After the Black Friday campaign, the marketing team wants a detailed report with delivery rates by operator, total costs and comparison with the previous year.
  • TelcoMobile — Weekly management report: Every Monday, the communications manager generates an aggregate report of the week's campaigns for the executive team.
  • BancaAdriatica — Enterprise client delivery audit: The compliance team needs to document the delivery rate of transactional notifications for a quarterly internal audit.

:::info Composite use case This UC combines the flows from UC-006 — Bulk SMS Campaign and UC-011 — Export Delivery Reports into a complete end-to-end workflow. :::

Prerequisites

Before you begin, make sure you have:

:::tip Test without costs Add "simulation": true in the request body to validate the flow without actually sending messages and without consuming credit. :::

Complete flow

The diagram illustrates the complete workflow: from campaign creation to CSV report download for analysis.

Step 1 — Create the campaign

Create a new SMS campaign targeted to a contact list:

curl -X POST "https://lora-api.agiletelecom.com/api/partner-gateway/v1/campaigns" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Black Friday 2026 - SMS Promo",
"channel": "SMS",
"sender": "FashionOut",
"contactListId": "lst_bf2026_clienti_vip",
"message": {
"body": "Ciao {firstName}! Black Friday FashionOutlet: -50% su tutto solo oggi! Usa il codice BF2026 su https://fashionoutlet.it/bf Rispondi STOP per opt-out."
},
"scheduledDate": "2026-11-27T09:00:00+01:00"
}'

Response — Campaign created

{ "id": "cmp_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90", "status": "DRAFT", "totalContacts": 15420, "scheduledDate": "2026-11-27T09:00:00+01:00" }

:::tip Save the campaign ID The campaign id field is needed for all subsequent steps: confirmation, monitoring and report linking. :::

Step 2 — Confirm the campaign send

The campaign remains in DRAFT status until explicit confirmation:

curl -X PUT "https://lora-api.agiletelecom.com/api/partner-gateway/v1/campaigns/cmp_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90/confirm" \
-H "X-Api-Key: YOUR_API_KEY"

Response — Campaign confirmed

{ "id": "cmp_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90", "status": "CONFIRMED", "estimatedCompletionTime": "2026-11-27T09:45:00+01:00" }
Behind the scenes — What happens after confirmation
  1. Validation: The system verifies contact list, sender and credit.
  2. Scheduling: If the scheduledDate is in the future, the campaign stays in queue.
  3. Throttling: Sending occurs in batches (15,000 SMS in ~30-45 minutes).
  4. Credit: Charged at actual send time, not at confirmation.

Step 3 — Monitor campaign statistics

During and after sending, check the aggregate statistics:

curl -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/campaigns/cmp_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90/stats" \
-H "X-Api-Key: YOUR_API_KEY"

Response — Completed campaign statistics

{
"campaignId": "cmp_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
"status": "COMPLETED",
"stats": {
"totalMessages": 15420, "delivered": 14650, "failed": 458,
"deliveryRate": 95.01, "totalCost": 539.70
},
"completedAt": "2026-11-27T09:38:22+01:00"
}

:::info Statistics polling Statistics are updated in real-time during sending. You can query the endpoint every 30-60 seconds to monitor progress. The status transitions from SENDING to COMPLETED when all messages have been processed. :::

Step 4 — Export the delivery report

Request the CSV export with the detail of every single message:

curl -X POST "https://lora-api.agiletelecom.com/api/partner-gateway/v1/exports/delivery-reports" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"dateFrom": "2026-11-27",
"dateTo": "2026-11-28",
"channel": "SMS",
"campaignId": "cmp_d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90"
}'

Response — Export queued

{
"exportId": "exp_1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"status": "PENDING",
"type": "DELIVERY_REPORTS",
"createdAt": "2026-11-28T10:00:00+01:00"
}

Step 5 — Download the CSV

Check the export status with GET /exports/{exportId}. When status is COMPLETED, use the downloadUrl to download the file:

curl -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/exports/exp_1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d" \
-H "X-Api-Key: YOUR_API_KEY"
{
"exportId": "exp_1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"status": "COMPLETED",
"isAvailableForDownload": true,
"downloadUrl": "https://cdn.agiletelecom.com/exports/exp_1a2b3c4d.csv?token=eyJhbG...",
"fileSize": 2458900,
"totalRows": 15420
}
curl -o "report_blackfriday_2026.csv" \
"https://cdn.agiletelecom.com/exports/exp_1a2b3c4d.csv?token=eyJhbG..."
Behind the scenes — CSV structure

The CSV contains one row per message with columns: messageId, destination, channel, status, statusCode, sendDate, deliveryDate, cost, parts, campaignId. The async export is necessary for large datasets.

Expected result

StepActionResult
1POST /campaignsCampaign created, status: "DRAFT"
2PUT /campaigns/{id}/confirmstatus: "CONFIRMED", delivery scheduled
3GET /campaigns/{id}/statsAggregate statistics, deliveryRate: 95.01%
4POST /exports/delivery-reportsExport queued, status: "PENDING"
5GET /exports/{id}Downloadable CSV with 15,420 message details

Complete end-to-end example

#!/bin/bash
API_KEY="YOUR_API_KEY"
BASE_URL="https://lora-api.agiletelecom.com/api/partner-gateway/v1"

# 1. Create and confirm campaign
CMP_ID=$(curl -s -X POST "${BASE_URL}/campaigns" \
-H "X-Api-Key: ${API_KEY}" -H "Content-Type: application/json" \
-d '{"name":"Black Friday 2026","channel":"SMS","sender":"FashionOut","contactListId":"lst_bf2026_clienti_vip","message":{"body":"Ciao {firstName}! -50% su tutto! Codice BF2026"}}' | jq -r '.id')

curl -s -X PUT "${BASE_URL}/campaigns/${CMP_ID}/confirm" -H "X-Api-Key: ${API_KEY}" > /dev/null

# 2. Monitor until completion
while true; do
CMP_STATUS=$(curl -s -X GET "${BASE_URL}/campaigns/${CMP_ID}/stats" \
-H "X-Api-Key: ${API_KEY}" | jq -r '.status')
echo "Status: ${CMP_STATUS}"
[[ "$CMP_STATUS" == "COMPLETED" ]] && break
sleep 60
done

# 3. Export and download
EXP_ID=$(curl -s -X POST "${BASE_URL}/exports/delivery-reports" \
-H "X-Api-Key: ${API_KEY}" -H "Content-Type: application/json" \
-d '{"dateFrom":"2026-11-27","dateTo":"2026-11-28","channel":"SMS","campaignId":"'"${CMP_ID}"'"}' | jq -r '.exportId')

sleep 30
DL_URL=$(curl -s -X GET "${BASE_URL}/exports/${EXP_ID}" -H "X-Api-Key: ${API_KEY}" | jq -r '.downloadUrl')
curl -o "report_blackfriday_2026.csv" "$DL_URL"

Variants

Multi-channel report

For multi-channel campaigns, omit the channel filter in the export request to include SMS, RCS and WhatsApp in the same CSV.

Aggregate report by period

For a weekly report including all campaigns, omit campaignId and specify only dateFrom/dateTo.

Common errors

404 Not Found — Campaign does not exist

{ "status": "fail", "data": { "error": "Campaign not found" } }

Solution: Verify the campaign ID. Use GET /campaigns to list available campaigns.

Export FAILED — Date range too large

{ "exportId": "exp_1a2b3c4d", "status": "FAILED", "error": "Date range too large. Maximum 90 days." }

Solution: Reduce the range to a maximum of 90 days. For longer periods, split into multiple exports.

Next steps

References