API Reference
WhatsApp Messaging

Upload media

POST
/v1/whatsapp/media

Uploads a file to WhatsApp and returns the media id you then send in an image/video/audio/document message.

Send a multipart/form-data body with a file part. The MIME type comes from a type field if you send one, otherwise from the part's own Content-Type — Meta requires it and will not sniff.

The sending number is named in the QUERY (number_id or connection_id) so the body stays a pure file upload.

curl -X POST \  "https://api.sautikit.com/v1/whatsapp/media?number_id=$NUMBER_ID" \  -H "Authorization: Bearer $SAUTIKIT_API_KEY" \  -F "type=application/pdf" \  -F "file=@invoice.pdf"

Meta's limits apply and are enforced upstream: 5 MB images, 16 MB audio/video, 100 MB documents, 500 KB stickers.

Meta's reference: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media

API-key scope: whatsapp.messages.

Authorization

bearerAuth
AuthorizationBearer <token>

Long-lived ES256 JWT minted from the dashboard (https://app.sautikit.com/developers/api-keys). Signed by the platform keyring. Carries workspace_id and scopes claims; revoked via the platform deny-list.

In: header

Query Parameters

number_id?string

A Sautikit number id to upload against. Mutually exclusive with connection_id.

Formatuuid
connection_id?string

A WhatsApp connection id. Mutually exclusive with number_id.

Formatuuid

Request Body

multipart/form-data

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

curl -X POST "https://example.com/v1/whatsapp/media" \  -F file="string"
{  "id": "1234567890123456"}
{  "error": {    "code": "validation.bad_request",    "message": "string",    "request_id": "string",    "details": [      "string"    ]  }}
Empty
{  "error": {    "code": "validation.bad_request",    "message": "string",    "request_id": "string",    "details": [      "string"    ]  }}

Ask a contact for permission to call them POST

Sends a call-permission request to a contact. You cannot place a WhatsApp call to someone who has not granted permission, so this is the step that unlocks outbound WhatsApp calling to them. Two forms, selected by `mode`: - `free_form` (default) — an interactive permission-request message built from `text`. Subject to the same 24-hour customer service window as any free-form message. - `template` — an already-approved template whose components include a `call_permission_request` component. Use this outside the 24-hour window. The contact's answer arrives as the `whatsapp.call_permission.updated` workspace webhook. ```json { "connection_id": "3f1a9c22-58d4-4f7e-9b10-2c6e8a4d5f31", "wa_id": "254700000001", "mode": "free_form", "text": "May we call you about your order?" } ``` Meta's reference: https://developers.facebook.com/docs/whatsapp/cloud-api/guides/call-permissions **API-key scope:** `whatsapp.messages`.

Download media GET

Streams the bytes of a media object. Inbound messages carry media as an **id**, not a URL — `{"type":"image","image":{"id":"1234567890123456"}}`. This endpoint is how you turn that id into the file. Sautikit proxies the bytes rather than redirecting you, deliberately: Meta serves media from a short-lived host whose URL expires in five minutes and is authorised only by your workspace's access token. A redirect would hand you a link that is both dead on arrival and, if it worked, would carry that token. The response is the raw file. `Content-Type` is the MIME type Meta reports, and `X-Sautikit-Media-Sha256` carries Meta's checksum so you can verify what you received. ```bash curl "https://api.sautikit.com/v1/whatsapp/media/$MEDIA_ID?number_id=$NUMBER_ID" \ -H "Authorization: Bearer $SAUTIKIT_API_KEY" \ -o receipt.pdf ``` Meta's reference: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media **API-key scope:** `whatsapp.messages`.