Loods API v1

Docs · API v1

Sending

Loods sends a chat message only when you ask for exactly that message, from a business number you connected. It never sends on its own, and it never sends mail.

Send a message

POST /v1/whatsapp/messages sends from a channel's number to to, in E.164. There are three ways to ask:

  • text, with up to three reply buttons, when the customer wrote to you in the last 24 hours. Up to 4096 characters; a button title is up to 20.
  • template, an approved template with its parameters, when they didn't.
  • Both. The text goes, and if the platform says the 24-hour window is shut, the template goes instead, once.

shape in the answer says what really went out: text, template or flow. Keep the id: the whatsapp.status events about this message carry it.

POST/v1/whatsapp/messages
curl https://loods.dev/v1/whatsapp/messages \
  -H "Authorization: Bearer $LOODS_KEY" \
  -H "Idempotency-Key: act-812" \
  -H "Content-Type: application/json" -d '{
    "channel": "whatsapp-main",
    "to": "+31623456789",
    "text": "Hoi Marieke, …",
    "template": {
      "name": "mail_notice",
      "language": "nl",
      "parameters": ["Marieke", "Voorbeeld", "uw offerte"]
    }
  }'
201 Created
{
  "id": "wamid.HBgLMzE2MjM0NTY3ODkVAgARGBI",
  "shape": "template",
  "channel": { "id": "ch_01k5twa3c4d5e6f7g8h9j0k1m2", "ref": "whatsapp-main", "type": "whatsapp" },
  "to": "+31623456789"
}

Idempotency

Every send needs an Idempotency-Key header, up to 255 characters. Use the id of the action a person confirmed, so a retry can never send twice. Loods remembers a key and its answer for a day.

You sendLoods answers
The same key with the same bodyThe first answer again. Nothing is sent.
The same key with another body409 idempotency_key_reused
The same key while the first is still being handled409 request_in_progress
No key400 idempotency_key_required

A key keeps its answer, except when nothing was sent: the platform refused the message, or Loods itself failed with a 500 or 503. Then the key is free, and the same request with the same key sends again.

So a retry with the same key is always safe. If it answers the same 502 with the header Idempotent-Replayed: true, the first attempt kept the key, because the message may have gone out: the platform couldn't be reached, or failed on its own side. Wait for a whatsapp.status event before you send it under a new key.

Forms

A template can carry a form button. Give template.flow a token of your own, and optional data to start the form with.

When the customer completes the form, it arrives as a whatsapp.received event with flow.token set to your token and the answers in flow.response.

POST/v1/whatsapp/messagesForm
{
  "channel": "whatsapp-main",
  "to": "+31623456789",
  "template": {
    "name": "quote_confirm",
    "language": "nl",
    "parameters": ["Marieke"],
    "flow": { "token": "tok-abc", "data": { "quote": "Q-2026-118" } }
  }
}

When it fails

If the platform refuses the message, the answer is a 502 with the code whatsapp_error. meta_code holds the platform's own error code, when it gave one. Nothing was sent, so fix the request and send it again with the same Idempotency-Key.

A message the platform accepted can still fail later. That arrives as a whatsapp.status event with "status": "failed".

Media

GET /v1/whatsapp/media/{media_id}?channel={ref} streams the bytes of a photo, video, document or voice note from a whatsapp.received event, under the type the platform gives.

Loods keeps none of it. Media ids expire at the platform after about 30 days, so save what you need.

GET/v1/whatsapp/media/{media_id}
curl "https://loods.dev/v1/whatsapp/media/1234567890123456?channel=whatsapp-main" \
  -H "Authorization: Bearer $LOODS_KEY" -o achtergevel.jpg