Skip to main content

UC-030 — Complete Template Lifecycle (Test, Campaign, Analysis)

FieldValue
IDUC-030
GoalManage the full lifecycle of a WhatsApp template: creation, approval, test, campaign and analysis
ChannelWhatsApp
Complexity⭐⭐⭐ Advanced
Estimated time30 minutes (excluding Meta approval times)
APIs involvedPOST /api/partner-gateway/v1/whatsapp/templates, POST /api/message-server/whatsapp/send, POST /api/partner-gateway/v1/campaigns, PUT /api/partner-gateway/v1/campaigns/{id}/confirm, POST /api/partner-gateway/v1/exports/delivery-reports, GET /api/partner-gateway/v1/exports/{exportId}

Real-world scenarios

  • FashionOutlet — New promotion launch: The marketing team creates a WhatsApp template for the summer sales, tests it in simulation, then uses it for a campaign to 20,000 VIP customers. After the campaign concludes, they export results to calculate ROI.
  • ClinicaSalute — New service template onboarding: The clinic creates a template to promote a new telemedicine service. After Meta approval, they test it on a small group, verify the visual rendering and then launch the campaign.
  • BancaAdriatica — Template A/B testing: The CRM team creates two template variants for a personal loan promotion. They test both on reduced samples, compare delivery and read rates, then use the winning variant for the bulk send.

:::info Composite use case This UC combines the flows from UC-013 — WhatsApp Template Workflow, UC-006 — Bulk Campaign and UC-011 — Export Delivery Reports into a complete lifecycle. :::

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. :::

Lifecycle flow

The diagram illustrates the complete cycle: from template creation to campaign, through to results analysis for iteration and improvement.

Step 1 — Create the WhatsApp template

Submit the template to Meta for approval:

curl -X POST "https://lora-api.agiletelecom.com/api/partner-gateway/v1/whatsapp/templates" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "promo_estate_2026",
"language": "it",
"category": "MARKETING",
"components": [
{ "type": "HEADER", "format": "IMAGE",
"example": { "header_handle": ["https://fashionoutlet.it/media/saldi-estate-2026.jpg"] } },
{ "type": "BODY",
"text": "Ciao {{1}}! Saldi estivi FashionOutlet: fino al {{2}}% di sconto. Offerta valida fino al {{3}}!",
"example": { "body_text": [["Marco", "40", "30 giugno"]] } },
{ "type": "FOOTER", "text": "FashionOutlet - Moda per tutti" },
{ "type": "BUTTONS", "buttons": [
{ "type": "URL", "text": "Scopri le offerte", "url": "https://fashionoutlet.it/saldi?ref={{1}}", "example": ["campaign_estate_2026"] },
{ "type": "QUICK_REPLY", "text": "Non mi interessa" }
]}
]
}'

Response — Template submitted

{ "templateId": "tpl_8a9b0c1d-2e3f-4a5b-6c7d-8e9f0a1b2c3d", "name": "promo_estate_2026", "status": "PENDING", "category": "MARKETING" }

:::info Meta approval times Template approval by Meta typically takes from a few hours to 24 hours. MARKETING templates take longer than UTILITY or AUTHENTICATION ones. Configure a webhook to receive the approval or rejection notification. :::

Step 2 — Wait for approval and check the status

Periodically check the template status:

curl -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/whatsapp/templates/tpl_8a9b0c1d-2e3f-4a5b-6c7d-8e9f0a1b2c3d" \
-H "X-Api-Key: YOUR_API_KEY"

Response — Template approved

{ "templateId": "tpl_8a9b0c1d-2e3f-4a5b-6c7d-8e9f0a1b2c3d", "status": "APPROVED", "qualityScore": "GREEN", "approvedAt": "2026-04-09T18:30:00+02:00" }
Behind the scenes — Quality Score and limits
  1. Quality Score: GREEN/YELLOW/RED based on user interactions. A low score limits volume.
  2. Sending tier: From tier 1 (1K conversations/day) to tier 4 (unlimited), grows with quality.
  3. Rejection: Common reasons -- aggressive language, missing opt-out, improper placeholders. Edit and resubmit.

Step 3 — Test the template in simulation

Before the campaign, verify the template with a simulation send ("simulation": true):

curl -X POST https://lora-api.agiletelecom.com/api/message-server/whatsapp/send \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"destination": "+393471234567",
"sender": "+393801234567",
"simulation": true,
"content": {
"templateName": "promo_estate_2026",
"language": "it",
"components": [
{ "type": "body", "parameters": [
{ "type": "text", "text": "Marco" },
{ "type": "text", "text": "40" },
{ "type": "text", "text": "30 giugno" }
]}
]
}
}'

Response — Simulation successful

