Send
POST /v1/send — deliver a message to one recipient across WhatsApp, WABA, Telegram, and email.
Endpoint
POST https://api.kirisan.com/v1/send
Authorization: Bearer YOUR_ACCOUNT_TOKEN
Content-Type: application/json Sends to one recipient per request. For large batches, use Send → Campaign in the dashboard or call this endpoint once per recipient from your app.
Request body
| Field | Required | Description |
|---|---|---|
keys | Yes | Channel tokens — whatsapp, telegram, waba, email |
content | Yes | Per-channel message — template ID or inline message |
target | Yes | Recipient address per channel + optional variables |
context | No | Scheduling and send behaviour |
keys
{
"keys": {
"whatsapp": {
"token": "DEVICE_TOKEN",
"fallback": false,
"fallback_sequence": 0
},
"email": {
"token": "SENDER_TOKEN",
"fallback": true,
"fallback_sequence": 1
}
}
} Include a key for every channel you intend to send on. See Authentication for where to copy tokens.
content
Each channel entry uses either a saved template or an inline message — not both.
Template reference (recommended — same as Send → Send):
{
"content": {
"whatsapp": { "template": 42 },
"email": { "template": 17 }
}
} Inline message (WhatsApp, Telegram, WABA only — email must use a template):
{
"content": {
"whatsapp": {
"message": {
"type": "text",
"message": "Hello {{name}}, your order is ready."
}
}
}
} message.type | Channels | Notes |
|---|---|---|
text | WhatsApp, Telegram, WABA | Plain text (WABA: approved session rules apply) |
image, video, document | WhatsApp, Telegram, WABA | Requires richContext.fileUrl or richContext.fileId |
location | WhatsApp, Telegram | Requires richContext.location — message text is ignored |
interactive | Telegram, WABA | Buttons or list — see richContext below |
message.richContext (optional):
| Field | Purpose |
|---|---|
fileUrl | Public HTTPS URL to an attachment |
fileId | ID of a file uploaded to Resources → Files |
fileName | Display filename — Kirisan may append the detected extension |
footer | Footer text (where supported) |
location | { "lat", "lng", "name", "address" } for location messages |
buttons | Array of button rows (Telegram inline keyboard / WABA interactive) |
listMessage | WABA list message object |
target
{
"target": {
"whatsapp": "6281234567890",
"email": "customer@example.com",
"telegram": "123456789",
"waba": "6281234567890",
"variables": {
"name": "Alex",
"order_id": "A-1001"
}
}
} | Field | Format |
|---|---|
whatsapp, waba | Phone with country code (digits, no + required) |
telegram | Chat ID |
email | Valid email address |
variables | Replaces {{placeholders}} in templates and inline messages before send |
Omit channel fields you are not sending on. Each active channel in content needs a matching target (unless filtered by context.behaviour.channel).
context
{
"context": {
"timing": {
"schedule": 1735689600
},
"behaviour": {
"channel": "all"
}
}
} | Field | Meaning |
|---|---|
timing.schedule | Unix timestamp (seconds) — queue for future delivery. Omit or set null to send now. Past times are rejected. |
behaviour.channel | "all" (default) — send every channel that has a key and content. Or one of whatsapp, telegram, waba, email to restrict to a single channel. |
When scheduled, the response includes "scheduled": true and each channel shows "scheduled": true instead of delivering immediately.
Examples
WhatsApp text with variables
{
"keys": {
"whatsapp": { "token": "DEVICE_TOKEN" }
},
"content": {
"whatsapp": {
"message": {
"type": "text",
"message": "Hi {{name}}, thanks for your order."
}
}
},
"target": {
"whatsapp": "6281234567890",
"variables": { "name": "Alex" }
}
} Saved template (multi-channel)
{
"keys": {
"whatsapp": { "token": "DEVICE_TOKEN" },
"email": { "token": "SENDER_TOKEN" }
},
"content": {
"whatsapp": { "template": 42 },
"email": { "template": 17 }
},
"target": {
"whatsapp": "6281234567890",
"email": "alex@example.com",
"variables": { "name": "Alex" }
}
} Scheduled send
{
"keys": { "telegram": { "token": "BOT_TOKEN" } },
"content": { "telegram": { "template": 8 } },
"target": { "telegram": "123456789" },
"context": {
"timing": { "schedule": 1735689600 }
}
} WhatsApp image with URL
{
"keys": { "whatsapp": { "token": "DEVICE_TOKEN" } },
"content": {
"whatsapp": {
"message": {
"type": "image",
"message": "Your receipt is attached.",
"richContext": {
"fileUrl": "https://cdn.example.com/receipt.jpg",
"fileName": "receipt"
}
}
}
},
"target": {
"whatsapp": "6281234567890"
}
} Fallback cascade
When channel keys use fallback: true, Kirisan tries tiers in order:
- Primary — all keys with no fallback (sent together).
- Fallback 1 — keys with
fallback_sequence: 1(parallel within the tier). - Fallback 2 — keys with
fallback_sequence: 2, and so on.
As soon as any channel in a tier succeeds, later tiers are skipped. This matches Use as fallback and Sequence on Send → Send. See Send messages for a dashboard walkthrough.
Failed channels in an earlier tier still appear under "channels" with "reason". A successful fallback channel may include "fallback": true.
Response
Immediate send:
{
"status": true,
"channels": {
"whatsapp": {
"status": true,
"processing_time": "142ms"
}
}
} Partial failure:
{
"status": false,
"channels": {
"whatsapp": {
"status": false,
"reason": "Device disconnected",
"processing_time": "89ms"
},
"email": {
"status": true,
"fallback": true,
"processing_time": "891ms"
}
}
} Scheduled:
{
"status": true,
"scheduled": true,
"channels": {
"telegram": { "status": true, "scheduled": true }
}
} Top-level status | Meaning |
|---|---|
true | At least one channel delivered or was scheduled |
false | Every attempted channel failed, or validation blocked the request |
Read "reason" on the root for validation errors. Read "channels.<name>.reason" for delivery failures. See Errors.
Channel notes
| Channel | Inline message | Templates |
|---|---|---|
| Yes — text, media, location, interactive | Yes — must be approved and active | |
| Telegram | Yes | Yes |
| WABA | Yes — text, media, interactive (Meta rules apply) | Yes — WABA templates from Meta; manage in Channel → WABA → Templates |
No — use content.email.template only | Yes — create in Channel → Email → Templates |
Templates referenced by ID must be Approved and Active in the dashboard. Copy the ID from Channel → channel → Templates, or use inline message content instead.
Related
- Authentication — account token and channel keys
- Errors — HTTP codes and common reasons
- Send messages — same request shape from the UI
- WhatsApp templates — create templates and copy IDs for send