Skip to content
  • Secret keys (sk_…, psk_…) stay on your servers: in environment variables or a secret store, never in a browser, an app, a repository or a log. Anyone holding one acts as your integration.
  • Publishable keys (pk_…, ppk_…) may be public: they only start sessions, and only from their allowed origins (or app ids) together with a user token signed by your server.
  • Keys are shown once. Nexafon stores only a hash, so a lost key is replaced, not recovered.
  • Rotate by creating the new key, deploying it, then revoking the old one; a revoked key answers 401 at once. Use test keys (sk_test_…) everywhere except production.

A secret key acts with its scopes: the permissions you give it when you create it, never more than your own. Give each key only what its job needs. For keys that sign user tokens, the scopes are also the most an embedded user may do, so include what your users need in the embed (for example inbox:reply and calls:answer). The permissions:

Permission Lets the key Needs plan feature
audit:view See the workspace audit log
billing:manage Pay, top up, change seats
billing:view See plan, wallet and invoices
call_groups:manage Set how a team rings: strategy, order and timings
call_reports:view See who answered and missed calls, per call and per staff member
call_routing:manage Call menu drafts, schedules and holidays
calls:answer Take WhatsApp and team calls
calls:pickup_queue Pick any caller from a queue
channels:manage Numbers, templates, IVR, hours
commerce:manage Add, change and remove the store’s products
commerce:view See the store’s products
developers:manage API keys, webhooks, embeds
files:view Open stored files; each kind of file also needs its own permission
group_calls:start Call several staff members or a team at once
inbox:assign_others Assign conversations to teammates
inbox:reply Send messages and templates
internal_calls:start Call one staff member inside Nexafon
meetings:create Schedule voice meetings and run the ones you host
meetings:manage Change, cancel and end any meeting and see its attendance
numbers:manage Connect the business WhatsApp number
onboarding:manage Run the setup wizard and see the setup checklist
orders:manage Accept, update and cancel orders
orders:view See the store’s orders
payments:manage Take and refund customer payments
queue:pickup Pick up a waiting caller or take the next one from a queue
recordings:download Download recordings
recordings:listen Play call recordings
recordings:manage Record, upload, replace and delete call audio
recordings:view Hear the call audio library
reports:detail See every report tab, agents and team calls, scoped to the teams you lead
reports:schedule Schedule reports by email
reports:view See team and call reports
team:manage Invite, change roles, remove
team:view See members, their roles and invitations
templates:manage Create, edit, delete and sync WhatsApp templates
templates:send Send approved WhatsApp templates

A secret key can be limited to your servers’ IP addresses or ranges; calls from anywhere else are refused.

Two lists protect the embed, and a page must be on both:

List Where Protects
A publishable key’s allowed origins Developers → API keys Which sites may start sessions with the key (client_not_allowed)
The workspace’s embed domains Developers → Embed domains Which sites may frame Nexafon’s screens: Nexafon sends them as the CSP frame-ancestors of its embed pages, so browsers refuse to show the frames elsewhere

Enter origins as scheme and host (and port), such as https://portal.example.com, without a path. A workspace has at most 20 embed domains. For partners, the partner’s domains serve as both lists for every store.

If your site sends a Content-Security-Policy, allow the loader script and Nexafon’s frames:

Content-Security-Policy: script-src 'self' https://app.nexafone.so/embed; frame-src https://app.nexafone.so

The SDK needs nothing else from your page: the frames talk to Nexafon themselves, and getUserToken calls your own server. With popOutCalls, pop-ups from your site must be allowed for calls to move to the pop-out window.

  • The user token is short-lived (at most 10 minutes) and works once; fetch a new one for every getUserToken call. Answer 401 from your token endpoint when nobody is signed in, 403 to signed-in users who are not your staff (a token can make its user a member of your workspace, so never sign for customers who signed up), and send Cache-Control: no-store.
  • The SDK session lives only in the memory of Nexafon’s frames: nothing is written to your site’s localStorage, sessionStorage or cookies, and your scripts never see the session token.
  • Every message between your page and the frames checks the sender’s origin and the protocol version.
  • Signing out of your product should end Nexafon too: call Nexafon.destroy().

Verify every delivery’s signature against the raw body, reject old timestamps, and dedupe on the event id. Keep each endpoint’s secret like a secret key, and rotate it with the overlap window.

Every request runs inside the workspace it belongs to; ids from other workspaces answer 404. Tenant secrets such as WhatsApp and PayPoint keys are encrypted at rest and never returned by the API.