Shared Inbox Links
Shared inbox links let you expose one phone number's inbox to an external user through a public URL, without giving them your organization API key or admin access.
Each link is scoped to exactly one phoneNumberId, can be permanent or expiring, and carries fine-grained permissions for reading and replying.
Typical Flow
- Your server creates a shared inbox link with
POST /v1/shared-inbox-links - The API returns a
publicUrl - You send that URL to the external user
- The user opens the URL in the inbox frontend
- The frontend exchanges the public token for a short-lived shared session
- The user works inside
/shared/inboxwith only the permissions granted by the link
You do not need to generate tokens manually. Use the publicUrl returned by the API.
Create a Shared Inbox Link
curl -X POST https://api.example.com/v1/shared-inbox-links \
-H "Authorization: Bearer sk_org_..." \
-H "Content-Type: application/json" \
-d '{
"phoneNumberId": "660e8400-e29b-41d4-a716-446655440001",
"name": "Support vendor access",
"expiresAt": "2026-04-01T00:00:00.000Z",
"permissions": {
"readInbox": true,
"readDetails": true,
"markRead": true,
"sendText": true,
"sendMedia": false,
"sendTemplates": true,
"sendAdvanced": false
}
}'
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
phoneNumberId |
UUID | Yes | Internal phone UUID whose inbox will be shared |
name |
string | Yes | Display name for the shared link |
expiresAt |
ISO datetime or null |
No | When omitted or null, the link does not expire |
permissions |
object | Yes | Fine-grained permission set for the shared inbox |
Permissions
| Permission | Description |
|---|---|
readInbox |
List conversations and read messages |
readDetails |
View business/profile details and media side panels |
markRead |
Mark inbound messages as read |
sendText |
Send plain text replies |
sendMedia |
Upload and send image, video, audio, document, sticker |
sendTemplates |
List and send WhatsApp templates |
sendAdvanced |
Send interactive, flow, and CTA URL messages |
Response
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"organizationId": "440e8400-e29b-41d4-a716-446655440000",
"phoneNumberId": "660e8400-e29b-41d4-a716-446655440001",
"phoneNumber": "+5491155551234",
"name": "Support vendor access",
"publicUrl": "https://inbox.example.com/shared/inbox/sil_550e8400-e29b-41d4-a716-446655440999.signature",
"permissions": {
"readInbox": true,
"readDetails": true,
"markRead": true,
"sendText": true,
"sendMedia": false,
"sendTemplates": true,
"sendAdvanced": false
},
"status": "active",
"expiresAt": "2026-04-01T00:00:00.000Z",
"revokedAt": null,
"lastUsedAt": null,
"createdAt": "2026-03-24T10:00:00.000Z",
"updatedAt": "2026-03-24T10:00:00.000Z"
}
}
Send the returned publicUrl to the person who should access the inbox.
Common Presets
Read-only inbox
{
"readInbox": true,
"readDetails": true,
"markRead": false,
"sendText": false,
"sendMedia": false,
"sendTemplates": false,
"sendAdvanced": false
}
Standard reply inbox
{
"readInbox": true,
"readDetails": true,
"markRead": true,
"sendText": true,
"sendMedia": true,
"sendTemplates": true,
"sendAdvanced": false
}
Full composer
{
"readInbox": true,
"readDetails": true,
"markRead": true,
"sendText": true,
"sendMedia": true,
"sendTemplates": true,
"sendAdvanced": true
}
List Shared Inbox Links
curl "https://api.example.com/v1/shared-inbox-links?phoneNumberId=660e8400-e29b-41d4-a716-446655440001&status=active" \
-H "Authorization: Bearer sk_org_..."
Supported filters:
phoneNumberIdstatus=active,expired, orrevoked- pagination with
pageandlimit
Get One Shared Inbox Link
curl https://api.example.com/v1/shared-inbox-links/{sharedInboxLinkId} \
-H "Authorization: Bearer sk_org_..."
Use this when you need the current publicUrl, permissions, status, or last usage timestamp.
Update a Shared Inbox Link
You can update the display name, expiration date, and permissions.
curl -X PATCH https://api.example.com/v1/shared-inbox-links/{sharedInboxLinkId} \
-H "Authorization: Bearer sk_org_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Support vendor access - Q2",
"expiresAt": null,
"permissions": {
"readInbox": true,
"readDetails": true,
"markRead": true,
"sendText": true,
"sendMedia": true,
"sendTemplates": true,
"sendAdvanced": false
}
}'
Changes apply to future requests immediately. Existing shared sessions are revalidated against the link on every request.
Rotate the Public URL
Rotating a link generates a new publicUrl without changing the link ID.
curl -X POST https://api.example.com/v1/shared-inbox-links/{sharedInboxLinkId}/rotate \
-H "Authorization: Bearer sk_org_..."
Use this if the old URL was exposed to the wrong person.
Rotation changes the public URL, but existing shared sessions continue working until they expire or the link is revoked.
Revoke a Shared Inbox Link
curl -X DELETE https://api.example.com/v1/shared-inbox-links/{sharedInboxLinkId} \
-H "Authorization: Bearer sk_org_..."
Revocation is immediate. Existing shared sessions stop working on the next request.
This is a soft revoke, not a hard delete.
Public Access vs API Access
POST /v1/shared-inbox-linksand related CRUD endpoints are organization-authenticatedpublicUrlis for the inbox frontend user/shared-inbox/exchangeand/shared-inbox/sessionare internal support endpoints used by the frontend session flow
If you are building your own frontend, you can reproduce the same flow:
- open the
publicUrl - exchange the
sil_...token - store the returned shared session token
- use that session token as
Authorization: Bearer sis_...for shared inbox frontend calls