Guides
Create a WhatsApp group with an API (curl, Node, Python)
To create a WhatsApp group with an API, send POST /v1/sessions/{channel}/groups with a subject, then POST the people to add to /participants with action "add", then GET /invite-link. Every call carries the channel token as a Bearer header. The answer to the first call includes the group jid you use for the rest.
Facts (as of October 2026, API v1)
- Base URL: https://api.wagate.dev/v1. Auth: Authorization: Bearer <channel token>.
- Subject: 1 to 25 characters. Participants: up to 50 per request, phone numbers or JIDs.
- The create answers 201 with the group. The participants call answers one result per person.
- The free sandbox channel allows 5 group adds a day.
Steps
- Get a channel token. In the console, link a number to your free sandbox channel and create an API token for it. Keep the channel ID and the token in environment variables.
- Create the group. POST /groups with a subject. The answer is the group, including its jid.
- Add people. POST /groups/{jid}/participants with action "add" and the people to add. Read the result of each person.
- Get the invite link. GET /groups/{jid}/invite-link and share the invite_link.
Before you start
You need a channel ID and its token. The commands below read them from CHANNEL_ID and CHANNEL_TOKEN. The examples use placeholders for phone numbers: use full international digits, no plus sign.
curl
API=https://api.wagate.dev/v1
BASE="$API/sessions/$CHANNEL_ID"
AUTH="Authorization: Bearer $CHANNEL_TOKEN"
curl -s -X POST "$BASE/groups" \
-H "$AUTH" \
-H "Content-Type: application/json" \
-d '{"subject":"Team","participants":[]}'
# Put the "jid" from the answer above here, for example [email protected]
[email protected]
curl -s -X POST "$BASE/groups/$GROUP/participants" \
-H "$AUTH" \
-H "Content-Type: application/json" \
-d '{"action":"add","participants":["66XXXXXXXXX"]}'
curl -s -X GET "$BASE/groups/$GROUP/invite-link" \
-H "$AUTH"Node.js
Node 20 or later, which has fetch built in. Save it as sample.mjs, because it uses top-level await. The script runs the three calls in order and prints each answer.
const API = 'https://api.wagate.dev/v1';
const { CHANNEL_ID, CHANNEL_TOKEN } = process.env;
const BASE = `${API}/sessions/${CHANNEL_ID}`;
const headers = {
Authorization: `Bearer ${CHANNEL_TOKEN}`,
'Content-Type': 'application/json',
};
async function call(method, path, body) {
const res = await fetch(`${BASE}${path}`, {
method,
headers,
body: body === undefined ? undefined : JSON.stringify(body),
});
const data = await res.json();
if (!res.ok) throw new Error(`${res.status} ${data.code}: ${data.error}`);
return data;
}
const group = await call('POST', `/groups`, {"subject":"Team","participants":[]});
console.log(group);
const added = await call('POST', `/groups/${group.jid}/participants`, {"action":"add","participants":["66XXXXXXXXX"]});
console.log(added);
const invite = await call('GET', `/groups/${group.jid}/invite-link`);
console.log(invite);Python
import os
import requests
API = 'https://api.wagate.dev/v1'
BASE = f"{API}/sessions/{os.environ['CHANNEL_ID']}"
HEADERS = {'Authorization': f"Bearer {os.environ['CHANNEL_TOKEN']}"}
def call(method, path, body=None):
res = requests.request(method, BASE + path, headers=HEADERS, json=body, timeout=30)
data = res.json()
if not res.ok:
raise RuntimeError(f"{res.status_code} {data.get('code')}: {data.get('error')}")
return data
group = call('POST', f"/groups", {
"subject": "Team",
"participants": []
})
print(group)
added = call('POST', f"/groups/{group['jid']}/participants", {
"action": "add",
"participants": [
"66XXXXXXXXX"
]
})
print(added)
invite = call('GET', f"/groups/{group['jid']}/invite-link")
print(invite)Read the add results
The participants call answers 200 with one result per person. A person who fails does not fail the others.
{
"results": [
{
"jid": "66XXXXXXXXX",
"status": "ok",
"matched_by": "a"
}
]
}- status "ok" means the person was added.
- status "error_<code>" means WhatsApp refused that person. 403 is their privacy settings or a missing admin right, 408 left recently, 409 already in the group, 401 blocked this number, 404 not on WhatsApp.
- status "unknown" means the change may have applied. Read the group before you retry.
More you can do with a group
| Method | Path | What it does |
|---|---|---|
| GET | /v1/sessions/{channel}/groups | List groups |
| POST | /v1/sessions/{channel}/groups | Create a group |
| GET | /v1/sessions/{channel}/groups/{group} | Get a group |
| PUT | /v1/sessions/{channel}/groups/{group}/description | Set or clear a group's description |
| GET | /v1/sessions/{channel}/groups/{group}/invite-link | Get a group's invite link |
| POST | /v1/sessions/{channel}/groups/{group}/participants | Add, remove, promote or demote participants |
| PUT | /v1/sessions/{channel}/groups/{group}/settings | Change a group's settings |
| PUT | /v1/sessions/{channel}/groups/{group}/subject | Set a group's subject |
Retry rules
The API has no idempotency key. A 500, 502 or 503 on a write can leave it applied. List or read the group first, and never re-create a group blindly. A person with error_409 is already in the group, which for an add is a success.
Questions
- What does the group create request need?
- Only a subject of 1 to 25 characters. participants (up to 50) and parent_jid (to create the group inside a community) are optional.
- Do I add people in the create call or after?
- Either. You can name up to 50 people in the create call, or add them afterwards with the participants call and action "add".
- What happens if one person cannot be added?
- The answer has one result per person, so the others still go through. The failed person has a status such as error_403 with a sentence that says why.
- How do I find out when someone joins or leaves?
- Subscribe a webhook receiver to group.participants. Each delivery is signed, so verify the signature before you trust it.
Free sandbox, forever. Add a real number when you're ready.
Start in the free sandboxKeep going
WaGate is an independent WhatsApp API for developers: send and receive messages, automate groups and communities, and get signed webhooks with a free sandbox. Not affiliated with WhatsApp or Meta. You link your own number.