- Display fields: show a name and avatar for an anonymous customer
- Signature: sign a signed-in customer’s email and identifiers on your server
- Email verification: ask the customer to verify an email in the widget
Pass display fields
A customer is anonymous until you provide and prove an email. You can still pass display fields oncustomerDetails in Plain.init. Plain doesn’t treat those fields as proof of who the customer is:
Sign a known customer
Use this when the customer is already signed in to your product and you know their email. The signature covers the email, plusexternalId and tenantIdentifier when you send them. externalId is your ID for the customer. tenantIdentifier is { tenantId: 'ten_0123456789' } or { externalId: 'acme' } for their account.
1
Generate a chat secret
Go to Settings → Chat, open the chat app, and click Generate secret. Keep the secret on your server, never in the browser. Clicking Re-generate secret invalidates the current secret, and signatures from the old secret stop verifying.
2
Build the signature on your server
The signature is a Hash-based Message Authentication Code (HMAC). Sign the message with HMAC-SHA256 and your chat secret, then hex-encode the digest.With no With either identifier, the message is JSON. Sort the keys alphabetically at every level, and set This TypeScript example builds that message and returns the signature.
externalId and no tenantIdentifier, the message is the email itself:v to the number 1:JSON.stringify drops identifiers you leave undefined and keeps the key order shown:Test vectors
Test vectors
Compare your function to these signatures. Each one uses the secret Sign Sign Sign Sign
chat_secret_example. Each block shows the exact message, then its lowercase hex signature. A space or line break in the message changes the signature.Sign ada@example.com with no identifiers:ada@example.com and externalId user_123:ada@example.com and tenantIdentifier { externalId: 'acme' }:ada@example.com and tenantIdentifier { tenantId: 'ten_0123456789' }:ada@example.com, externalId user_123, and tenantIdentifier { externalId: 'acme' }:3
Pass the details and signature to the widget
Pass Fetch a new payload when the email or the identifiers change. Plain rejects the request when
customerDetailsSignature next to customerDetails. The values in customerDetails must match the ones you signed. In this example, fetchCustomerFromBackend calls your own endpoint, which returns { customerDetails, customerDetailsSignature } for the signed-in customer, so the details and the signature come from one place.externalId or tenantIdentifier differs from what you signed.Verify an unknown email
SetrequireAuthentication when the customer isn’t signed in and you want an email before they can chat. This fits a public page where you don’t manage sign-in. You can pair this option with the Require email verification setting in Settings → Chat.

