Developers

Order updates API

Send a customer an order update on WhatsApp from any system — a custom checkout, an ERP, a courier integration, Zapier. Three endpoints, one workspace key. Each update is an approved utility template on your own WhatsApp Business account; Meta bills your account per message and Tendabot adds nothing. Shopify and WooCommerce stores get all of this without writing code — see WhatsApp on Tendabot.

Before the first call

Four things, five minutes.

Endpoint 1 · send an update

POST /api/v1/orders/events

Records the order, then queues the update. It sends as soon as the template is approved, or after the wait you set for that event (confirmed waits two minutes so a payment seconds later folds into one message).

Request
curl -X POST https://platform.tendabot.com/api/v1/orders/events \
  -H "Authorization: Bearer tbk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: acme:5512:shipped:1" \
  -d '{
    "botId": "YOUR_BOT_ID",
    "event": "order.shipped",
    "order": {
      "externalId": "5512",
      "number": "4821",
      "status": "shipped",
      "total": "68.00",
      "currency": "GBP",
      "paymentMethod": "card",
      "orderUrl": "https://shop.example/orders/4821",
      "customer": { "name": "Sara Khan", "phone": "+447700900123", "city": "Leeds", "country": "GB" },
      "items": [{ "name": "10 ml bottle", "qty": 2 }],
      "tracking": { "carrier": "Royal Mail", "number": "RM482177301GB", "url": "https://www.royalmail.com/track-your-item#/tracking-results/RM482177301GB" },
      "occurredAt": "2026-09-05T10:12:00Z"
    }
  }'
Responses
201 { "status": "queued",    "event": "shipped", "eventId": "…", "scheduledAt": "2026-09-05T10:12:01.000Z" }
200 { "status": "duplicate", "event": "shipped", "reason": "already recorded for this order" }
200 { "status": "skipped",   "event": "shipped", "eventId": "…", "reason": "no usable phone number on the order" }
200 { "status": "off",       "event": "shipped", "reason": "order updates are switched off for this bot — enable them under Automations" }
401 { "error": "Send your workspace API key as \"Authorization: Bearer tbk_…\"." }
402 { "error": "This workspace has sent its 1,000 order updates for the month — upgrade in Billing for more." }
422 { "error": "order.customer.phone … / order.orderUrl must be an http(s) URL", "field": "order.orderUrl" }
Events

Nine updates, one template each.

eventSend it whenThe customer gets
placedThe order is inThanks for your order #… Total … · View order
paidPayment landed on an unpaid orderPayment of … received for order #… · View order
cod_confirmA cash-on-delivery order is inPlease confirm your cash-on-delivery order #… · Confirm order / Cancel order
payment_pendingStill unpaid after your waitOrder #… is waiting for payment · Pay now
shippedA tracking number existsOrder #… is on its way with … Tracking … · Track parcel
completedComplete, no tracking numberOrder #… is complete and on its way
deliveredThe courier delivered itOrder #… has been delivered
cancelledCancelled or refundedOrder #… has been cancelled
feedbackAfter deliveryHow was your order #…? · Great / Okay / Not good

All nine are utility templates: no promotional wording, so they stay on Meta's cheapest rate. Each can be switched off per bot under Automations.

Endpoint 2 · keep an order current

PUT /api/v1/orders/{externalId}

Records or updates an order without messaging anyone, so the AI can answer “where is my order” for a store that sends no updates, or ahead of the events that will.

Request
curl -X PUT https://platform.tendabot.com/api/v1/orders/5512 \
  -H "Authorization: Bearer tbk_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{ "botId": "YOUR_BOT_ID", "order": { "number": "4821", "status": "processing", "total": "68.00", "currency": "GBP",
        "customer": { "name": "Sara Khan", "phone": "+447700900123" } } }'

200 { "ok": true, "storeOrderId": "…", "reachableOnWhatsApp": true }
Endpoint 3 · the timeline

GET /api/v1/orders/{externalId}/events

Every update decided for the order: sent, delivered, read, replied, or skipped with the reason. Works with a read-only key. Add &source=wordpress for orders that arrived through the plugin.

Request
curl "https://platform.tendabot.com/api/v1/orders/5512/events?botId=YOUR_BOT_ID" -H "Authorization: Bearer tbk_YOUR_KEY"

200 {
  "order":  { "externalId": "5512", "number": "4821", "status": "shipped", "codDecision": null, "updatedAt": "…" },
  "events": [
    { "id": "…", "event": "shipped", "status": "read", "template": "tb_order_shipped", "sentAt": "…", "deliveredAt": "…", "readAt": "…" },
    { "id": "…", "event": "placed",  "status": "skipped", "reason": "older than 24 hours when it arrived" }
  ]
}
Webhook · what the customer tapped

order.replied

A tap on Confirm order, Cancel order, or a feedback button reaches you here. Add a webhook under Bot → Settings → Webhooks and tick order.replied; it is signed with your webhook secret like every Tendabot webhook. WooCommerce stores also get the decision written onto the order by the plugin.

Payload
{
  "event": "order.replied",
  "botId": "…", "eventId": "…", "externalId": "5512", "orderNumber": "4821", "source": "api",
  "decision": "confirm",            // confirm | cancel | feedback
  "score": 3,                       // feedback only: 1 not good · 2 okay · 3 great
  "customerWaId": "447700900123",
  "at": "2026-09-05T10:20:31.000Z"
}
Limits

What the plan and Meta allow.

Ready when you are

Your first agent, answering in five minutes.