Get Started
Authenticated Embeds
Automatically sign website users into embeds using a short-lived signed ES256 JWT.
Related In Learn
Embeds
Add your agents directly to any website with embed code snippets.
Authenticated Embeds let you place a Pickaxe embed on your own website and automatically sign in visitors who are already logged into your app.
Pickaxe handles the final session creation for the embed. Your website only needs to prove the visitor's identity by returning a short-lived signed JWT.
Important: this system uses a signed JWT, not an encrypted JWT.
What Your Website Must Implement
Your website needs four pieces:
- A normal logged-in session for your own users.
- A server-side ES256 private key stored securely on your backend.
- A backend endpoint that returns a short-lived signed JWT for the current logged-in user.
- A frontend
getJwtfunction insidewindow.PickaxeConfigso the embed can request that JWT.
Your website does not need to exchange the JWT for a Pickaxe session token itself. The Pickaxe embed runtime does that automatically.
Workspace Setup In Pickaxe
Open Workspace Settings > Embed SSO and configure:
Enable customer-authenticated embeds: turn this on.Trusted issuer: the exact issuer string your backend signs into the JWT, for examplehttps://app.example.com.Signing key ID: the exactkidvalue your backend puts in the JWT header, for examplecustomer-key-2026-04.Public key: the PEM-encoded public key matching your backend private key.Allowed host origins: every website origin where the embed will run, for examplehttps://app.example.comorhttps://portal.example.com:8443.
Origin format rules:
- Include protocol:
https://app.example.com - Include port when needed:
https://app.example.com:3000 - Do not include a path: use
https://app.example.com, nothttps://app.example.com/account - Avoid issuer mismatches caused by trailing slash differences
Also make sure the deployment itself allows the same website domain in its normal embed domain allowlist. Embed SSO does not replace the deployment domain check.
JWT Requirements
Header
Use this JWT header shape:
{
"alg": "ES256",
"kid": "customer-key-2026-04",
"typ": "JWT"
}
Required Claims
Use these claims in the JWT payload:
{
"iss": "https://app.example.com",
"aud": "pickaxe-embed",
"sub": "user_123",
"customer_id": "YOUR_WORKSPACE_ID",
"email": "user@example.com",
"external_user_id": "user_123"
}
These are the minimum identity claims your website should send.
Field rules:
iss: must exactly matchTrusted issuerin Pickaxe.aud: must be exactlypickaxe-embed.sub: should be a stable external user identifier from your system.customer_id: should be your Pickaxe workspace ID.email: should be the end user's real email address.external_user_id: should usually matchsub.
Frontend Example
Add the embed bundle, container, and getJwt function on your page:
<script>
window.PickaxeConfig = {
"deployment-YOUR_DEPLOYMENT_ID": {
sso: {
getJwt: async ({ deploymentId, studioId, pickaxeId }) => {
const response = await fetch("/api/pickaxe/embed-sso-token", {
method: "POST",
credentials: "include",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
deploymentId,
studioId,
pickaxeId,
}),
});
if (!response.ok) return null;
const data = await response.json();
return data.token || null;
},
},
},
};
</script>
<script src="https://studio.pickaxe.co/api/embed/bundle.js" defer></script>
<div id="deployment-YOUR_DEPLOYMENT_ID"></div>
The getJwt function receives:
deploymentIdstudioIdpickaxeId
It should return:
- a signed JWT string when the visitor is logged in
nullwhen the visitor is not logged in or your site does not want to auto-sign them in
If you want one shared handler for all embeds on the page, you can also define window.PickaxeConfig.sso.getJwt globally instead of attaching it to one deployment ID.
Backend Example Contract
Your backend endpoint can use any internal route you want. A common pattern is:
Request
POST /api/pickaxe/embed-sso-token
{
"deploymentId": "deployment-YOUR_DEPLOYMENT_ID",
"studioId": "studio-123",
"pickaxeId": "pickaxe-123"
}
The endpoint should:
- read the current logged-in website user from your own cookie or session
- reject the request if the browser is not logged in
- build a short-lived JWT for that user
- sign it with your private ES256 key
- return the signed JWT
Response
{
"token": "SIGNED_JWT_HERE"
}
Important security rules:
- Keep the private key on the server only.
- Never put the private key in frontend JavaScript.
- Do not return a long-lived token.
- Do not send passwords or raw login credentials to Pickaxe.
What Pickaxe Does After getJwt
Once your frontend returns the signed JWT:
- The embed sends that JWT to Pickaxe.
- Pickaxe verifies the signature using the public key from your workspace settings.
- Pickaxe checks issuer, audience, expiry, key ID, and origin.
- Pickaxe finds or creates the matching studio user.
- Pickaxe creates the final Pickaxe session token for the embed.
- The embed stores and uses that Pickaxe session automatically.
Your website does not need to handle the Pickaxe session token directly.
Quick Checklist
- Create an embed deployment and allow your website domain.
- Turn on
Workspace Settings > Embed SSO. - Add issuer, key ID, public key, and allowed origins.
- Generate ES256-signed JWTs on your backend.
- Return those JWTs from a backend endpoint for the current logged-in user.
- Implement
window.PickaxeConfig.sso.getJwtorwindow.PickaxeConfig[deploymentId].sso.getJwt. - Mount the normal Pickaxe embed bundle and deployment
<div>.
If getJwt returns null, the embed can still fall back to its normal auth flow.
