Skip to content
Pinnaki

Developers · Developer API

One endpoint to send a template.

Order updates and one-time passcodes, sent from your own systems on your WhatsApp number. One HTTPS request with a JSON body; delivery comes back to you by webhook.

The Developer API is on Professional (₹3,499 a month + GST, 14-day trial) and above. Each message has one price for its category, the same on every paid plan.

Send a template · curl
# PINNAKI_API = Pinnaki's API base URLcurl -X POST "$PINNAKI_API/mass-messaging/api/v1/messages" \  -H "Authorization: Bearer $PINNAKI_KEY" \  -H "Content-Type: application/json" \  -H "Idempotency-Key: order-4821-shipped" \  -d '{    "to": "919800000000",    "template_name": "order_shipped",    "language_code": "en",    "variables": ["Asha", "#4821", "Thursday"]  }'

The Developer API is on Professional (₹3,499 a month + GST, 14-day trial) and above. Each message has one price for its category, the same on every paid plan.

01The request

What goes in the body.

POST /mass-messaging/api/v1/messages with your key as a Bearer token. The template must be approved by Meta and be a utility or authentication template.

Request body fields
FieldTypeNotes
tostringThe recipient in full international format, with the country code. Up to 32 characters.
template_namestringAn approved utility or authentication template in your workspace.
variablesstring[]Values for {{1}}, {{2}} … in order. Up to 50, each up to 1,024 characters.
named_variablesobjectValues for named parameters such as {{first_name}}. Up to 50 keys in lowercase letters, digits and underscores.
media_urlstringA link to the header image, video or document, if the template has one.
language_codestringThe template language to use, such as en. Optional.
disable_loggingbooleanLeave this message out of the stored API logs. Optional.

An accepted request returns a message_id and the status ACCEPTED: the message is queued for sending. What happens next arrives by webhook.

Response · 201
{  "success": true,  "message_id": "msg_3f6c2a9e-8d1b-4c57-9a0e-5b7d1c2e4f60",  "status": "ACCEPTED"}

02Errors

When it says no, it says why.

Errors come back with a standard HTTP status and a message that names the problem.

HTTP status codes returned by the Developer API
StatusWhen
400The body is invalid, the template isn’t approved in that language, or the number isn’t in international format.
401The key is missing, wrong or expired, or the signature is missing, stale, wrong or already used.
402The wallet balance doesn’t cover the message.
403The IP address or the template isn’t allowed for this key, the template is a marketing template, or the workspace’s plan or WhatsApp channel is inactive.
409The WhatsApp number is disconnected, or a request with the same Idempotency-Key is still in progress.
422An Idempotency-Key was reused with a different body.
429The key’s requests-per-second limit was exceeded.

03Signing

Sign the request, if you want proof it came from you.

Turn on “Enforce Cryptographic Signature” for a key, and every request must carry a timestamp and an HMAC of its body.

Send X-SaaS-Timestamp (seconds or milliseconds) and X-SaaS-Signature: the hex HMAC-SHA256 of the timestamp, a dot and the raw body, keyed with your API key. A sha256= prefix is accepted.

Requests older than five minutes are refused, and each signature is accepted once. A request that carries an Idempotency-Key may be retried with the same signature, inside the same five minutes.

Sign a request · Node.js
// Node.js: sign the exact bytes you sendimport { createHmac } from "node:crypto"; const body = JSON.stringify(payload);const timestamp = Math.floor(Date.now() / 1000).toString();const signature = createHmac("sha256", process.env.PINNAKI_KEY)  .update(timestamp + "." + body)  .digest("hex"); // headers: "X-SaaS-Timestamp": timestamp//          "X-SaaS-Signature": "sha256=" + signature

04Retries

Retry safely with an Idempotency-Key.

Networks fail. Send the same Idempotency-Key with a retry and the message goes out once.

Put any string up to 128 characters in Idempotency-Key (or X-Idempotency-Key), such as your order ID and the event. For 24 hours, the same key with the same body returns the original response instead of sending again.

The same key with a different body is refused with 422. While the first request is still being handled, a second one gets 409.

05Keys

Each key carries its own limits.

Set the rules once on the key, and every request made with it follows them.

IP allowlist
Accept requests only from the addresses or ranges you list, IPv4 or IPv6.
Rate limit
A ceiling in requests per second for the key: 10 unless you set another.
Allowed templates
Limit the key to the templates it should send; anything else is refused with 403.
Expiry
Give a key an end date, and it stops working on its own.
Message logs
Keep a log of API messages with their delivery status, or turn storage off.
Stored hashed
Pinnaki keeps a hash of the key, not the key. You see the key once, when it is created or regenerated.

06Webhooks

Delivery comes back to you.

Add a webhook URL to the key, and Pinnaki posts each status change of your API messages to it, signed with the webhook secret.

Events are message.sent, message.delivered, message.read and message.failed; a failed event adds a reason.

Check X-Signature-256: the HMAC-SHA256 of X-Timestamp, a dot and the body, keyed with your webhook secret. X-Webhook-Id stays the same across retries, so you can drop duplicates.

Webhook delivery · HTTP
POST https://your-server.example/pinnaki-eventsX-Timestamp: 1791936600X-Webhook-Id: 0b9f6d0e-2f53-4c1e-9b7a-3d1f0c8e5a21X-Signature-256: sha256=<hex HMAC-SHA256 of "<X-Timestamp>.<body>"> {  "workspace_id": "…",  "message_id": "msg_3f6c2a9e-8d1b-4c57-9a0e-5b7d1c2e4f60",  "event": "message.delivered",  "to": "919800000000"}

07Questions

Questions, answered.

What developers ask before they wire Pinnaki into an order system.

Can I send marketing templates through the API?

No. The API sends utility and authentication templates, such as order updates and one-time passcodes. Marketing messages go out as campaigns, where the opt-out and audience rules apply.

Is there an SDK?

Not today. The API is one HTTPS endpoint with a JSON body, so any HTTP client works. The examples on this page use curl and Node.js.

What happens if my wallet runs low?

The API checks the balance against the message price before it accepts a request. If the balance is too low, it answers 402 and nothing is sent.

Which plan includes the API?

The Developer API and webhooks are on Professional and above. Create the key in Pinnaki under WhatsApp, Integrations, Developer API; it is shown once, so store it when you see it.

Create an API key.

Start the 14-day Professional trial, connect your WhatsApp number, then open WhatsApp, Integrations, Developer API to create the key and its webhook.