API keys and session tokens
What each credential can do, how long it lasts, and what revoking does.
Nuance uses two credentials, so the secret one never reaches a browser.
| API key | Session token | |
|---|---|---|
| Looks like | nk_… | st_… |
| Where it lives | Your server | Your page or app |
| Made by | You, on the platform | Your server, with POST /session-tokens |
| Lasts | Until you revoke it | One conversation |
| Can | Mint session tokens, list and end your conversations, read transcripts | Start and run one conversation |
API keys
Create and revoke API keys on the Nuance platform. A key belongs to your organization, is shown once when you create it, and goes in requests as a bearer token: Authorization: Bearer nk_…. Your plan sets how many live keys you can hold; get your usage shows it as limits.api_keys.
The platform asks you to accept the API Developer Agreement and the Acceptable Use Policy when you first sign in, before you can make a key. Until the account that made your API key has accepted them, starting a conversation answers 403 legal_required (Errors).
Session tokens
Your server mints a token with POST /session-tokens and hands it to the page or app. An endpoint your page calls for one:
// On your server: an endpoint your page or app calls to get a session token
// for a Nuance Live conversation.
// A web-standard handler, so it runs as a Next.js route handler, on Bun,
// Deno or a Cloudflare Worker as written.
const NUANCE_API = process.env.NUANCE_API_URL ?? "https://api.nuancelabs.ai";
/**
* Your id for the signed-in person making the request, or null. Replace this
* with your own auth (NextAuth, Clerk, your session cookie): anyone who can
* call this endpoint can start conversations on your account. Until then it
* signs in no one, unless you set EXAMPLE_USER_ID to try the example.
*/
async function currentUserId(_request: Request): Promise<string | null> {
return process.env.EXAMPLE_USER_ID ?? null;
}
export async function POST(request: Request): Promise<Response> {
const userId = await currentUserId(request);
if (!userId) {
return new Response("Sign in to start a conversation", { status: 401 });
}
const response = await fetch(`${NUANCE_API}/session-tokens`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NUANCE_API_KEY}`,
"Content-Type": "application/json",
},
// Your id for the person, so a policy pause stops them, not your whole
// account. Letters, digits and _ . : - only: hash an email first.
body: JSON.stringify({ end_user_id: userId }),
});
if (!response.ok) {
// For you, in your server's log: the status and Nuance's reason, such as
// 401 for a wrong or revoked key. The page gets only the generic message.
console.error(
`POST /session-tokens answered ${response.status}: ${await response.text()}`,
);
return new Response("Couldn't start a conversation", { status: 502 });
}
const { token } = (await response.json()) as { token: string };
return Response.json({ token });
}
Replace currentUserId with your own sign-in check; until then it signs in no one, and every request gets a 401. Set up a session adds the session's own settings.
- Start within 60 seconds. A token that hasn't started a conversation by then is refused. Mint one when the person is about to start, not when the page loads.
- One conversation each. Starting a conversation spends the token. After that it reaches only that conversation, and keeps working until 300 seconds after the conversation ends.
- Settings are fixed when you mint it. The conversation runs with what your server sends to
POST /session-tokens, and the page can't change it:
| Field | What it sets |
|---|---|
personality.system_prompt | Who the persona is: your own prompt. |
personality.persona_id | Who the persona looks and sounds like: sam, sonia or mira (see them). Sam and Mira share one voice; Sonia has her own. Left out, sam. Any other id is refused with a 400 whose detail lists the ids you can use. |
end_user_id | Your id for the person, so a policy pause stops that person, not your whole account. |
expressiveness | How much the persona's face and head move, from 0 to 2: lower is calmer, higher more expressive. Left out, 1: the persona's own tuned level. |
Leave a field out for the default. interface_setup settles the session itself: see Set up a session. The API reference has every field and its limits.
Revoking a key
Once you revoke a key:
- requests with the key are refused, including minting new tokens;
- every session token the key minted is refused, whether or not it has been used.
A conversation that is already connected keeps running until it ends. Its media no longer goes through the Nuance API once it's connected.