Server credentials and IP allowlist
Before your server calls the server REST API (OpenAPI), it exchanges the app's Client ID and Client Secret for an App Token; see Authentication and App Token. This page covers viewing, rotating and revoking these credentials in the console, and using an IP allowlist to limit which servers can call OpenAPI.
Credentials are managed in the "Server secret" tab of app details, and the IP allowlist in the "IP allowlist" tab. Every member can view them; changes need owner or admin.
Credentials and slots
When an app is created (including the demo app created at sign-up), the system generates its first credentials; see Create an app. The console list only shows the first few characters of the Secret, so you can tell which is which. Any member can click "View" under "Access credentials" on the Overview and verify their identity again to see the full current Secret. Older Secrets created without a recoverable encrypted copy, and imported Secrets, can't be viewed again; rotate if you need one.
Each app has two slots, primary and secondary, each holding at most one valid Secret, so an app has at most two valid Secrets at once. Both slots work the same; there are two so you can replace the Secret without downtime, with old and new valid together for a while. For system-generated credentials, an app's Client ID stays the same, and rotation only replaces the Secret.
The credential list under "Server secret":
| Column | Description |
|---|---|
| client_id | The Client ID used to get an App Token |
| Secret prefix | The first characters of the Secret: 8 for system-generated, 4 for imported |
| Slot | primary or secondary |
| Source | Generated by the system, or imported when migrating from another provider |
| Status | Valid, revoked or expired. Only valid Secrets can get an App Token |
| Expires | A valid Secret stops working at this time; "Never" means it doesn't expire |
| Last used | The last time it was used to get an App Token, updated at most hourly; use it to see whether an old Secret is still in use |
| Created | When the Secret was created |
Rotate the secret
Rotate to replace the Secret regularly, or when you suspect it leaked. owner or admin clicks "Rotate secret" under "Server secret" and verifies their identity again as prompted:
- The system generates a new Secret in the free slot, effective immediately. The page shows the new client_id and client_secret; save them to your server right away, then click "I've saved them". You can view it again later on the Overview.
- The other still-valid Secret enters a 24-hour grace period: both old and new Secrets can get App Tokens during it, and when it ends the old Secret stops working, along with the App Tokens it obtained.
To replace the Secret without downtime:
- Click "Rotate secret" and save the new Secret.
- Update your server's config to the new Secret and get new App Tokens with it.
- Once the old Secret's "Last used" stops changing in the list, click its "Revoke", or let the grace period end.
You can't rotate while both slots hold valid Secrets; the page says "Both secret slots are in use, revoke one first". Confirm which one is no longer used, revoke it, then rotate.
Revoke a secret
owner or admin can click "Revoke" on a valid Secret's row and verify their identity again as prompted. After revoking:
- The Secret can no longer get App Tokens.
- App Tokens obtained with it stop working immediately, and calls to OpenAPI return
401 unauthenticated; App Tokens from the other Secret aren't affected. - If the other Secret is in its grace period, the grace period is cancelled and it stays valid indefinitely, so the app isn't left without a usable Secret when the grace period would have ended.
The app's last valid Secret can't be revoked; the page says "Can't revoke the last valid secret". Rotate first if you need to replace it.
If you suspect a leaked Secret
Rotate to a new Secret right away, switch your server to it, then revoke the old one. Revoking invalidates every App Token the old Secret obtained, so the leaked credentials stop working immediately. We also recommend setting up the IP allowlist below.
Import credentials from another provider
When migrating from another IM service and your server is already configured with the old Client ID and Client Secret, you can import them into the app and keep getting App Tokens with them, without redistributing credentials.
- The imported Client ID and Secret stay exactly as they were and take a free slot; if both slots are used, revoke one first.
- The Client ID is 1 to 128 characters and the Secret 16 to 256 characters, both only visible ASCII characters without spaces.
- Imported Secrets can't be viewed afterward either; the list only shows their first 4 characters.
- Importing needs
owneroradminand identity verification. Imported credentials can be revoked like any other.
Importing only keeps the credentials themselves: the org_name is system-generated, so the AppKey and OpenAPI addresses change, and servers and clients still have to switch to the new address and AppKey.
Where it is in the console
The "Server secret" page currently only offers rotate and revoke; importing is coming soon. If you need to keep the old credentials when migrating, contact us.
IP allowlist
The IP allowlist limits which source IPs can get App Tokens and call OpenAPI. Once set, servers elsewhere can't call it even if the credentials leak. We recommend adding all your servers' public egress IPs.
- Only servers are limited: the allowlist only checks the source IP of App Token requests and OpenAPI requests. It doesn't affect clients (apps, web pages) signing in and messaging, or the console.
- No limit without active entries: when the app has no active entry (enabled, past its start time and not expired), every IP is allowed.
- With active entries, only the allowlist gets through: as soon as one entry is active, requests from IPs not in any active entry get
403 ip_not_allowed.
In the "IP allowlist" tab, click "Add" and fill in:
| Field | Description |
|---|---|
| IP or range | A single IP, such as 203.0.113.10 or 2001:db8::10, or a CIDR range, such as 203.0.113.0/24 or 2001:db8::/32 |
| Note | Optional, up to 256 characters, such as "Production egress" |
| Expires | Optional; after this time the entry stops working, which suits opening an address temporarily. Without it the entry lasts indefinitely |
Addresses are normalized when added: a single IP is saved as a /32 (/128 for IPv6) range, ranges drop their host bits (203.0.113.77/24 is saved as 203.0.113.0/24), and IPv4-mapped IPv6 addresses (such as ::ffff:198.51.100.9) are saved as IPv4. The same range can't be added twice; ranges can't be edited after adding, so delete and add again to change one.
Each entry in the list can be:
- Enabled: turn the switch off to pause the entry without deleting it.
- Deleted: removed immediately.
The "Starts" and "Expires" columns are when the entry takes effect and expires: entries added in the console take effect immediately, shown as - under "Starts"; "Never" under "Expires" means it lasts indefinitely. Expired entries aren't deleted automatically but no longer apply.
After you change the allowlist, App Token requests are checked against it immediately, and other OpenAPI requests within 30 seconds at most. Each app can have up to 200 entries (including disabled and expired ones); delete ones you no longer need when you reach that.
Before adding the first entry
Once the first entry is active, servers outside the allowlist immediately can't call OpenAPI. Before adding it, confirm every egress IP of your servers, including multiple servers, NAT gateways and proxies; when debugging from your own machine, remember to add its egress IP too, or use a separate test app.
