A WhatsApp group invite link looks like ordinary text:
https://chat.whatsapp.com/...
Operationally, it behaves more like a credential.
Anyone who receives it may be able to forward it, publish it, store it in a ticket, or turn it into a QR code. Resetting the link in WhatsApp does not automatically remove old copies from your application.
When building an invite-link workflow, keep four operations separate:
Read the current link
Share the link
Review join requests
Reset the link
With UnifyPort, the documented API retrieves the current WhatsApp group invite link. It does not document an API operation that resets the link.
That boundary should be visible in both your backend and operator interface.
Read and reset are different operations
To retrieve the current link, use:
GET /v1/accounts/{account_id}/groups/invite-code
The group identifier is supplied as a query parameter:
group_id
A successful response includes:
data.invite_url
data.invite_code
Calling this endpoint is a read operation.
It does not imply that:
- a new invite link was created;
- the previous link was invalidated;
- the group’s join policy changed;
- a pending requester was approved;
- WhatsApp confirmed that the link was distributed.
WhatsApp provides a native administrator action for deactivating an existing invite link and creating a new one. That native reset is separate from the UnifyPort retrieval endpoint.
Understand the identifiers
The workflow involves several identifiers that should not be interchanged.
| Value | Meaning |
|---|---|
account_id |
The connected messaging account performing the action |
group_id |
The provider’s group identifier |
data.invite_url |
The current invitation URL returned by the API |
data.invite_code |
The invitation code contained in the returned result |
request_id |
Diagnostic identifier for the API request |
The invite code is not the group ID.
Do not construct a group identifier from the invite code, and do not construct an invite URL by appending the group ID to a guessed URL prefix.
Use the values returned by the documented endpoints.
Select the account and group together
A group operation needs both:
Connected account
+
Selected group
The same display name can appear on multiple groups, so avoid selecting a group by title alone.
Start with the List Groups endpoint and retain the selected item’s provider ID.
Conceptually:
const selection = {
accountId: "acc_8c21d0",
groupId: "120363041234567890@g.us",
displayName: "Customer Community",
};
Treat accountId and groupId as one selection boundary. A group ID copied from another account may not be meaningful or authorized under the selected account.
The connected account must also have the required WhatsApp group permissions. Workspace API access does not create group-admin authority.
Retrieve the link from the backend
The authenticated request should run on your server:
curl --get \
"https://api.unifyport.ai/v1/accounts/${UNIFYPORT_ACCOUNT_ID}/groups/invite-code" \
-H "X-Api-Key: ${UNIFYPORT_API_KEY}" \
--data-urlencode "group_id=${WHATSAPP_GROUP_ID}"
Query encoding matters because provider identifiers may contain characters such as @.
Do not put the UnifyPort API key in:
- browser JavaScript;
- mobile application bundles;
- URLs;
- analytics properties;
- screenshots;
- support tickets;
- source control.
Your frontend should call an application endpoint protected by your own authorization layer.
For example:
Browser
↓
Your authenticated backend
↓
UnifyPort API
↓
Your backend returns only the approved result
A small server-side helper
async function getWhatsAppGroupInviteLink({
accountId,
groupId,
}) {
if (!accountId || !groupId) {
throw new Error("accountId and groupId are required");
}
const query = new URLSearchParams({
group_id: groupId,
});
const response = await fetch(
`https://api.unifyport.ai/v1/accounts/${encodeURIComponent(
accountId,
)}/groups/invite-code?${query}`,
{
headers: {
"X-Api-Key": process.env.UNIFYPORT_API_KEY,
},
},
);
const body = await response.json();
if (!response.ok) {
throw new InviteLinkError({
status: response.status,
code: body.error?.code ?? "unknown_error",
requestId: body.request_id ?? null,
});
}
const inviteUrl = body.data?.invite_url;
const inviteCode = body.data?.invite_code;
if (!inviteUrl || !inviteCode) {
throw new Error("Invite-link response is incomplete");
}
return {
inviteUrl,
inviteCode,
retrievedAt: new Date().toISOString(),
};
}
Avoid logging body in full because it contains the invite URL.
A safer error type keeps only diagnostic metadata:
class InviteLinkError extends Error {
constructor({ status, code, requestId }) {
super(`Invite-link request failed: ${status} ${code}`);
this.status = status;
this.code = code;
this.requestId = requestId;
}
}
The server’s request_id can help with troubleshooting. It is not a replacement for application authorization or an idempotency key.
Treat the invite URL as sensitive data
An invite URL is designed to be shared, but that does not mean it should be public by default.
Apply an explicit permission check before retrieval:
async function showGroupInviteLink({
operator,
accountId,
groupId,
}) {
await assertPermission(operator, {
action: "group.invite_link.read",
accountId,
groupId,
});
return getWhatsAppGroupInviteLink({
accountId,
groupId,
});
}
Consider separate permissions for:
group.invite_link.read
group.invite_link.copy
group.invite_link.distribute
group.invite_link.reset_native
Reading and distributing the link are different levels of access.
An operator may need to verify that a link exists without being authorized to send it outside the organization.
Design separate interface controls
Avoid one ambiguous button labeled:
Manage Invite
Use controls that describe the exact action:
| Control | Behavior |
|---|---|
| Show current link | Retrieve and display the current API result |
| Copy link | Copy the currently displayed URL |
| Open join requests | Enter the moderation workflow |
| Reset link in WhatsApp | Explain or initiate the native administrator procedure |
| Refresh after reset | Retrieve the current link again |
This makes it harder for operators to assume that reading the link rotated it.
A safe UI might show:
Current invite link
Retrieved: 2026-10-15 10:31 UTC
[Reveal] [Copy]
Resetting is performed by a group administrator in WhatsApp.
After reset, click “Refresh current link.”
Do not label a cached value simply as “Current” unless it was freshly retrieved.
Prefer:
Previously retrieved link
Last checked 18 minutes ago
Avoid leaking links through observability
Invite links can escape through systems that were never intended to distribute them.
Audit:
- application logs;
- reverse-proxy access logs;
- frontend error reporting;
- analytics events;
- session replay tools;
- support screenshots;
- exception traces;
- clipboard telemetry;
- database query logs.
This log statement is unsafe:
logger.info("invite_link_loaded", {
accountId,
groupId,
inviteUrl,
});
Prefer metadata:
logger.info("invite_link_loaded", {
accountId,
groupId,
operatorId,
retrievedAt: new Date().toISOString(),
});
If you need to correlate a specific returned value internally, use a one-way fingerprint rather than writing the complete link:
import { createHash } from "node:crypto";
function fingerprintInviteUrl(inviteUrl) {
return createHash("sha256")
.update(inviteUrl)
.digest("hex")
.slice(0, 12);
}
A fingerprint can confirm that an application-held value changed without exposing the URL itself.
Do not silently restore stale cached links
Suppose the API request fails.
This fallback is dangerous:
try {
return await getWhatsAppGroupInviteLink(input);
} catch {
return database.getCachedInviteLink(input.groupId);
}
The cached URL may have been invalidated through a native reset.
Showing it as current creates false confidence and may continue distributing a dead or compromised link.
Use an explicit result:
{
"state": "unavailable",
"lastKnownRetrievedAt": "2026-10-14T08:20:00Z"
}
If you display a cached value at all, label it clearly:
Last known link — current validity has not been verified
For sensitive workflows, keeping distribution paused is safer than silently falling back.
Reset the link through the documented native flow
UnifyPort’s public API reference documents invite-link retrieval, not reset.
Do not invent an endpoint such as:
POST /v1/accounts/{account_id}/groups/invite-code/reset
Do not send guessed parameters such as:
{
"reset": true
}
When an invite link must be invalidated:
- Stop distributing the application’s stored copy.
- Have an authorized group administrator reset the link in WhatsApp.
- Retrieve the link again through the API.
- Verify that the freshly retrieved value is the expected one.
- Replace every application-controlled copy.
- Review external distribution surfaces separately.
This is an operational sequence, not an atomic API transaction.
Refresh application state after reset
A native reset does not automatically update:
- your database;
- generated QR codes;
- onboarding emails;
- support macros;
- internal documentation;
- partner portals;
- printed materials;
- third-party automation.
After the administrator completes the reset, retrieve the current link again:
async function refreshStoredInviteLink({
operator,
accountId,
groupId,
}) {
await assertPermission(operator, {
action: "group.invite_link.refresh",
accountId,
groupId,
});
const current = await getWhatsAppGroupInviteLink({
accountId,
groupId,
});
const fingerprint = fingerprintInviteUrl(
current.inviteUrl,
);
await database.groupInviteLinks.upsert({
accountId,
groupId,
encryptedInviteUrl: await encrypt(current.inviteUrl),
fingerprint,
retrievedAt: current.retrievedAt,
retrievedBy: operator.id,
});
return {
fingerprint,
retrievedAt: current.retrievedAt,
};
}
If your application stores the URL, encrypt it appropriately and restrict access.
The operator interface does not always need the raw value after storage. It may only need to confirm that the refreshed fingerprint differs from the previous one.
Track application-owned distribution
You cannot necessarily recall every link another person forwarded, but you can track surfaces your application controls.
For example:
const distribution = {
accountId: "acc_8c21d0",
groupId: "120363041234567890@g.us",
linkFingerprint: "5e9128f1b448",
channel: "customer_onboarding_email",
distributedBy: "operator_42",
distributedAt: "2026-10-15T10:42:00Z",
};
After reset, query records using the previous fingerprint and identify content that needs replacement.
Do not store the full invite URL in every distribution record. A fingerprint and reference to encrypted central storage is usually safer.
Link sharing is not join approval
Retrieving or sharing a link does not mean a person has joined the group.
It also does not approve a pending requester.
Keep moderation separate:
Invite-link retrieval
↓
Link distribution
↓
Person requests or attempts to join
↓
Pending-request reconciliation
↓
Moderator approves or rejects
If the group uses join approval, build that as a separate queue with its own:
- requester identifiers;
- moderator authorization;
- decision state;
- audit records;
- retries;
- reconciliation.
Do not infer membership from a copy action or link retrieval.
Handle errors without inventing conclusions
A failed invite-link read does not prove that:
- the group was deleted;
- the account was removed;
- the invite was reset;
- the operator lacks permission;
- WhatsApp is unavailable.
Record the evidence:
HTTP status
Machine-readable error code
request_id
Account ID
Group ID
Timestamp
Then branch according to the documented error.
For example, get_group_invite_code_failed describes a failed retrieval. It is not evidence that the group no longer exists.
Leave the UI in an unavailable state until the cause is known.
Provider support remains explicit
The documented action applies to the supported WhatsApp provider path.
A shared group API does not mean invite-link retrieval works identically for:
- LINE;
- Telegram;
- Zalo;
- TikTok;
- X;
- separate WhatsApp provider implementations.
Check the current provider action support matrix before enabling the control.
If the provider is unsupported, hide or disable the action rather than retrying it as a transient failure.
Suggested acceptance tests
Before production, test:
- [ ] The correct connected account and group are selected together.
- [ ] Duplicate group names do not select the wrong provider ID.
- [ ] A group ID containing
@is query-encoded correctly. - [ ] The API key never reaches browser code.
- [ ] Unauthorized operators cannot reveal the link.
- [ ] Copy permission is separate from read permission where required.
- [ ] Logs do not contain the invite URL or code.
- [ ] Analytics do not collect the link.
- [ ] Missing response fields produce an unavailable state.
- [ ] Cached values are labeled as previously retrieved.
- [ ] A failed refresh does not silently restore an old link.
- [ ] A native reset is followed by a fresh API read.
- [ ] Application-generated QR codes are replaced after reset.
- [ ] Distribution surfaces can be found by link fingerprint.
- [ ] Join approval remains a separate workflow.
- [ ] Unsupported providers do not expose the control.
A practical state model
Represent invite-link state explicitly:
unknown
↓
retrieving
├── available
├── unavailable
└── stale
During native reset:
available
↓
distribution_paused
↓
native_reset_pending
↓
refreshing
├── available
└── unresolved
This is safer than one database column named:
invite_link
The state tells operators whether the stored value is safe to distribute.
Takeaway
A WhatsApp group invite link is a sensitive distribution capability, not just a string.
Keep these actions separate:
Read
Share
Moderate
Reset
Refresh
The UnifyPort endpoint retrieves the current link. It does not document link rotation.
When a reset is required:
Pause distribution
↓
Reset natively in WhatsApp
↓
Retrieve the current link again
↓
Replace controlled copies
↓
Review external distribution
Do not invent a reset endpoint, expose the API key to the browser, log the returned link, or silently present stale cached data as current.
References
- WhatsApp: Create and invite into a group
- UnifyPort: Get group invite link
- UnifyPort: List groups
- UnifyPort: Provider action support
- UnifyPort: Error reference
- UnifyPort: Request tracing
- WhatsApp join-request approval queue
This article was adapted from an original UnifyPort technical guide with AI-assisted editing.
Top comments (0)