Send a WhatsApp message or mark inbound as read
package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://api.kirim.chat/v1/106540352242922/messages"
payload := strings.NewReader("{ \"messaging_product\": \"whatsapp\", \"recipient_type\": \"individual\", \"to\": \"example\", \"type\": \"text\", \"text\": { \"body\": \"example\", \"preview_url\": true } }")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>") req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}const url = 'https://api.kirim.chat/v1/106540352242922/messages';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"messaging_product":"whatsapp","recipient_type":"individual","to":"example","type":"text","text":{"body":"example","preview_url":true}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}use serde_json::json;use reqwest;
#[tokio::main]pub async fn main() { let url = "https://api.kirim.chat/v1/106540352242922/messages";
let payload = json!({ "messaging_product": "whatsapp", "recipient_type": "individual", "to": "example", "type": "text", "text": json!({ "body": "example", "preview_url": true }) });
let mut headers = reqwest::header::HeaderMap::new(); headers.insert("Authorization", "Bearer <token>".parse().unwrap()); headers.insert("Content-Type", "application/json".parse().unwrap());
let client = reqwest::Client::new(); let response = client.post(url) .headers(headers) .json(&payload) .send() .await;
let results = response.unwrap() .json::<serde_json::Value>() .await .unwrap();
dbg!(results);}curl --request POST \ --url https://api.kirim.chat/v1/106540352242922/messages \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "messaging_product": "whatsapp", "recipient_type": "individual", "to": "example", "type": "text", "text": { "body": "example", "preview_url": true } }'Meta-style messages endpoint. Two operations share the same path, distinguished by the request body:
Outbound send — body has a type field (text, image, document, video, audio, template, interactive). Body shape mirrors the Meta WhatsApp Cloud API; media variants accept either link (hosted URL) or id (Meta uploaded media). The sender is the WhatsApp account identified by phone_number_id in the URL path; there is no from field in the body. Pass Idempotency-Key to safely retry on network failure.
Read receipt — body has status: "read" + message_id (the inbound wamid from your webhook). Sends a read receipt back to the sender so the double-tick turns blue on their phone. Optional typing_indicator: { type: "text" } shows a typing bubble alongside the receipt; Meta auto-dismisses after ~25 seconds or on first outbound message.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”Meta WhatsApp Business phone_number_id of the connected account that should send / own this resource. Discoverable via GET /v1/accounts (returned as phone_number_id on each row).
Example
106540352242922Header Parameters
Section titled “Header Parameters ”Optional idempotency token. See /docs/idempotency.
Request Body
Section titled “Request Body ”object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
object
Meta WhatsApp message id (wamid) of the inbound message to mark as read. Get it from the inbound webhook payload — NOT a Kirim msg_* external id.
Example
wamid.HBgNNjI4MTIzNDU2Nzg5FQIAEhggMUE5MDM1QzVDMUYxQTAyRkVCNzZDQjVDMjFFRDQzNTUAOptional. When present, Meta also shows a typing indicator to the recipient that auto-dismisses on response or after ~25 seconds. Only include if you intend to respond — leaving the indicator hanging produces a poor UX.
object
Responses
Section titled “ Responses ”Message accepted for delivery, or read receipt sent.
object
object
object
Example
{ "data": { "id": "msg_01HXYZABCDEFGHJKMNPQRSTVWX", "object": "message", "status": "queued" }}Validation failure
object
object
Example
{ "error": { "type": "invalid_request_error", "code": "invalid_phone_number", "request_id": "req_01HXYZABCDEFGHJKMNPQRSTVWX" }}Authentication failure
object
object
Example
{ "error": { "type": "invalid_request_error", "code": "invalid_phone_number", "request_id": "req_01HXYZABCDEFGHJKMNPQRSTVWX" }}Resource not found
object
object
Example
{ "error": { "type": "invalid_request_error", "code": "invalid_phone_number", "request_id": "req_01HXYZABCDEFGHJKMNPQRSTVWX" }}Semantic failure (e.g. idempotency key reuse)
object
object
Example
{ "error": { "type": "invalid_request_error", "code": "invalid_phone_number", "request_id": "req_01HXYZABCDEFGHJKMNPQRSTVWX" }}Rate limit exceeded
object
object
Example
{ "error": { "type": "invalid_request_error", "code": "invalid_phone_number", "request_id": "req_01HXYZABCDEFGHJKMNPQRSTVWX" }}Upstream WhatsApp error
object
object
Example
{ "error": { "type": "invalid_request_error", "code": "invalid_phone_number", "request_id": "req_01HXYZABCDEFGHJKMNPQRSTVWX" }}Service unavailable
object
object
Example
{ "error": { "type": "invalid_request_error", "code": "invalid_phone_number", "request_id": "req_01HXYZABCDEFGHJKMNPQRSTVWX" }}