Send contact
curl --request POST \
--url https://api.omni.z-api.io/v1/channels/{channelId}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"recipient": {
"identifier": "5511999999999"
},
"content": {
"type": "CONTACT",
"attachments": [
{
"name": "Gutemberg Fernandes",
"phones": [
"5511888888888"
]
}
]
}
}
'import requests
url = "https://api.omni.z-api.io/v1/channels/{channelId}/messages"
payload = {
"recipient": { "identifier": "5511999999999" },
"content": {
"type": "CONTACT",
"attachments": [
{
"name": "Gutemberg Fernandes",
"phones": ["5511888888888"]
}
]
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
recipient: {identifier: '5511999999999'},
content: {
type: 'CONTACT',
attachments: [{name: 'Gutemberg Fernandes', phones: ['5511888888888']}]
}
})
};
fetch('https://api.omni.z-api.io/v1/channels/{channelId}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.omni.z-api.io/v1/channels/{channelId}/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'recipient' => [
'identifier' => '5511999999999'
],
'content' => [
'type' => 'CONTACT',
'attachments' => [
[
'name' => 'Gutemberg Fernandes',
'phones' => [
'5511888888888'
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.omni.z-api.io/v1/channels/{channelId}/messages"
payload := strings.NewReader("{\n \"recipient\": {\n \"identifier\": \"5511999999999\"\n },\n \"content\": {\n \"type\": \"CONTACT\",\n \"attachments\": [\n {\n \"name\": \"Gutemberg Fernandes\",\n \"phones\": [\n \"5511888888888\"\n ]\n }\n ]\n }\n}")
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(string(body))
}HttpResponse<String> response = Unirest.post("https://api.omni.z-api.io/v1/channels/{channelId}/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"recipient\": {\n \"identifier\": \"5511999999999\"\n },\n \"content\": {\n \"type\": \"CONTACT\",\n \"attachments\": [\n {\n \"name\": \"Gutemberg Fernandes\",\n \"phones\": [\n \"5511888888888\"\n ]\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.omni.z-api.io/v1/channels/{channelId}/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"recipient\": {\n \"identifier\": \"5511999999999\"\n },\n \"content\": {\n \"type\": \"CONTACT\",\n \"attachments\": [\n {\n \"name\": \"Gutemberg Fernandes\",\n \"phones\": [\n \"5511888888888\"\n ]\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"messageId": "01A0C92D0C957FE98B73C8BA0CACF741"
}{
"error": 401,
"message": "Unauthorized"
}{
"timestamp": "2026-10-22T14:00:00.123Z",
"code": "BUSINESS_RULE_VIOLATION",
"subCode": "CHANNEL_DISCONNECTED",
"message": "Channel is disconnected"
}Messages
Send contact
Send contacts via WhatsApp
POST
/
v1
/
channels
/
{channelId}
/
messages
Send contact
curl --request POST \
--url https://api.omni.z-api.io/v1/channels/{channelId}/messages \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"recipient": {
"identifier": "5511999999999"
},
"content": {
"type": "CONTACT",
"attachments": [
{
"name": "Gutemberg Fernandes",
"phones": [
"5511888888888"
]
}
]
}
}
'import requests
url = "https://api.omni.z-api.io/v1/channels/{channelId}/messages"
payload = {
"recipient": { "identifier": "5511999999999" },
"content": {
"type": "CONTACT",
"attachments": [
{
"name": "Gutemberg Fernandes",
"phones": ["5511888888888"]
}
]
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
recipient: {identifier: '5511999999999'},
content: {
type: 'CONTACT',
attachments: [{name: 'Gutemberg Fernandes', phones: ['5511888888888']}]
}
})
};
fetch('https://api.omni.z-api.io/v1/channels/{channelId}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.omni.z-api.io/v1/channels/{channelId}/messages",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'recipient' => [
'identifier' => '5511999999999'
],
'content' => [
'type' => 'CONTACT',
'attachments' => [
[
'name' => 'Gutemberg Fernandes',
'phones' => [
'5511888888888'
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.omni.z-api.io/v1/channels/{channelId}/messages"
payload := strings.NewReader("{\n \"recipient\": {\n \"identifier\": \"5511999999999\"\n },\n \"content\": {\n \"type\": \"CONTACT\",\n \"attachments\": [\n {\n \"name\": \"Gutemberg Fernandes\",\n \"phones\": [\n \"5511888888888\"\n ]\n }\n ]\n }\n}")
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(string(body))
}HttpResponse<String> response = Unirest.post("https://api.omni.z-api.io/v1/channels/{channelId}/messages")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"recipient\": {\n \"identifier\": \"5511999999999\"\n },\n \"content\": {\n \"type\": \"CONTACT\",\n \"attachments\": [\n {\n \"name\": \"Gutemberg Fernandes\",\n \"phones\": [\n \"5511888888888\"\n ]\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.omni.z-api.io/v1/channels/{channelId}/messages")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"recipient\": {\n \"identifier\": \"5511999999999\"\n },\n \"content\": {\n \"type\": \"CONTACT\",\n \"attachments\": [\n {\n \"name\": \"Gutemberg Fernandes\",\n \"phones\": [\n \"5511888888888\"\n ]\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"messageId": "01A0C92D0C957FE98B73C8BA0CACF741"
}{
"error": 401,
"message": "Unauthorized"
}{
"timestamp": "2026-10-22T14:00:00.123Z",
"code": "BUSINESS_RULE_VIOLATION",
"subCode": "CHANNEL_DISCONNECTED",
"message": "Channel is disconnected"
}Being implemented. Only one contact per message works today:
attachments accepts a list, but nothing from the second item on is sent.We also carry only name and phones. Meta accepts up to 257 contacts in one send, and on each one also email, address, organization, birthday and website.We are extending the endpoint. Until then, send one contact per request.Overview
Sends a contact to a recipient. Thecontent.type field must be CONTACT. You can send multiple phone numbers in the phones array.
Details of the Meta Cloud API rule in conversation window. See what each channel accepts for every channel.
If the channel is disconnected, the API refuses the send with
422 and subCode CHANNEL_DISCONNECTED, and the message is not sent. See Send errors.Authorizations
Secret Key generated in the Omni Z-API Security panel
Path Parameters
Channel ID
Example:
"YOUR_CHANNEL_ID"
Body
application/json
Response
Message sent successfully
Sent message ID — 32-character uppercase hexadecimal string