REST API v1 · Resource
Sending
Send texts, templates, media and interactive messages, and upload files to send by media id.
API reference · Sending
Endpoints
Paths are relative to https://fliok.com/api/v1. Each endpoint names the scope and the lowest key role it needs; a key without them gets 403 (see Authentication).
Sending
2- POST
/sendSend a text, template, media or interactive messageScopemessages:send· agent role or higherNeeds an API key - POST
/mediaUpload a document/image (up to 16 MB) to Meta and get a reusable media idScopemessages:send· agent role or higherNeeds an API key
Request bodies
What these endpoints take, field by field. A body that doesn’t match answers 400 naming the field.
POST /send
JSON body. Send an `Idempotency-Key` header (1–255 characters, remembered for 24 hours) and a retry of the same request returns the first answer instead of sending twice; the same key with a different body is refused (422 idempotency_key_reused).
| Field | Type | What it is |
|---|---|---|
torequired | string | The customer’s number in E.164, with or without “+”. A number without a country code takes your sending number’s. For a customer WhatsApp shares no number for, pass the phone we report for them ("wa:<user id>") as it is — or leave `to` out and use `recipient`. |
recipient | string | Instead of `to`: the customer’s WhatsApp user id (the `userId` on webhooks and contacts, like "IN.21483648909127364650"), for a customer WhatsApp shares no phone number for. `to` wins when both are sent. |
typerequired | string | text, template, image, video, audio, document, interactive, reaction, location, sticker or contacts. |
text | string | The message, for type "text" (required then, never empty). Needs an open 24-hour window. |
payload | object | For every other type: Meta’s message object, { "type": "<type>", "<type>": { … } } — e.g. { "type": "document", "document": { "id": "<media id>", "filename": "invoice.pdf" } }. |
payload.template.variables | array | Template shortcut: the body’s {{1}}, {{2}}… in order. Fliok builds Meta’s components from the approved template, so you can leave components out. |
payload.template.headerMedia | object | Template shortcut: { "id": "<media id>" } or { "link": "https://…" } (plus "filename" for a document) for an image, video or document header. |
payload.template.headerText · couponCode · offerExpiresAt | various | Template shortcut: a text header’s variables, a coupon-code button’s code, a limited-time offer’s end (ISO time). |
phoneNumberId | uuid | Which of your numbers sends (GET /phone-numbers). Default: your first active number. |
replyTo | string | A wamid to reply to: the message shows as a reply to it. |
Returns 200 { "ok": true, "messageId": "<uuid>" } — queued, not yet delivered. Refusals: 422 outside_24h_window, 422 needs_phone_number (a verification-code template to a customer with no phone number — WhatsApp only delivers those to a number), 409 contact_opted_out, 402 plan_limit_reached (a new number past your contact limit) or quota_exceeded, 400 invalid_template_parameters / template_header_media_required. A refused send writes nothing: no contact, no conversation, no contact.created webhook.
POST /media
JSON body, up to 16 MB of file. Upload once, send the id as many times as you like for about 30 days. A workspace can have 4 uploads running at once, 2 of them over 10 MB (429 uploads_in_progress beyond, with Retry-After).
| Field | Type | What it is |
|---|---|---|
fileBase64required | string | The file’s bytes, base64-encoded, without a "data:" prefix. |
mimeType | string | For example application/pdf, image/jpeg, video/mp4. Default application/pdf. |
filename | string | Up to 200 characters. Default document.pdf. |
phoneNumberId | uuid | The number that will send it. Default: your first active number. |
Returns 200 { "id": "<Meta media id>" }
Examples
# Send a text message (needs an open 24h window). The Idempotency-Key makes a retry
# safe: the same key within 24 hours answers with the first result instead of sending twice.
curl -X POST https://fliok.com/api/v1/send \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-12345-shipped" \
-d '{
"to": "+919876543210",
"type": "text",
"text": "Hello! Your order #12345 has been shipped."
}'
# Send a template (the only way to open a NEW conversation)
curl -X POST https://fliok.com/api/v1/send \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+919876543210",
"type": "template",
"payload": {
"type": "template",
"template": {
"name": "order_confirmation",
"language": { "code": "en" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Rahul" },
{ "type": "text", "text": "ORD-12345" }
]
}
]
}
}
}'
# The same template, letting Fliok build the components from the approved
# template: variables in order, and the header's media when it has one
curl -X POST https://fliok.com/api/v1/send \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+919876543210",
"type": "template",
"payload": {
"type": "template",
"template": {
"name": "order_confirmation",
"language": { "code": "en" },
"variables": ["Rahul", "ORD-12345"]
}
}
}'
# Upload a document, then send it by media id
curl -X POST https://fliok.com/api/v1/media \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"fileBase64": "JVBERi0xLjQK...",
"mimeType": "application/pdf",
"filename": "invoice.pdf"
}'
# -> { "id": "1234567890" } (reusable for ~30 days){
"ok": true,
"messageId": "4f6c1e2a-91d3-4a77-b0c2-5f1e8d9a3b44"
}
// The send is queued, not yet delivered. Poll GET /messages/{id}
// or subscribe to the message.status webhook for the outcome.Message types and templates
Session Messages (Free-form)
24h windowWhen a customer messages you first, a 24-hour window opens. During this window you can send:
- Text (
type: "text") - Images, video, audio, documents, stickers — upload via
/media - Interactive buttons and lists (
type: "interactive") - Location, contacts and reactions
No template approval needed. Outside the window, /send returns 422 outside_24h_window.
Template Messages (Pre-approved)
Any timeTo message a customer outside the 24h window (notifications, broadcasts, alerts), you must use Meta-approved templates:
- Create it in the dashboard, or POST
/templates - Submitted straight to Meta on the Cloud API — no reseller in between
- Once approved, send it with
/sendusingtype: "template" - Poll
GET /templatesfor the live approval status
3 categories: Marketing, Utility, Authentication. Meta prices and reviews each differently, and may recategorise on submission.
Marketing templates must include opt-out text (e.g., "Reply STOP to unsubscribe"). Templates with spammy language, excessive caps, or URLs in body text will be rejected by Meta.
Rate limits
The buckets these endpoints use. Burst is how many requests you can make back-to-back from a full bucket; sustained is how fast it refills.
| Bucket | Endpoints | Burst | Sustained |
|---|---|---|---|
| Send | /send | 200 | 50 / sec |
| Media upload | /media | 200 | 50 / sec |
Every limit, the RateLimit-* headers and what to do on a 429: Rate limits.