Identity Callback URL
The most private option: no user data is embedded in the widget at all. When a session begins, Buddy POSTs the session id to your endpoint, signing the request so you can verify it really came from the platform. You respond with the user's attributes.
Flow
- A session starts in the widget (no user token needed).
- Buddy POSTs
{ sessionId, agentId, timestamp }to your callback URL. - The request carries an
X-Platform-SignatureHMAC of the exact body, using your callback secret. - You verify the signature, look up the user for that session, and return their attributes.
The request Buddy sends
POST /buddy/identity HTTP/1.1
Content-Type: application/json
X-Platform-Signature: <hex HMAC-SHA256 of the raw body>
{ "sessionId": "sess_…", "agentId": "agt_…", "timestamp": 1717000000 }
Response shape
Return JSON with at least a userId. Optional email, role and a customAttributes object are mapped through.
{
"userId": "user_123",
"email": "ada@example.com",
"role": "customer",
"customAttributes": { "plan": "pro", "lifetimeValue": 4200 }
}
Verify the signature
// Express — verify the request really came from Buddy.
import crypto from 'node:crypto';
app.post('/buddy/identity', express.text({ type: '*/*' }), (req, res) => {
const expected = crypto
.createHmac('sha256', process.env.BUDDY_CALLBACK_SECRET)
.update(req.body) // the raw body bytes, verbatim
.digest('hex');
const got = req.get('X-Platform-Signature') || '';
if (got.length !== expected.length ||
!crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))) {
return res.status(401).end();
}
const { sessionId } = JSON.parse(req.body);
const user = lookupUserForSession(sessionId);
res.json({ userId: user.id, email: user.email, role: user.role });
});
Troubleshooting
| Code | Meaning & fix |
|---|---|
AUTH_CALLBACK_TIMEOUT | Your endpoint didn't respond in time. Buddy retries once, then falls back to anonymous. Keep the handler fast. |
AUTH_CALLBACK_FAILED | Non-2xx response or unreachable URL. Confirm the URL is public HTTPS. |
AUTH_CALLBACK_BAD_RESPONSE | Response had no userId. See the response shape. |