Skip to content

Send

POST /v1/send — deliver a message to one recipient across WhatsApp, WABA, Telegram, and email.

4 min read

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

FieldRequiredDescription
keysYesChannel tokens — whatsapp, telegram, waba, email
contentYesPer-channel message — template ID or inline message
targetYesRecipient address per channel + optional variables
contextNoScheduling 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.typeChannelsNotes
textWhatsApp, Telegram, WABAPlain text (WABA: approved session rules apply)
image, video, documentWhatsApp, Telegram, WABARequires richContext.fileUrl or richContext.fileId
locationWhatsApp, TelegramRequires richContext.locationmessage text is ignored
interactiveTelegram, WABAButtons or list — see richContext below

message.richContext (optional):

FieldPurpose
fileUrlPublic HTTPS URL to an attachment
fileIdID of a file uploaded to Resources → Files
fileNameDisplay filename — Kirisan may append the detected extension
footerFooter text (where supported)
location{ "lat", "lng", "name", "address" } for location messages
buttonsArray of button rows (Telegram inline keyboard / WABA interactive)
listMessageWABA list message object

target

{
  "target": {
    "whatsapp": "6281234567890",
    "email": "customer@example.com",
    "telegram": "123456789",
    "waba": "6281234567890",
    "variables": {
      "name": "Alex",
      "order_id": "A-1001"
    }
  }
}
FieldFormat
whatsapp, wabaPhone with country code (digits, no + required)
telegramChat ID
emailValid email address
variablesReplaces {{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"
    }
  }
}
FieldMeaning
timing.scheduleUnix 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:

  1. Primary — all keys with no fallback (sent together).
  2. Fallback 1 — keys with fallback_sequence: 1 (parallel within the tier).
  3. 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 statusMeaning
trueAt least one channel delivered or was scheduled
falseEvery 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

ChannelInline messageTemplates
WhatsAppYes — text, media, location, interactiveYes — must be approved and active
TelegramYesYes
WABAYes — text, media, interactive (Meta rules apply)Yes — WABA templates from Meta; manage in Channel → WABA → Templates
EmailNo — use content.email.template onlyYes — 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.

Last updated: July 2, 2026
Was this page helpful?