Connect Meta WhatsApp channel
curl --request POST \
--url https://api.omni.z-api.io/v1/channels/{channelId}/connect \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"wabaId": "428083093730937",
"phoneId": "123456789012345",
"code": "ABC123DEF456",
"coexistence": false
}
'import requests
url = "https://api.omni.z-api.io/v1/channels/{channelId}/connect"
payload = {
"wabaId": "428083093730937",
"phoneId": "123456789012345",
"code": "ABC123DEF456",
"coexistence": False
}
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({
wabaId: '428083093730937',
phoneId: '123456789012345',
code: 'ABC123DEF456',
coexistence: false
})
};
fetch('https://api.omni.z-api.io/v1/channels/{channelId}/connect', 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}/connect",
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([
'wabaId' => '428083093730937',
'phoneId' => '123456789012345',
'code' => 'ABC123DEF456',
'coexistence' => false
]),
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}/connect"
payload := strings.NewReader("{\n \"wabaId\": \"428083093730937\",\n \"phoneId\": \"123456789012345\",\n \"code\": \"ABC123DEF456\",\n \"coexistence\": false\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}/connect")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"wabaId\": \"428083093730937\",\n \"phoneId\": \"123456789012345\",\n \"code\": \"ABC123DEF456\",\n \"coexistence\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.omni.z-api.io/v1/channels/{channelId}/connect")
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 \"wabaId\": \"428083093730937\",\n \"phoneId\": \"123456789012345\",\n \"code\": \"ABC123DEF456\",\n \"coexistence\": false\n}"
response = http.request(request)
puts response.read_body{
"success": true
}{
"error": 401,
"message": "Unauthorized"
}Channels
Connect Meta WhatsApp channel
Complete flow to connect a META_WHATSAPP channel to the WhatsApp Official API
POST
/
v1
/
channels
/
{channelId}
/
connect
Connect Meta WhatsApp channel
curl --request POST \
--url https://api.omni.z-api.io/v1/channels/{channelId}/connect \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"wabaId": "428083093730937",
"phoneId": "123456789012345",
"code": "ABC123DEF456",
"coexistence": false
}
'import requests
url = "https://api.omni.z-api.io/v1/channels/{channelId}/connect"
payload = {
"wabaId": "428083093730937",
"phoneId": "123456789012345",
"code": "ABC123DEF456",
"coexistence": False
}
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({
wabaId: '428083093730937',
phoneId: '123456789012345',
code: 'ABC123DEF456',
coexistence: false
})
};
fetch('https://api.omni.z-api.io/v1/channels/{channelId}/connect', 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}/connect",
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([
'wabaId' => '428083093730937',
'phoneId' => '123456789012345',
'code' => 'ABC123DEF456',
'coexistence' => false
]),
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}/connect"
payload := strings.NewReader("{\n \"wabaId\": \"428083093730937\",\n \"phoneId\": \"123456789012345\",\n \"code\": \"ABC123DEF456\",\n \"coexistence\": false\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}/connect")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"wabaId\": \"428083093730937\",\n \"phoneId\": \"123456789012345\",\n \"code\": \"ABC123DEF456\",\n \"coexistence\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.omni.z-api.io/v1/channels/{channelId}/connect")
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 \"wabaId\": \"428083093730937\",\n \"phoneId\": \"123456789012345\",\n \"code\": \"ABC123DEF456\",\n \"coexistence\": false\n}"
response = http.request(request)
puts response.read_body{
"success": true
}{
"error": 401,
"message": "Unauthorized"
}Overview
After creating a channel of typeMETA_WHATSAPP, you need to connect it to a WhatsApp Business number. There are two ways:
- Via dashboard — Guided flow directly in the Dashboard
- Via SDK + API — Integrate the connection flow into your system
Connection via dashboard
The simplest way. Go to the Dashboard, select the created channel and follow the guided connection flow.Connection via SDK + API
Use this flow when you want your user to connect the channel from within your system, without needing to access the dashboard. The flow has 3 steps:1
Frontend — Start connection with SDK
In your application’s frontend, use the SDK to start the connection flow. The SDK will open the WhatsApp authentication process and return the necessary information.
import OmniZapi from '@omni-zapi/connect';
const client = OmniZapi.newClient({
publicKey: 'YOUR_PUBLIC_KEY'
});
const response = await client.connect({
channelId: 'CHANNEL_ID'
});
// Send the response to your backend
The
publicKey can be exposed in the frontend. See more at Authentication.2
Frontend → Backend — Send data
The SDK returns an object with the connection information. Send this data to your application’s backend:
{
"wabaId": "428083093730937",
"phoneId": "123456789012345",
"code": "ABC123DEF456",
"coexistence": false
}
| Field | Type | Description |
|---|---|---|
wabaId | string | Selected WhatsApp Business Account ID |
phoneId | string | Selected phone number ID |
code | string | Authorization code generated by WhatsApp |
coexistence | boolean | Whether the number is in coexistence mode |
3
Backend — Finalize connection via API
In the backend, call the connection API passing the data received from the frontend:
POST /v1/channels/{channelId}/connectcurl -X POST https://api.omni.z-api.io/v1/channels/CHANNEL_ID/connect \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_SECRET_KEY" \
-d '{
"wabaId": "428083093730937",
"phoneId": "123456789012345",
"code": "ABC123DEF456",
"coexistence": false
}'
This call must be made in the backend, as it uses the Secret Key which should never be exposed in the frontend.
Flow summary
Frontend (SDK) → Backend (API)
1. client.connect()
2. User authenticates
3. SDK returns data -----→ 4. POST /v1/channels/{id}/connect
with wabaId, phoneId, code, coexistence
5. Channel connected ✓
After connection, the channel is ready to send and receive messages. Use the
channelId in the free messages and templates endpoints.Authorizations
Secret Key generated in the Omni Z-API Security panel
Path Parameters
Channel ID (obtained via Create channel)
Example:
"a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Body
application/json
Response
Channel connected successfully
Indicates whether the operation was successful