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

Register a new OAuth client

POST/portal/v1/accounts/{accountSlug}/applications/{appSlug}/environments/{envSlug}/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

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

Requires capability oauth_clients.manageDeveloper Console

Create, edit, rotate, and delete OAuth clients. Granted through an administrator role in the Admin Workspace; a valid token without it is refused with 403.

Path Parameters

accountSlugstring Required

The Account's slug. An unknown one answers 404.

appSlugstring Required

The Application's slug within the Account.

envSlugstring Required

The Environment's slug within the Application.

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*

Errors

When the request can't be completed, the response body includes a stable error code you can branch on, and a correlation_id (also sent as the X-Correlation-Id header). Quote the correlation id when you contact support: it identifies the exact request in Canopy's logs.

403account.capability_requiredForbidden
When it happens

The signed-in user's administrator roles do not grant the capability this endpoint requires.

Remediation

Ask an account administrator to grant a role carrying the capability named in the Authentication section, then retry.

Returned object

Request
curl -X POST "https://auth.canopy-io.com/portal/v1/accounts/value/applications/value/environments/value/oauth-clients" \
  -H "Authorization: Bearer $CANOPY_TOKEN" \
  -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,
    "owner": "developer",
    "last_token_at": "2026-04-20T12:00:00.000Z",
    "previous_secret_expires_at": "2026-04-20T12:00:00.000Z",
    "secret_rotated_at": "2026-04-20T12:00:00.000Z",
    "version": 0,
    "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
Was this page helpful?

Tell us how we can improve this guide.