Skip to main content
Qirtaas separates credentials by where they live and what they can do: Your backend is the broker: the browser never sees the secret key or signing secret — only the short-lived artifacts derived from them.
Keys are provisioned per organization. Request them via the key request form. Self-hosting? You issue your own — see Self-hosting.

Embed tokens (authoring)

The editor authenticates every request with an embed token supplied by the SDK’s getToken callback. Your backend mints one by exchanging its API key:

POST /v1/embed/tokens/

string
required
Bearer qrt_sk_… — your secret API key.
string
required
A stable identifier for the end user in your system (a user id, UUID, or even a fixed value if all authors share one identity). Qirtaas auto-provisions an identity under your organization per distinct id.
Response 200:
Errors: 400 { "error": "external_user_id_required" }, 401 invalid or revoked key, 403 { "error": "organization_suspended" }. Tokens expire after 1 hour. The SDK calls getToken on init, proactively before expiry, and once more after a 401 — your endpoint should simply mint a fresh token on every call.

Example endpoint

Authenticate the request with your own session auth, then exchange:
Whoever can call your token endpoint can edit that identity’s documents. Gate it with your app’s own authentication, and scope external_user_id to the authenticated user.

Signatures (cross-user reads)

Embed tokens are scoped to one identity’s documents. To let other users read a document (ex: student reading teacher’s document) the renderer uses a per-document, expiring HMAC signature instead. Your backend computes it after running its own access check:
exp is a unix timestamp. The renderer sends the pair as ?sig=&exp= query parameters, and Qirtaas recomputes the same HMAC under the document owner’s secret to verify.
Python
Feed it to the renderer via getSignature:
An invalid or expired signature is a 403 { "error": "invalid_signature" } — signatures are not refreshable the way tokens are; the renderer surfaces the error via onError.

Share tokens (public reads)

A document explicitly shared by its author gets an opaque share token that resolves it publicly via GET /v1/documents/shared/{token}/ — no key, no signature. Pass it straight to the renderer as shareToken. See Renderer. The token is minted by the backend when sharing is turned on, not by the SDK: call the client’s setSharing(documentId, true) (which wraps PATCH /v1/documents/{id}/share/ over the embed-token channel) and store or link the returned share_token. Turning sharing off revokes the token. Self-hosted backends implement the same share endpoints.

Which read auth should I use?