Unstable API: endpoints and payloads are still changing. Expect breaking changes without notice, and plan to update your integration.

Overview

ComplyOnce authenticates people through an app on their phone. A user scans a QR code, compares a short pairing code, and confirms with a PIN. Your site never handles the user's credentials — it receives a verified identity when the flow completes.

This documentation is for relying parties: sites and services that want to log users in with ComplyOnce, or have them sign documents.

Who does what

Participant Role
Relying party (you) The site the user logs in to. A confidential OAuth client — it holds a client_secret and starts and finishes every login from its server. Serving the page the user waits on is yours to do or to hand to ComplyOnce.
ComplyOnce backend The authorization server. Every endpoint you call requires your client credentials.
ComplyOnce app The user's phone. Scans the QR code, shows what is being approved, and signs with a PIN-gated key.

The two operations

Login — logging a user in. Available now. This is an OAuth 2.0 authorization code flow with PKCE, so if you have integrated with any OAuth provider before, the shape will be familiar. See the login flow.

Signing — having a user sign a document. Not implemented yet. See the signing flow for the current status.

Both are called from your server with your client credentials — see Authentication.

What you receive

A successful login gives you exactly one thing: a subjectId, a UUID identifying the user to you specifically.

{ "subjectId": "8f14e45f-ceea-4a1b-9f2c-3d5b7a081c62" }

It is stable for that user across all their logins to you, so it works as the primary key of your own account record. It is also specific to you: the same person logging in to a different relying party is given a different subjectId, derived so that no two relying parties can tell they hold the same user. On its own it carries no name, no personal identification code, and no date of birth.

Identity properties — requesting attribute values (name, country) or true/false predicates evaluated by ComplyOnce (age_at_least: 18) — can be added to a login, bounded by a per-client allow-list, and are returned in the token response. See Identity properties.

You need a server

Every ComplyOnce endpoint a relying party calls requires your client_secret, and there is no public-client (secret-free) variant of any of them. A browser-only integration would have to ship the secret to every visitor, and would have to trust the ?code=… parameter without ever redeeming it — meaning anyone could forge that URL and let themselves in.

So the login must be owned by your server: it generates the PKCE values, creates the session, redeems the code, and only then establishes a session for the browser.

What sits in the middle — showing the QR code, waiting for the user to confirm — you can either build yourself, in which case your pages talk only to your server, or hand to the ComplyOnce-hosted login page, which your server sends the browser to with a one-time token. Either way your client_secret stays on your server and the code is redeemed there. See the two ways to integrate.

Before you start

You need to be registered as a relying party — see Registration. Nothing works until that is done: without credentials ComplyOnce answers every call with 401.

Endpoint-level detail for every call is in the API reference.