Synq Docs
Concepts

Apps and APIs

A brand's apps sign people in; its APIs are what their access tokens are for.

Apps

An app is an OAuth client of one brand: something that signs people in through the brand's issuer, or gets tokens of its own. Its type fixes how it may do that:

TypeWhat it is
webA server-side web app, which keeps a secret (or signs with its own keys, private_key_jwt)
spaA single-page app in a browser: public, with no secret
nativeA mobile or desktop app: public, with PKCE, and RFC 8252's redirect URIs (see below)
m2mA machine: gets tokens for an API with its own credentials (client_credentials), never for a person
agentAn agent or CLI that signs a person in with the device flow (RFC 8628)

Redirect URIs are matched exactly, port included, and are https. A web app or SPA may also register https on localhost, 127.0.0.1 or [::1] for a dev server.

A native app has three kinds of redirect URI to choose from (RFC 8252):

  • A claimed https link, a universal link (iOS) or App Link (Android) on a domain the app is associated with. Only that app can open it, so this is the strongest choice.
  • Its own scheme, such as com.example.app:/callback, which is how an iOS app's ASWebAuthenticationSession hears the redirect without an associated domain. The scheme must be a reverse domain name you own, in lowercase, with at least one dot: never http, https, javascript, data, file or a single word like myapp. Another app on the device could claim the same scheme, which is why a native app is always public (it never has a secret) and always uses PKCE (S256): a code that reaches the wrong app is useless without the verifier only yours holds.
  • http on localhost or 127.0.0.1, on any port, for a desktop app that listens while it signs someone in.

Web apps, SPAs and machine apps can't register a scheme of their own, and neither can an app that registered itself. Post-logout redirect URIs follow the same rules. An app's secret is in the answer that makes or rotates it, once: Synq keeps only its hash. A rotation keeps the old secret working for the overlap you ask for (a day by default).

An app marked first_party is one of the brand's own: people aren't asked to consent to it, and only such apps may use the account API. How many apps an org may make is its plan's. See Make an app.

APIs

An API is a resource server of the brand: your backend, which accepts the brand's access tokens. You register it with an identifier (usually its URL), which never changes, and its scopes, each with the words the consent page shows for it. An app asks for a token for it with resource=<identifier> and gets an ES256 JWT (RFC 9068) whose aud is that one API, with azp, scope, auth_time, acr and amr, living as long as the API says (5 to 15 minutes; 10 by default). Your API checks it against the issuer's keys; it can't be revoked before it expires. A token asked for without a resource is opaque, and good only for the issuer's userinfo.

  • An app gets only scopes the API defines; asking for one it may not have is invalid_scope, never silently dropped. You can limit an app to some of an API's scopes, and a machine app reaches only the APIs you gave it scopes of.
  • An API is open only to the brand's own apps unless you allow apps that aren't yours (allow_third_party), such as MCP hosts. Those ask the person for consent.
  • Dropping a scope takes it from every app and every consent that had it.

See Register an API and Set which of an API's scopes an app may ask for.

On this page