{
"messageId": "e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a0b",
"simulation": true,
"results": { "whatsapp": { "accepted": true, "reasons": [] } }
}

:::tip Real test send After the simulation, send a real test to your personal number (without "simulation": true) to verify the visual rendering on the device. :::

Step 4 — Create and launch the campaign

With the template tested, create the campaign and confirm the send:

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": "Saldi Estate 2026 - WhatsApp VIP",
"channel": "WHATSAPP",
"sender": "+393801234567",
"contactListId": "lst_clienti_vip_2026",
"whatsappTemplate": {
"templateName": "promo_estate_2026",
"language": "it",
"bodyParameters": ["firstName", "discountPercent", "expiryDate"]
}
}'

Response

{ "id": "cmp_2c3d4e5f-6a7b-8c9d-0e1f-2a3b4c5d6e7f", "status": "DRAFT", "totalContacts": 20150 }

Confirm the send with PUT /campaigns/{id}/confirm.

Step 5 — Monitor and export

Monitor with GET /campaigns/{id}/stats until status: "COMPLETED", then export the report with POST /exports/delivery-reports (see UC-029 for the full export flow).

{
"campaignId": "cmp_2c3d4e5f-6a7b-8c9d-0e1f-2a3b4c5d6e7f",
"status": "COMPLETED",
"stats": {
"totalMessages": 20150, "delivered": 18935, "read": 12480,
"failed": 695, "deliveryRate": 93.97, "readRate": 65.91,
"totalCost": 1612.00
}
}

Expected result

StepActionResult
1POST /whatsapp/templatesTemplate submitted, status: "PENDING"
2GET /whatsapp/templates/{id}status: "APPROVED", qualityScore: "GREEN"
3POST /whatsapp/send (simulation)simulation: true, accepted: true
4POST /campaigns + PUT /confirmCampaign created and confirmed
5GET /campaigns/{id}/stats + exportdeliveryRate: 93.97%, downloadable CSV

Complete end-to-end example

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

# 1. Create template
TPL_ID=$(curl -s -X POST "${PG}/whatsapp/templates" -H "X-Api-Key: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{"name":"promo_estate_2026","language":"it","category":"MARKETING","components":[{"type":"BODY","text":"Ciao {{1}}! Saldi: -{{2}}% fino al {{3}}!"}]}' | jq -r '.templateId')

# 2. Wait for approval
while true; do
S=$(curl -s "${PG}/whatsapp/templates/${TPL_ID}" -H "X-Api-Key: ${API_KEY}" | jq -r '.status')
[[ "$S" == "APPROVED" ]] && break; [[ "$S" == "REJECTED" ]] && exit 1; sleep 300
done

# 3. Simulation test
curl -s -X POST "${MS}/whatsapp/send" -H "Content-Type: application/json" -H "X-Api-Key: ${API_KEY}" \
-d '{"destination":"+393471234567","sender":"+393801234567","simulation":true,"content":{"templateName":"promo_estate_2026","language":"it","components":[{"type":"body","parameters":[{"type":"text","text":"Marco"},{"type":"text","text":"40"},{"type":"text","text":"30 giugno"}]}]}}' | jq .

# 4. Campaign → 5. Monitor → Export (see UC-029 for the full export flow)
CMP_ID=$(curl -s -X POST "${PG}/campaigns" -H "X-Api-Key: ${API_KEY}" -H "Content-Type: application/json" \
-d '{"name":"Saldi Estate 2026","channel":"WHATSAPP","sender":"+393801234567","contactListId":"lst_clienti_vip_2026","whatsappTemplate":{"templateName":"promo_estate_2026","language":"it","bodyParameters":["firstName","discountPercent","expiryDate"]}}' | jq -r '.id')
curl -s -X PUT "${PG}/campaigns/${CMP_ID}/confirm" -H "X-Api-Key: ${API_KEY}" > /dev/null

Variants

A/B Testing with two templates

Create two variants (e.g., urgent tone vs friendly), wait for approval of both, then launch two campaigns on different segments of the same list. Compare deliveryRate and readRate in their respective reports.

Template with tracked opt-out button

The Quick Reply "Non mi interessa" button generates an INBOUND webhook with the button text, which you can use to update the contact's preferences (see UC-028).

Common errors

Template rejected by Meta

{ "templateId": "tpl_8a9b0c1d", "status": "REJECTED", "rejectionReason": "Template content violates WhatsApp Commerce Policy" }

Solution: Common reasons: aggressive language, unrealistic promises, missing sender identity. Edit and resubmit.

Campaign with unapproved template

{ "status": "fail", "data": { "error": "Template 'promo_estate_2026' is not in APPROVED status" } }

Solution: Only templates with status: "APPROVED" can be used in campaigns. Check the status before creating the campaign.

Next steps

References