1. Docs
  2. API Reference
  3. Register a new OAuth client

Register a new OAuth client

POST/api/v1/oauth-clients

Registers a new confidential OAuth client in the current Environment with the given name, redirect_uris, and optional scopes (defaulting to openid profile email), each one of openid, profile, email, org and permissions; any other value is refused with 400 (oauth.client_scope_unknown). With client_kind: machine it registers a machine client instead: a principal of its own that holds roles (see the assignments routes) and obtains tokens for itself, with an optional organization_node_id (the one organization it acts in), optional allowed_audiences and the permissions scope, the client_credentials grant only and no redirect URIs; it counts toward the plan's machine-credential allowance (409 plan_limit_exceeded). Generates the client_id and a client_secret that is bcrypt-hashed at rest; the raw secret is returned in this response only and is never retrievable again. Responds 201 Created.

Authentication

Bearer TokenAuthorization Option A

JWT access token. Never send alongside X-API-Key: a request carrying both is refused.

API KeyX-API-Key Option B

API key for management-tier access. Never send alongside an Authorization header: a request carrying both is refused.

Request body

application/json

namestring Required
client_kindenum Optional

`web` (when omitted): a person signs in through this client with the authorization code grant. `machine`: the client is a principal of its own that holds roles and obtains tokens for itself with the `client_credentials` grant, for the audiences it lists, inside at most one organization; it takes no redirect URIs or sign-in fields.

one of "web" · "machine"

organization_node_idstring Optional

Machine clients only: the organization the client acts in. Its tokens name it and it may hold roles only inside it. Omitted, the client acts across the Environment.

allowed_audiencesstring[] Optional

For a machine client: the audiences (your APIs' identifiers) it may request a token for with `audience`, beside the Environment's `m2m_default_audience`. The token's `aud` names the one asked for.

redirect_urisstring[] Optional

Required for a web client; a machine client has none.

post_logout_redirect_urisstring[] Optional

Where this client may send someone after RP-initiated logout. Matched exactly, and separate from `redirect_uris`: receiving an authorization code and being a landing page after sign-out are different kinds of trust.

scopesstring[] Optional

What the client's tokens may carry. Omitted, a web client gets `openid`, `profile` and `email`; a machine client gets `permissions`, the only scope it may hold.

backchannel_logout_uristring Optional

Where Canopy delivers a signed logout token, server to server, when a session this client issued tokens for ends. Omit it and the client is told nothing.

invite_redirect_urlstring Optional
initiate_login_uristring Optional

The route in your application that starts a sign-in (OpenID Connect `initiate_login_uri`): it should send the person to Canopy's `/oauth/authorize`. Canopy's hosted pages that end with nothing to return to, such as an accepted invitation or a verified email, offer it as **Sign in**. Absolute `http` or `https` URL.

Responses

application/json

  • dataOAuthClientCreatedResponseDto*

application/json

  • errorApiErrorBodyDto*

application/json

  • errorApiErrorBodyDto*

application/json

  • errorApiErrorBodyDto*

application/json

  • errorApiErrorBodyDto*

application/json

  • errorApiErrorBodyDto*

Idempotency

Idempotency-Key header

Send an Idempotency-Key header to make retries safe. Canopy replays the same response for matching keys within 24 hours, and refuses the same key sent with a different request with 422 idempotency.key_reused_with_different_request.

Returned object

Request
curl -X POST "https://auth.canopy-io.com/api/v1/oauth-clients" \
  -H "X-API-Key: $CANOPY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "client_kind": "web",
    "organization_node_id": "string",
    "allowed_audiences": [
      "https://api.example.com"
    ],
    "redirect_uris": [
      "string"
    ],
    "post_logout_redirect_uris": [
      "string"
    ],
    "scopes": [
      "string"
    ],
    "backchannel_logout_uri": "string",
    "invite_redirect_url": "string",
    "initiate_login_uri": "string"
  }'
Response
{
  "data": {
    "id": "string",
    "client_id": "string",
    "name": "string",
    "client_kind": "web",
    "organization_node_id": "string",
    "organization_name": "string",
    "allowed_audiences": [
      "string"
    ],
    "redirect_uris": [
      "string"
    ],
    "post_logout_redirect_uris": [
      "string"
    ],
    "grant_types": [
      "string"
    ],
    "scopes": [
      "string"
    ],
    "backchannel_logout_uri": "string",
    "invite_redirect_url": "string",
    "initiate_login_uri": "string",
    "is_active": false,
    "created_at": "2026-04-20T12:00:00.000Z",
    "issuer": "https://auth.yourapp.com",
    "client_secret": "string"
  }
}
Related endpoints
GETList OAuth clients for Application
GETActive/inactive OAuth client counts for the environment
GETGet OAuth client details
PATCHUpdate OAuth client
DELETEDelete OAuth client
POSTRotate an OAuth client's secret
GETList a machine client's role assignments
POSTAssign a role to a machine client at a node
PATCHChange a machine client's assignment
DELETERemove a machine client's assignment
GETGet where a machine client holds each permission
Was this page helpful?

Tell us how we can improve this guide.