Home / API
API

Send from whatever you already run.

Your ERP, your billing software, a spreadsheet, a form on your website. Three things to know and you are sending.

One

Get a key.

Settings → API. It is shown once and never again — if you lose it, make another and the old one stops working immediately.

# Every request carries it as a bearer token.
Authorization: Bearer afo_live_8f2k9m4x…

Anybody with this key can send messages as your business, so it belongs on a server rather than in a page somebody can view the source of.

Two

Send a message.

POST /api/v1/messages Send to one number

A template if they have not written to you in the last 24 hours, and ordinary text if they have. Sending text into a shut window comes back as an error rather than silently going nowhere — which is the one thing worth knowing before you build against this.

{
  "to": "919876543210",
  "template": "order_shipped",
  "language": "en_US",
  "variables": ["Ravi", "#1042", "DL8829174421"]
}

Comes back with an id you can look up later, and the status the message is in.

POST /api/v1/messages/text Free text, inside the window
{ "to": "919876543210", "body": "Rate list attached." }
GET /api/v1/messages/:id Did it arrive

queued, sent, delivered, read or failed — with the reason, if it failed.

Three

Be told when something happens.

Give us a URL and we post to it. Message received, message sent, new contact, conversation assigned.

// what arrives at your URL
{
  "event": "message.received",
  "at": "2026-08-26T09:04:11Z",
  "contact": { "name": "Rajesh Sharma", "phone": "919876543210" },
  "message": { "type": "text", "body": "Rate bhej do" }
}
And the other way

A URL anything can post a lead to.

No key needed — the URL itself is the credential, which is why it is long and can be replaced. Point a website form, a Zap, or a portal at it.

POST https://afosales.com/api/leads/in/a7f3k9dQ2p

{ "name": "Rajesh", "phone": "9876543210", "subject": "MS pipes" }

A contact is made, a reply goes out, and somebody is given it — the same as a lead from any portal. Only the phone number is required.

Worth knowing

The limits, and why they are there.

Sixty requests a minute

Enough for any ordinary use. A queue is better than a burst anyway — WhatsApp rate-limits at its end too, and a burst there costs more than a queue here.

Templates cannot be created through the API

Meta has to approve each one, and approval takes hours. Creating them in the app is the only way that gives you the rejection reason when it comes back.

The 24-hour window applies here too

It is WhatsApp's rule, not ours. Text to somebody who has not written in a day returns an error rather than pretending to send — which catches it in your logs rather than in a customer complaint a week later.