Create a WhatsApp Group via API: Confirm the ID and Members
To create a WhatsApp group through UnifyPort, send POST /v1/accounts/{account_id}/groups/create with a required name and an optional members array. For this creation request, WhatsApp initial members are identified by phone numbers. The successful response returns data.id, not a membership report. Save that ID immediately, then read the group and its members before starting dependent automation.
Key takeaways
- Creating a group, inviting people, and changing existing members are different operations.
- Initial
membersuses phone numbers; later member-management requests use a different identifier contract. - The public catalogue has no
group.createdevent. Do not wait for one to finish your workflow. - A missing response leaves creation uncertain; automatically repeating it can create another group.
Read the creation contract before building the form
The Create group reference defines the following contract. UnifyPort provides an unofficial interface for the connected messaging account, not a WhatsApp Cloud API endpoint. Its action support matrix currently maps group creation to whatsapp, excluding LINE, Telegram, and the separate whatsapp-protocol provider.
| Value | Meaning | Do not substitute |
|---|---|---|
Path account_id | Account that will create the group | A workspace ID |
Body name | Required group name, up to 100 characters | A unique resource identifier |
Body members | Optional initial-member identifiers; phone numbers for WhatsApp | A copied array of member LIDs |
Response data.id | Newly created group ID | An invitation code or operation ID |
The creation response contains only the new group ID within data. It does not provide a per-person admission result. Keep the intended initial membership separate from the membership you subsequently observe.
WhatsApp’s official member-management guide describes adding members, inviting them, and reviewing pending requests when approval is enabled. Those are separate user journeys, not interchangeable evidence that someone joined. If people should choose whether to enter an existing group, use the invite-link workflow rather than creating another group.
Prepare one deliberate creation attempt
Before enabling the button, confirm the selected account is authorized and its runtime is running using the account lifecycle reference. Keep the API key on your backend and enforce operator permissions there.
Recommended application safeguards:
- Show the selected account, proposed name, and intended participants for confirmation. Add only people who expect to participate.
- Save a local creation intent before dispatch. Record the operator and intended inputs in your application, not as extra API fields.
- Prevent concurrent submissions for that intent on the backend; disabling the browser button alone is insufficient.
- Make one request and preserve its outcome before allowing follow-up actions.
The following illustrative server-side JavaScript constructs the documented request from confirmed inputs. It has not been executed here and deliberately performs no retries:
async function createGroupOnce({ apiKey, accountId, name, phones }) {
if (!apiKey || !accountId || typeof name !== 'string' || !name.trim()) {
throw new Error('Missing credential, account, or group name');
}
const body = { name };
if (phones !== undefined) {
if (!Array.isArray(phones) ||
phones.some(p => typeof p !== 'string' || !/^[0-9]+$/.test(p))) {
throw new Error('Use confirmed phone-number strings');
}
body.members = phones;
}
const response = await fetch(
`https://api.unifyport.ai/v1/accounts/${encodeURIComponent(accountId)}/groups/create`,
{
method: 'POST',
headers: { 'X-Api-Key': apiKey, 'Content-Type': 'application/json' },
body: JSON.stringify(body)
}
);
return { httpStatus: response.status, result: await response.json() };
}
Use actual confirmed phone numbers in the documented format. The digit check is a local input guard, not proof that a number belongs to an eligible participant. Validate the documented name limit too. Production code must handle network and non-JSON failures, securely retain request_id when available, and avoid logging credentials or participant phone lists.
Separate the group ID from membership verification
On 200 OK with data.id, persist the returned ID with the selected account and your local creation intent. Then use Get group with that ID as group_id.
To inspect participants, use List conversation members with the group ID as conversation_id and type=group. Follow has_more and next_cursor; a missing person on the first page is not a completed membership check. Preserve returned peer_id and role values without deriving LIDs from phone numbers.
Later management is a separate contract: Manage group members accepts singular member_id, one action per request, and WhatsApp LIDs returned as peer_id by the member list. Do not reuse the creation payload there. If assigning administrators is the next task, follow the admin role-change guide.
| Observation | Recommended application state | Next action |
|---|---|---|
| Successful response and group ID saved | Created; membership not yet verified | Read the group and all member pages |
| Group readable, intended membership not resolved | Group exists; membership needs review | Inspect identity mappings or review in the native app |
| Timeout, unreadable response, or missing expected ID | Creation outcome unresolved | Reconcile before considering a new attempt |
These are application states, not additional API response values.
Recover without creating a duplicate group
The standard event catalogue does not include group.created; creation success does not promise that callback. A group.updated event is not a guaranteed receipt for this request either.
If the response is lost, inspect List groups under the same account, following pagination. It includes joined groups even without message activity. Use available details and the native app to investigate; a matching name alone is not proof of identity, and an incomplete or failed read is not proof that creation failed.
The public creation contract documents no idempotency key. A local intent record helps prevent your own duplicate submissions but cannot make the upstream operation exactly-once. Keep dependent invitations and automated messages paused while the outcome remains unresolved. Require operator review before another creation attempt.
FAQ
Can I omit members?
Yes, the API documents members as optional. That is a request-schema property, not a guarantee of every upstream account’s behavior. Verify the actual result.
Does HTTP success prove every requested person joined?
No. The documented result returns a group ID, not per-member outcomes. Read membership separately.
Can I add the description and avatar in the creation request?
They are not documented creation fields. Handle them afterward using the separate group information editing workflow.
Next step and sources
Build against Create group. Test duplicate clicks, lost responses, repeated group names, paginated member lists, and unavailable participants with accounts you control. These are proposed checks, not reported test results.
References checked on 2026-10-24:
Turn messaging integration into a stable product pipeline.
Start by sending through one API, then bring every inbound message back into your business system with standard events.