Get started

Session secrets

Every session has its own secret, returned once when it starts. Later calls on the session or its documents send it, so a leaked key alone reads nothing.

What a session secret is

POST /v1/sessions returns a turn with a top-level session_secret (dss_…). It is returned only there and never shown again; we store only a hash of it. A session opens only for your organisation's key and its secret.

Your key lives in your server's environment and the secrets in your database, so someone who gets hold of the key alone can't read your users' conversations or documents.

Store it

Save the session ID, its secret and your own user's ID together, as soon as the session starts. That row is how you find a user's sessions later and how you check that a request is theirs.

Node.js
// Your server, behind your own login.app.post("/api/sessions", requireLogin, async (req, res) => {  const r = await fetch(`${DOCGEN}/v1/sessions`, {    method: "POST",    headers: {      Authorization: `Bearer ${process.env.DOCGEN_API_KEY}`,      "Content-Type": "application/json",    },    body: JSON.stringify({ message: req.body.message }),  });  const turn = await r.json();  if (!r.ok) return res.status(r.status).json(turn);  // Store the session ID, its secret and your user's ID together.  await db.sessions.insert({    id: turn.session.id,    secret: turn.session_secret,    user_id: req.user.id,  });  const { session_secret, ...rest } = turn; // never send the secret to the browser  res.status(201).json(rest);});

If the response is lost, retry with the same Idempotency-Key: for 24 hours the replay returns the same session and the same secret. A secret you lose after that can't be recovered; start a new session.

Send it

Send Docgen-Session-Secret on every call after the session starts: reading, messaging, answers, closing and deleting it, and POST /v1/documents with its session. A document takes the secret of the session it was made from, on GET /v1/documents/{document} and its stream.

cURL
curl https://api.129.212.147.181.sslip.io/v1/sessions/$SESSION_ID \  -H "Authorization: Bearer $DOCGEN_API_KEY" \  -H "Docgen-Session-Secret: $SESSION_SECRET"

The signed download links in files.*.url need neither the key nor the secret: the link is the credential, and it expires.

Your users

An ID is never a permission. Look the session up in your own database for the signed-in user, then send its secret. Never take a session ID from the browser and forward it as is.

There is no call that lists sessions. Your database already knows which sessions belong to which user, so a “your documents” page reads from there.

Node.js
app.post("/api/sessions/:id/messages", requireLogin, async (req, res) => {  // Only this user's sessions: the lookup is your permission check.  const s = await db.sessions.findOne({ id: req.params.id, user_id: req.user.id });  if (!s) return res.sendStatus(404);  const r = await fetch(`${DOCGEN}/v1/sessions/${s.id}/messages`, {    method: "POST",    headers: {      Authorization: `Bearer ${process.env.DOCGEN_API_KEY}`,      "Docgen-Session-Secret": s.secret,      "Content-Type": "application/json",    },    body: JSON.stringify({ text: req.body.text }),  });  res.status(r.status).json(await r.json());});

When it fails

Server only

Keep the secret on your server, like the key. Secret keys are refused from browsers: a request with an Origin header gets 401 secret_key_in_browser. Your page calls your server; your server adds the key and the session's secret and calls us. The same goes for streams.

Docgen-Subject

Docgen-Subject is an optional label for your end user (a user ID or a hash of one, never an email) sent when a session starts. We store it and echo it in session.subject. It grants no access: that rests on the secret.