WhatsApp Business groups
WhatsApp Business groups are groups a business creates on its own Cloud API number through Meta's Groups API. They are not personal WhatsApp groups: Tyxter does not connect to, read, join, import or mirror groups created in the WhatsApp or WhatsApp Business app.
Read WhatsApp Business groups are not personal WhatsApp groups before designing around groups: it compares the two features and answers common requests, such as connecting existing groups or adding people by phone number. Create and manage WhatsApp Business groups walks one group through these routes and its events, sandbox first.
pending, and a Tyxter worker then picks it up. In sandbox the group becomes active once the worker has run, with a sandbox provider_group_id (starting sb_) and a sandbox invite_link (starting https://chat.whatsapp.com/sandbox_) that cannot be used to join a real group (assumed); the sandbox never refuses a create. In production Tyxter sends the create to Meta once, and Meta reports the result later by webhook. Tyxter applies that report, making the group active with Meta's provider_group_id and invite_link or failed, but Meta does not send these webhooks to Tyxter yet (they are not enabled on Tyxter's Meta app), and a report is matched to its group only by the request id Meta returns for the create (assumed). Until then, and whenever a report cannot be matched, the group stays pending with no provider_group_id or invite_link, unless Meta refuses the create outright, which makes it failed with failure.code group_provider_rejected. No production group has yet been observed through Tyxter from create to Meta's reported outcome; the shapes of Meta's group webhooks are assumed from Meta's documentation. If the worker finds it cannot send the create, nothing is sent to Meta and the group becomes failed with failure.provider null and a failure.message saying why; create the group again once the cause is fixed. failure.code is sender_phone_number_unavailable when the phone number can no longer host a group when the worker runs (for example it was released or disconnected after the create was accepted; the one case a sandbox key can reach), group_phone_number_not_eligible when its stored eligibility answer became not_eligible after the create was accepted (production only), and provider_errorwhen the production environment has no connected Meta provider or its stored Meta credentials cannot be read. A create left unsent for any other reason (for example the worker cannot reach Tyxter's database) stays pending. Tyxter does not promise a completion time. Deleting an active group makes it deleting, and a Tyxter worker then picks the delete up. In sandbox the group becomes deleted once the worker has run; a sandbox delete never fails. In production Tyxter sends the delete to Meta once, and Meta reports the result later by webhook. Tyxter applies that report, making the group deleted, or active again with failure.code group_provider_rejectedwhen Meta refused, but only once Meta sends these webhooks to Tyxter (not enabled on Tyxter's Meta app yet); until then the group stays deleting. If Meta refuses the delete outright, the group is active again with that failure; if Tyxter cannot tell whether Meta deleted it (for example the call timed out), it stays deleting with failure.code provider_error. If the environment's Meta connection cannot be used, nothing is sent and the group stays deleting, with failure null. A delete that stays deleting produces no group.deleted or group.delete_failed event unless Meta later reports its outcome; read the group rather than waiting for one. Resetting an activegroup's invite link keeps the group active, and a Tyxter worker then resets the link. In sandbox invite_link becomes a new sandbox link once the worker has run; a sandbox reset never fails. In productionTyxter sends the reset to Meta once, and Meta answers with the new link in the same call (heard from Meta's documentation); Tyxter stores it, and earlier links stop working. If Meta refuses, the stored link is kept and the group gets failure.code group_provider_rejected; if Tyxter cannot tell whether Meta reset the link (for example the call timed out), the group gets failure.code provider_errorand the stored link may no longer work; if Tyxter sent the reset but could not record Meta's answer, the group also gets failure.code provider_errorand the stored link may no longer work; if the environment's Meta connection cannot be used, nothing is sent, the link is unchanged and the group gets failure.code provider_error. Every group read carries participants (by WhatsApp ID) and participant_count: in production they follow the joins and removals Meta reports by webhook, under the same condition as the create outcome (Meta does not send these webhooks to Tyxter yet); in sandbox you simulate them with the sandbox participant route below. A deleted group lists none. Webhook endpoints subscribed to them receive eight group events, signed like every Tyxter webhook. group.created, group.create_failed, group.deleted, group.delete_failed, group.invite_link_reset and group.invite_link_reset_failed carry group_id, phone_number_id, status, subject, provider_group_id, invite_link, failure and occurred_at (when Tyxter recorded the outcome). On group.create_failed, group.delete_failed and group.invite_link_reset_failed, failureis the failure of the operation that failed, which Tyxter stores with the event when it records the outcome: a delayed delivery or a listen read still shows it after a newer delete or reset changed the group's failure, and a reset that fails while the group is deleting carries its own reason although the group's failure stays the delete's. Every other field but occurred_at, and failure on the other three events, is the group as Tyxter reads it when it sends the event or serves it on a listen read, so a delayed or replayed event can show a later state. group.participant_joined and group.participant_removed carry group_id, phone_number_id, participant.wa_id, participant_count (Tyxter's count right after it applied the change) and occurred_at (Meta's time, in whole seconds; the simulation time in sandbox), plus initiated_by (participant or business) on a removal. A join or removal older than the participant's latest recorded one is still delivered although group reads do not reflect it, and the same participant, action and second reported twice is one event. The invite_link in a payload lets anyone who has it join the group, so store payloads as secrets. A sandbox key never receives group.delete_failed or group.invite_link_reset_failed. Removing participants, join requests, group messages and webhooks for group settings or status are not offered yet. This page is where availability is kept current.Read eligibility
Query params
| Field | Type | Notes |
|---|---|---|
phone_number_idrequired | string | Tyxter phone number id (the id on GET /v1/phone-numbers), not the Meta id. len 1..255 |
Response
| Field | Type | Notes |
|---|---|---|
objectrequired | "group_eligibility" | |
phone_number_idrequired | string | Tyxter phone number id the answer is about. |
environmentrequired | "sandbox" | "production" | |
statusrequired | "eligible" | "not_eligible" | "unknown" | "not_checked" | "read_failed" | eligible, not_eligible, unknown (Meta answered without every fact needed and nothing reported disqualifies), not_checked (no check has run), or read_failed (the last check could not read Meta or did not finish). |
reasonsrequired | "not_cloud_api" | "whatsapp_business_app_number" | "not_official_business_account" | "missing_messaging_permission"[] | Disqualifying reasons; non-empty only when status is not_eligible. |
checked_atrequired | string<ISO-8601> | null | When the latest completed check ran, including one that ended read_failed; null when no check has completed. A value later than check_requested_at answers the latest request. |
check_requested_atrequired | string<ISO-8601> | null | When the latest check was requested; null when none was requested. |
Requires groups:read. phone_number_id is the Tyxter phone number id (the id on GET /v1/phone-numbers), not Meta's. The answer comes from Tyxter's own records; the call never reaches Meta.
- It serves the answer of the latest completed eligibility check (see below), with its
checked_atandcheck_requested_at. - With no completed check, a sandbox number answers
eligibleand a production number answersnot_checked, withreasonsempty andchecked_atnull.not_checkedsays nothing about whether Meta would accept the number.
The full status vocabulary is eligible, not_eligible, unknown, not_checked and read_failed; reasons is non-empty only for not_eligible. Branch on every value.
A missing or blank phone_number_id, or an unknown query parameter, returns 400 invalid_groups_query with param naming it. A phone number that does not exist and one that belongs to another organization, project or environment both return the same 404 phone_number_not_found.
curl "https://api.tyxter.com/v1/groups/eligibility?phone_number_id=$PHONE_NUMBER_ID" \
-H "authorization: Bearer $TYXTER_API_KEY"Check eligibility
Request body
| Field | Type | Notes |
|---|---|---|
phone_number_idrequired | string | Tyxter phone number id (the id on GET /v1/phone-numbers), not the Meta id. len 1..255 |
Requires groups:write and honors Idempotency-Key: a replay with the same key and body returns the first response and runs no second check. Returns 202 with a GroupEligibilityResponse holding the answer stored at that moment (the previous answer, or the no-check answer) and the new check_requested_at. The call itself never reaches Meta: a Tyxter worker reads the facts afterwards. Poll GET /v1/groups/eligibility until checked_at is later than check_requested_at. A check normally completes shortly after it is accepted, but Tyxter does not promise a completion time: if checked_at has not passed check_requested_at within your own timeout, that check did not complete. You can request a new check at any time, with a new Idempotency-Key.
- A sandbox number answers
eligiblewithout any call to Meta. - A production number answers
eligibleonly when Meta reports a Cloud API number (platform_typeCLOUD_API) that is not on the WhatsApp Business app (is_on_biz_appfalse) and is an Official Business Account, and the connection's token holdswhatsapp_business_messaging. not_eligiblelists each disqualifier Meta reported inreasons:not_cloud_api,whatsapp_business_app_number(assumed to include a number using the WhatsApp Business app and the Cloud API together, from Meta's "not the WhatsApp Business app" requirement),not_official_business_accountormissing_messaging_permission.unknownmeans Meta answered without every fact needed and nothing it reported disqualifies the number. Meta documents no field for Official Business Account status, so Tyxter reads a field whose name is assumed. When Meta omits or refuses it, that missing field never by itself makes the answereligibleornot_eligible: with no other disqualifier the answer isunknown, and a disqualifier Meta did report still answersnot_eligible.read_failedmeans the check could not read Meta or did not finish — a failed Graph call, an invalid token, a stored Meta credential Tyxter could not open, no connected Meta provider for the environment, or a check that kept failing inside Tyxter. It is never turned into a yes or a no; run the check again later.- The answer is about the number, whatever its lifecycle status; whether a number can host a group is decided when the group is created.
A body that is not a JSON object, a missing or blank phone_number_id, or an unknown field returns 400 invalid_group_request with param naming it. A foreign or absent phone number returns 404 phone_number_not_found. When an organization owner or admin disables WhatsApp Business groups for the environment in feature controls, the check returns 403 feature_disabled before any work, and the eligibility read keeps answering.
curl -X POST "https://api.tyxter.com/v1/groups/eligibility-checks" \
-H "authorization: Bearer $TYXTER_API_KEY" \
-H "content-type: application/json" \
-H "idempotency-key: $(uuidgen)" \
-d '{"phone_number_id":"'"$PHONE_NUMBER_ID"'"}'Create a group
Request body
| Field | Type | Notes |
|---|---|---|
phone_number_idrequired | string | Tyxter phone number id (the id on GET /v1/phone-numbers) to create the group on, not the Meta id. len 1..255 |
subjectrequired | string | Group name shown to participants. Required. len 1..∞ |
description | string | null | Optional group description. |
join_approval_mode | "auto_approve" | auto_approve (the default and the only value offered). Meta documents it as letting anyone who has the group invite link join without approval (heard). |
Response
| Field | Type | Notes |
|---|---|---|
idrequired | string | Tyxter group id, minted when the create is accepted. Never Meta's group id. |
objectrequired | "group" | |
statusrequired | "pending" | "active" | "failed" | "deleting" | "deleted" | pending, active, failed, deleting or deleted. A new group is pending until Tyxter learns Meta's create outcome, or until Tyxter's worker finds it cannot send the create (its phone number, eligibility answer or Meta connection rules it out), which ends it failed. |
environmentrequired | "sandbox" | "production" | |
phone_number_idrequired | string | Tyxter phone number id the group is created on. |
subjectrequired | string | |
descriptionrequired | string | null | |
join_approval_moderequired | "auto_approve" | |
provider_group_idrequired | string | null | Meta's group id; null until Meta confirms. |
invite_linkrequired | string | null | Invite link; null until Meta confirms. Replaced when an invite link reset completes; a reset made outside Tyxter (directly through Meta's API) is not seen, so the stored link can then be stale. |
participantsrequired | object[] | The current members Tyxter has recorded, oldest join first. A participant appears only while a member: removed participants are dropped, and a deleted group lists none. Tyxter learns membership only from the participant events Meta sends (or the sandbox simulation), never by reading the group from Meta. |
participant_countrequired | integer | The number of entries in participants. range 0..9007199254740991 |
failurerequired | object | null | Why the last provider operation failed; null otherwise. |
created_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
updated_atrequired | string<ISO-8601> | pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ |
deleted_atrequired | string<ISO-8601> | null |
Requires groups:write and honors Idempotency-Key: a replay with the same key and body returns the first response as it was sent, with the same group id and status pending, and creates no second group; it does not show the group's current status, so read that with GET /v1/groups/{group_id}. Returns 202 with the group and status pending. The call itself never reaches Meta; a Tyxter worker sends the create afterwards (see Available today). Tyxter sets no length limit of its own on subject or description and checks only that subject is a non-blank string and description a string or null; Meta enforces its own limits, and a value Meta refuses makes the group failed with failure.code group_provider_rejected and Meta's reason, not a request error. join_approval_mode accepts only auto_approve, the default; Meta's documentation describes it as letting anyone who has the group's invite link join without approval (heard). Treat invite_link like a password: anyone who has it can join the group. approval_required returns 400 invalid_group_request because it is not offered yet.
id is the Tyxter group id, minted when the create is accepted; provider_group_id is Meta's group id and invite_link the invite link, both null until Meta confirms the group. status is one of pending, active, failed, deleting or deleted (the last two through a delete, below); a group whose Meta outcome never arrives stays pending, and Tyxter does not guess an outcome. When Tyxter cannot tell whether Meta created the group (for example the call to Meta timed out), the group also stays pending.
400 invalid_group_request: the body is not a JSON object, a required field is missing or blank, a field has the wrong type, or the body carries an unknown field;paramnames it.404 phone_number_not_found: the phone number does not exist or belongs to another organization, project or environment.400 sender_phone_number_unavailable: the number cannot host a group — it is not an active WhatsApp phone number linked to Meta, for example because it was released or disconnected.422 group_phone_number_not_eligible: the stored eligibility answer for the number isnot_eligible. Any other answer, or no check at all, admits the create and the group is accepted aspending; Meta then decides (see Available today).403 feature_disabled: WhatsApp Business groups are disabled for the environment in feature controls; the group reads and the delete keep answering (the invite-link reset is refused the same way).
Retrieve a group
Requires groups:read and returns the GroupResponsefrom Tyxter's records; the call never reaches Meta. group_id is the id POST /v1/groupsreturned, never Meta's group id. A deleted group stays readable. If the group_id path segment looks like a personal WhatsApp group — an app-style id ending in @g.us, or an invite link from chat.whatsapp.com that is percent-encoded into the one segment (the SDK's groups.retrieve encodes the id) — the route returns 422 personal_whatsapp_group_not_supported, and the message links WhatsApp Business groups are not personal WhatsApp groups. An invite link pasted into the path unencoded contains slashes, matches no route and returns 404 route_not_found instead. Any other id that does not exist or belongs to another organization, project or environment returns 404 group_not_found.
List groups
Query params
| Field | Type | Notes |
|---|---|---|
limitrequired | integer | Maximum number of items to return. Defaults to 20; maximum 100. range 1..100 |
starting_after | string | Opaque cursor from the previous response next_cursor. |
phone_number_id | string | Only groups created on this Tyxter phone number id. len 1..255 |
status | "pending" | "active" | "failed" | "deleting" | "deleted" | Only groups in this status. |
Requires groups:read. Lists the groups of the key's environment, newest first, with cursor pagination and optional phone_number_id and status filters; the response is object: "list" with data, has_more and next_cursor. A phone_number_id from another environment returns an empty page. An invalid or unknown parameter returns 400 invalid_groups_query, and a malformed cursor returns 400 invalid_cursor.
curl -X POST "https://api.tyxter.com/v1/groups" \
-H "authorization: Bearer $TYXTER_API_KEY" \
-H "content-type: application/json" \
-H "idempotency-key: $(uuidgen)" \
-d '{"phone_number_id":"'"$PHONE_NUMBER_ID"'","subject":"Support team"}'
curl "https://api.tyxter.com/v1/groups?status=pending&limit=20" \
-H "authorization: Bearer $TYXTER_API_KEY"Delete a group
Requires groups:write and honors Idempotency-Key: a replay with the same key returns the first response as it was sent, not the group's current status. Returns 202 with the GroupResponse; the call itself never reaches Meta. What happens depends on the group's status:
active: the group becomesdeleting, and a Tyxter worker deletes it (see Available today). Afailureleft by an earlier refused delete is cleared.failed: Meta never created the group, so it becomesdeletedat once, withdeleted_atset and no call to Meta; its createfailurestays readable.deletingordeleted: the group is returned unchanged and nothing starts again.pending:409 group_not_active, because Tyxter has not learned whether Meta created the group; delete it once it isactiveorfailed.
A deleted group stays readable with GET /v1/groups/{group_id} and listed by GET /v1/groups, with status deleted and deleted_at set. The delete keeps working when an organization owner or admin disables WhatsApp Business groups in feature controls, so you can always delete the groups you created. A group_id that looks like a personal WhatsApp group returns 422 personal_whatsapp_group_not_supported, as on retrieve (an invite link pasted unencoded returns 404 route_not_found), and any other id that does not exist or belongs to another organization, project or environment returns 404 group_not_found.
curl -X DELETE "https://api.tyxter.com/v1/groups/$GROUP_ID" \
-H "authorization: Bearer $TYXTER_API_KEY" \
-H "idempotency-key: $(uuidgen)"Reset the invite link
Requires groups:write and honors Idempotency-Key: a replay with the same key returns the first response as it was sent and never resets the link again. There is no request body. Returns 202 with the GroupResponse, still active and still showing the link the reset will replace; the call itself never reaches Meta, and a Tyxter worker resets the link afterwards (see Available today). Read the group with GET /v1/groups/{group_id} to see the new invite_link; there is no separate route to read the link, because it is a field of the group. After a failure, reset again.
- Only an
activegroup can be reset: apending,failed,deletingordeletedgroup returns409 group_not_activeand nothing is written. - A newer reset can replace an earlier queued reset before a worker starts it. While a reset worker is running, a new request returns
409 group_invite_link_reset_in_progressand nothing is written; retry after it finishes. A same-key replay still returns the original accepted response. - While the group is
deleting(a delete accepted while a reset is in progress), a new link Meta returns for the reset is still stored and the reset's outcome leavesfailureto the delete; in production a reset not yet sent to Meta when the delete is accepted is not sent (reset again if the delete is refused). - Tyxter knows the link only from its own records, so a link reset outside Tyxter (for example by calling Meta's API directly with your own app) is not seen, and the stored
invite_linkcan then be stale. 403 feature_disabled: WhatsApp Business groups are disabled for the environment in feature controls.
A group_id that looks like a personal WhatsApp group returns 422 personal_whatsapp_group_not_supported, as on retrieve (an invite link pasted unencoded returns 404 route_not_found), and any other id that does not exist or belongs to another organization, project or environment returns 404 group_not_found.
curl -X POST "https://api.tyxter.com/v1/groups/$GROUP_ID/invite-link/reset" \
-H "authorization: Bearer $TYXTER_API_KEY" \
-H "idempotency-key: $(uuidgen)"Participants
participants lists the group's current members, each with its wa_id (the participant's WhatsApp ID, as Meta reports it) and joined_at, oldest join first; participant_countis their number. Tyxter learns membership only from the participant events Meta sends (in sandbox, from the simulation below), never by reading the group from Meta. Events are told apart by participant, action and Meta's event time, which is in whole seconds: each distinct join or removal is recorded once, even when Meta delivers it twice, but two joins (or two removals) of the same participant in the same second count as one, so a leave and rejoin within one second loses the rejoin. Meta does not promise delivery order, so the newest event about a participant decides: a removal that arrives before the join that preceded it leaves the participant out, and a join and a removal in the same second are ordered by arrival. An event Tyxter cannot match to a group, or that fails inside Tyxter, is not applied, and the list can then differ from the group at Meta. A participant who leaves is removed from the list; a group that becomes deleted lists none. While a group is deleting, Meta's joins and removals still apply, and a refused delete keeps them.
Erasing a contact (DELETE /v1/contacts/{id}) removes, from every group in the contact's environment, each participant whose wa_idis exactly the contact's phone number with or without the leading +(for most Brazilian mobile numbers, also without the ninth digit), removes that participant's events from the listen routes, and clears the payload of the stored copies of those webhook events. A wa_id written any other way is not matched: for example an identifier Meta sends that is not the phone number, or a number WhatsApp writes differently from its international form (such as the extra 1in Mexican mobile numbers). Tyxter then no longer knows which of that participant's events it already recorded, so a later event about them, a repeated one included, is recorded again and can list them again.
The erasure does not immediately remove these copies of the participant's wa_id; each leaves on its own schedule:
- the stored reply to a groups request sent with an
Idempotency-Keyexpires 24 hours after the request, and until then a replay of that request can still return the erased participant; - Tyxter's captured copies of Meta's webhook deliveries are removed by a scheduled cleanup once they are 30 days old;
- Tyxter's raw record of each Meta group event is removed by a scheduled cleanup no sooner than 30 days after Tyxter hands it to its processing queue, and possibly later; a record Tyxter could not hand to its processing queue is kept with no scheduled deletion;
- a webhook delivery already being sent when the erasure completes is not recalled.
Simulate a participant (sandbox)
Request body
| Field | Type | Notes |
|---|---|---|
wa_idrequired | string | The simulated participant's WhatsApp ID, for example 5511999990000. len 1..64 |
actionrequired | "join" | "remove" | join adds the participant; remove removes it (as if the participant left). |
Sandbox keys only; requires groups:write and honors Idempotency-Key. Simulates Meta reporting that a participant joined (join) or left (remove) an active group and returns 200 with the GroupResponse, participants included; the call never reaches Meta. A join of a current member or a removal of a non-member changes nothing, so a retry never records the fact twice, with or without a key; a replay with the same key returns the first response.
400 sandbox_group_participant_sandbox_only: the key is not a sandbox key. In production, participants change only when Meta reports them.400 invalid_group_request: the body is not a JSON object,wa_idis missing, blank or longer than 64 characters,actionis notjoinorremove, or the body carries an unknown field;paramnames it.409 group_not_active: the group is notactive.409 group_participant_limit_reached: the group already has eight participants, the cap Meta documents (heard); simulate a removal first. Whether Meta also counts the business number is not known. Production applies no limit of Tyxter's own.403 feature_disabled: WhatsApp Business groups are disabled for the environment in feature controls.
A group_id that looks like a personal WhatsApp group returns 422 personal_whatsapp_group_not_supported, as on retrieve, and any other id that does not exist or belongs to another organization, project or environment returns 404 group_not_found.
JavaScript SDK
const eligibility = await client.groups.retrieveEligibility({
phone_number_id: phoneNumberId,
});
// eligibility.status: 'eligible' | 'not_eligible' | 'unknown' | 'not_checked' | 'read_failed'
const accepted = await client.groups.createEligibilityCheck(
{ phone_number_id: phoneNumberId },
{ idempotencyKey: crypto.randomUUID() },
);
// Poll retrieveEligibility until checked_at is later than accepted.check_requested_at.
// If that has not happened within your own timeout, the check did not complete:
// request a new one (new idempotency key).
const group = await client.groups.create(
{ phone_number_id: phoneNumberId, subject: 'Support team' },
{ idempotencyKey: crypto.randomUUID() },
);
// group.status === 'pending'. Sandbox: it becomes 'active' once the worker has run
// ('failed' if its number can no longer host a group by then). Production: today it
// stays 'pending' unless Meta refuses or Tyxter cannot send the create (see
// "Available today").
const same = await client.groups.retrieve(group.id);
const page = await client.groups.list({ status: 'pending', limit: 20 });
// Sandbox only: simulate a participant joining an active group.
const withMember = await client.sandbox.groups.simulateParticipant(
group.id,
{ wa_id: '5511999990001', action: 'join' },
{ idempotencyKey: crypto.randomUUID() },
);
// withMember.participants: [{ wa_id: '5511999990001', joined_at: '...' }]
const removed = await client.groups.delete(group.id, { idempotencyKey: crypto.randomUUID() });
// removed.status: 'deleting' for an active group, 'deleted' for a failed one;
// a pending group throws a TyxterApiError with code 'group_not_active'.
const resetting = await client.groups.resetInviteLink(group.id, {
idempotencyKey: crypto.randomUUID(),
});
// resetting.status === 'active' and still shows the old link; read the group
// with retrieve to see the new invite_link once the worker has run.