Issuing Widget Tokens
An init token is a short-lived, signed credential your server issues and passes to the Publisher Widget. When the widget iframe loads it exchanges the init token for a widget session.
Always issue init tokens on your server. Never expose your widget_secret to the browser.
Endpoint
POST /widget/tokensAuthentication: No Bearer token required. The endpoint expects widget credentials via HTTP Basic auth:
Authorization: Basic BASE64(widgetId:widgetSecret)The API validates that the widget is active, its owning app is active, and all enabled platforms are verified before issuing a token.
Request Body
{
"external_user_id": "usr_abc123",
"ttl": 300,
"meta": {
"name": "Jane Doe",
"email": "[email protected]",
"avatar_url": "https://example.com/avatar.jpg"
}
}| Field | Type | Required | Description |
|---|---|---|---|
external_user_id | string | ✓ | Your system’s identifier for this user. Stored in the widget session log. |
ttl | integer | — | Token lifetime in seconds. Min 60, default 300, max 900. |
meta.name | string | — | Display name shown inside the widget. |
meta.email | string | — | User email (informational only). |
meta.avatar_url | string | — | Avatar URL shown inside the widget. |
Response
The Palactix API returns the raw init token in the init_token field. Example response from the Palactix API:
{
"init_token": "<signed-encrypted-string>",
"expires_at": "2026-01-01T12:05:00Z"
}Your server should extract init_token and return a small JSON object to the browser such as { "token": "<init_token>" } — the widget initializer expects the frontend payload to contain token.
Server Examples
Node.js
// Using native fetch (Node 18+)
async function getInitToken(userId: string): Promise<string> {
const credential = Buffer.from(`${process.env.PALACTIX_WIDGET_ID}:${process.env.PALACTIX_WIDGET_SECRET}`).toString('base64');
const res = await fetch('https://api.palactix.com/widget/tokens', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${credential}`,
},
body: JSON.stringify({
external_user_id: userId,
ttl: 300,
meta: { name: 'Jane Doe', email: '[email protected]' },
}),
});
if (!res.ok) throw new Error(`Palactix API error: ${res.status}`);
const body = await res.json();
// Palactix returns `init_token` — return the token string for use by your frontend
return body.init_token as string;
}
// Next.js Route Handler example
// app/api/publisher-token/route.ts
export async function GET(req: Request) {
const session = await getSession(req); // your auth
const initToken = await getInitToken(session.userId);
// Return a small JSON payload to the browser. The widget expects `{ token }`.
return Response.json({ token: initToken });
}Token lifetime guidance
| Scenario | Recommended TTL |
|---|---|
| Token rendered into server-side HTML | 120s — page loads are fast, minimal replay window |
| Token fetched via AJAX on button click | 300s (default) — gives the user time to interact |
| Token fetched ahead of time | 600s — useful for SPAs that pre-warm the widget |
Tokens are single-use inside an origin check — once exchanged for a session they cannot be replayed.