@canopy-io/node 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1708,7 +1708,7 @@ interface paths {
1708
1708
  };
1709
1709
  /**
1710
1710
  * Recent directory-sync activity for an organization
1711
- * @description The organization's own provisioning events, newest first
1711
+ * @description The organization's own directory events (provisioning, group mapping, and changes to its connection, tokens and allowed roles), newest first
1712
1712
  */
1713
1713
  get: operations["ApiOrganizationDirectoryController_activity"];
1714
1714
  put?: never;
@@ -2255,6 +2255,98 @@ interface paths {
2255
2255
  patch: operations["ApiWebhooksController_update"];
2256
2256
  trace?: never;
2257
2257
  };
2258
+ "/api/v1/oauth-clients": {
2259
+ parameters: {
2260
+ query?: never;
2261
+ header?: never;
2262
+ path?: never;
2263
+ cookie?: never;
2264
+ };
2265
+ /**
2266
+ * List OAuth clients for Application
2267
+ * @description Returns a paginated list of the OAuth clients registered in the current Environment, newest first by default. Supports `q` to filter by client name and the standard sort/pagination query options. Client secrets are never included.
2268
+ */
2269
+ get: operations["ApiOAuthClientsController_list"];
2270
+ put?: never;
2271
+ /**
2272
+ * Register a new OAuth client
2273
+ * @description Registers a new confidential OAuth client in the current Environment with the given `name`, `redirect_uris`, and optional `scopes` (defaulting to `openid profile email`). 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`.
2274
+ */
2275
+ post: operations["ApiOAuthClientsController_create"];
2276
+ delete?: never;
2277
+ options?: never;
2278
+ head?: never;
2279
+ patch?: never;
2280
+ trace?: never;
2281
+ };
2282
+ "/api/v1/oauth-clients/summary": {
2283
+ parameters: {
2284
+ query?: never;
2285
+ header?: never;
2286
+ path?: never;
2287
+ cookie?: never;
2288
+ };
2289
+ /**
2290
+ * Active/inactive OAuth client counts for the environment
2291
+ * @description Returns Environment-wide active and inactive OAuth client counts (not just the current page), optionally narrowed by the same `q` name filter the list endpoint uses. Drives the client stat card.
2292
+ */
2293
+ get: operations["ApiOAuthClientsController_summary"];
2294
+ put?: never;
2295
+ post?: never;
2296
+ delete?: never;
2297
+ options?: never;
2298
+ head?: never;
2299
+ patch?: never;
2300
+ trace?: never;
2301
+ };
2302
+ "/api/v1/oauth-clients/{id}": {
2303
+ parameters: {
2304
+ query?: never;
2305
+ header?: never;
2306
+ path?: never;
2307
+ cookie?: never;
2308
+ };
2309
+ /**
2310
+ * Get OAuth client details
2311
+ * @description Returns a single OAuth client by `id`, scoped to the current Environment — a client that exists in a sibling Environment reads as `404`. The `client_secret` is never included.
2312
+ */
2313
+ get: operations["ApiOAuthClientsController_get"];
2314
+ put?: never;
2315
+ post?: never;
2316
+ /**
2317
+ * Delete OAuth client
2318
+ * @description Deletes an OAuth client from the current Environment by `id`. Responds `204 No Content` on success, or `404` when the client is not found in this Environment.
2319
+ */
2320
+ delete: operations["ApiOAuthClientsController_remove"];
2321
+ options?: never;
2322
+ head?: never;
2323
+ /**
2324
+ * Update OAuth client
2325
+ * @description Updates an OAuth client's mutable fields (`name`, `redirect_uris`, `post_logout_redirect_uris`, `backchannel_logout_uri`, `scopes`, `is_active`, `invite_redirect_url`, `initiate_login_uri`), scoped to the current Environment. Returns the updated client, or `404` when the client is not found in this Environment. The secret is not rotated here.
2326
+ */
2327
+ patch: operations["ApiOAuthClientsController_update"];
2328
+ trace?: never;
2329
+ };
2330
+ "/api/v1/oauth-clients/{id}/rotate-secret": {
2331
+ parameters: {
2332
+ query?: never;
2333
+ header?: never;
2334
+ path?: never;
2335
+ cookie?: never;
2336
+ };
2337
+ get?: never;
2338
+ put?: never;
2339
+ /**
2340
+ * Rotate an OAuth client's secret
2341
+ * @description Rotates the OAuth client's `client_secret`, generating and hashing a new secret and invalidating the old one. The new raw secret is returned in this response only and cannot be retrieved again. Returns `404` when the client is not found in the current Environment.
2342
+ */
2343
+ post: operations["ApiOAuthClientsController_rotateSecret"];
2344
+ delete?: never;
2345
+ options?: never;
2346
+ head?: never;
2347
+ patch?: never;
2348
+ trace?: never;
2349
+ };
2258
2350
  "/api/v1/api-keys": {
2259
2351
  parameters: {
2260
2352
  query?: never;
@@ -3263,6 +3355,7 @@ interface components {
3263
3355
  saml_name_id_format?: string;
3264
3356
  /** @description Force the IdP to re-authenticate the user on every login (SAML ForceAuthn / OIDC max_age=0). Prevents silent reuse of a stale IdP session on shared devices. */
3265
3357
  force_authn?: boolean;
3358
+ /** @description The identity provider's OIDC discovery document. Canopy's servers fetch it, so it must be an `https` address on a public host; private, loopback and link-local addresses are refused. */
3266
3359
  oidc_discovery_url?: string;
3267
3360
  oidc_client_id?: string;
3268
3361
  /** @description OIDC client secret (plaintext in; encrypted at rest). */
@@ -3288,6 +3381,7 @@ interface components {
3288
3381
  saml_name_id_format?: string;
3289
3382
  /** @description Force the IdP to re-authenticate the user on every login (SAML ForceAuthn / OIDC max_age=0). Prevents silent reuse of a stale IdP session on shared devices. */
3290
3383
  force_authn?: boolean;
3384
+ /** @description The identity provider's OIDC discovery document. Canopy's servers fetch it, so it must be an `https` address on a public host; private, loopback and link-local addresses are refused. */
3291
3385
  oidc_discovery_url?: string;
3292
3386
  oidc_client_id?: string;
3293
3387
  /** @description OIDC client secret (plaintext in; encrypted at rest). */
@@ -3750,7 +3844,7 @@ interface components {
3750
3844
  UpdateEnvironmentBrandingDto: {
3751
3845
  /** @description The product name hosted pages and the organization admin portal show: in the browser tab title, beside the logo when `logo_kind` is `icon`, as a full logo's alt text, and in place of a logo when none is set. Null clears it, and the pages then show no name. */
3752
3846
  product_name?: string | null;
3753
- /** @description Absolute https URL of the logo shown at the top of hosted pages and the portal. Null clears it. */
3847
+ /** @description Absolute https URL of the logo shown at the top of hosted pages, the portal and emails to the Environment's users. Emails show it only when the image is a PNG, JPEG or GIF, which every email client displays; with any other format they show the product name. Null clears it. */
3754
3848
  logo_url?: string | null;
3755
3849
  /**
3756
3850
  * @description What the logo image is. `full`: a complete logo that already carries the product name, shown alone. `icon`: a square mark, shown at icon size with the product name beside it. Null returns to `full`.
@@ -3851,6 +3945,90 @@ interface components {
3851
3945
  description?: string | null;
3852
3946
  is_active?: boolean;
3853
3947
  };
3948
+ OAuthClientCreatedResponseDto: {
3949
+ id: string;
3950
+ client_id: string;
3951
+ name: string;
3952
+ redirect_uris: string[];
3953
+ /** @description Where this client may send someone after RP-initiated logout, matched exactly. */
3954
+ post_logout_redirect_uris: string[];
3955
+ grant_types: string[];
3956
+ scopes: string[];
3957
+ /** @description Where Canopy delivers a logout token when a session ends. Null means the client is told nothing. */
3958
+ backchannel_logout_uri?: string | null;
3959
+ invite_redirect_url?: string | null;
3960
+ /** @description The route in the client's application that starts a sign-in (OpenID Connect `initiate_login_uri`), offered as **Sign in** on hosted pages that end with nothing to return to. */
3961
+ initiate_login_uri?: string | null;
3962
+ is_active: boolean;
3963
+ /** Format: date-time */
3964
+ created_at: string;
3965
+ /**
3966
+ * @description The issuer this client's tokens name, which a relying party configures: `https://<custom auth domain>` while the Environment has an active one, else the platform's. Its discovery document is at `<issuer>/.well-known/openid-configuration`.
3967
+ * @example https://auth.yourapp.com
3968
+ */
3969
+ issuer: string;
3970
+ /** @description Client secret — shown only once */
3971
+ client_secret: string;
3972
+ };
3973
+ CreateOAuthClientDto: {
3974
+ name: string;
3975
+ redirect_uris: string[];
3976
+ /** @description 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. */
3977
+ post_logout_redirect_uris?: string[];
3978
+ scopes?: string[];
3979
+ /** @description 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. */
3980
+ backchannel_logout_uri?: string;
3981
+ invite_redirect_url?: string;
3982
+ /** @description 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. */
3983
+ initiate_login_uri?: string;
3984
+ };
3985
+ OAuthClientResponseDto: {
3986
+ id: string;
3987
+ client_id: string;
3988
+ name: string;
3989
+ redirect_uris: string[];
3990
+ /** @description Where this client may send someone after RP-initiated logout, matched exactly. */
3991
+ post_logout_redirect_uris: string[];
3992
+ grant_types: string[];
3993
+ scopes: string[];
3994
+ /** @description Where Canopy delivers a logout token when a session ends. Null means the client is told nothing. */
3995
+ backchannel_logout_uri?: string | null;
3996
+ invite_redirect_url?: string | null;
3997
+ /** @description The route in the client's application that starts a sign-in (OpenID Connect `initiate_login_uri`), offered as **Sign in** on hosted pages that end with nothing to return to. */
3998
+ initiate_login_uri?: string | null;
3999
+ is_active: boolean;
4000
+ /** Format: date-time */
4001
+ created_at: string;
4002
+ /**
4003
+ * @description The issuer this client's tokens name, which a relying party configures: `https://<custom auth domain>` while the Environment has an active one, else the platform's. Its discovery document is at `<issuer>/.well-known/openid-configuration`.
4004
+ * @example https://auth.yourapp.com
4005
+ */
4006
+ issuer: string;
4007
+ };
4008
+ ActiveSummaryDto: {
4009
+ /** @description Active items in the environment */
4010
+ active_count: number;
4011
+ /** @description Inactive items in the environment */
4012
+ inactive_count: number;
4013
+ };
4014
+ UpdateOAuthClientDto: {
4015
+ name?: string;
4016
+ redirect_uris?: string[];
4017
+ /** @description Where this client may send someone after RP-initiated logout. Matched exactly. An empty array removes every destination, which leaves logout working with nowhere to return to. */
4018
+ post_logout_redirect_uris?: string[];
4019
+ scopes?: string[];
4020
+ is_active?: boolean;
4021
+ /** @description Where Canopy delivers a signed logout token when a session this client issued tokens for ends. `null` stops the notifications. */
4022
+ backchannel_logout_uri?: string | null;
4023
+ invite_redirect_url?: string | null;
4024
+ /** @description 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; `null` clears it. */
4025
+ initiate_login_uri?: string | null;
4026
+ };
4027
+ OAuthClientSecretRotatedResponseDto: {
4028
+ client_id: string;
4029
+ /** @description New client secret — shown only once */
4030
+ client_secret: string;
4031
+ };
3854
4032
  ApiKeyCreatedResponseDto: {
3855
4033
  id: string;
3856
4034
  name: string;
@@ -3880,7 +4058,7 @@ interface components {
3880
4058
  */
3881
4059
  access_mode: "scoped" | "full_access";
3882
4060
  /** @description Permission scopes this key is authorized for, each one the platform offers (`GET .../api-keys/scopes`). Required and must be non-empty when `access_mode` is `scoped`. Must be omitted when `access_mode` is `full_access`. */
3883
- scopes?: ("hierarchy.view" | "hierarchy.manage" | "rbac.view_roles" | "rbac.manage_roles" | "rbac.view_assignments" | "rbac.manage_assignments" | "permissions.evaluate" | "identity.view" | "identity.manage" | "api_key.view" | "api_key.manage" | "webhook.view" | "webhook.manage")[];
4061
+ scopes?: ("hierarchy.view" | "hierarchy.manage" | "rbac.view_roles" | "rbac.manage_roles" | "rbac.view_assignments" | "rbac.manage_assignments" | "permissions.evaluate" | "identity.view" | "identity.manage" | "api_key.view" | "api_key.manage" | "webhook.view" | "webhook.manage" | "oauth_client.view" | "oauth_client.manage")[];
3884
4062
  /** @description Expiration date (ISO 8601). Omit for no expiration. */
3885
4063
  expires_at?: string;
3886
4064
  };
@@ -3940,6 +4118,11 @@ interface components {
3940
4118
  * @example GET
3941
4119
  */
3942
4120
  method: string;
4121
+ /**
4122
+ * @description The request's correlation id, the same value as the `X-Correlation-Id` response header. Quote it to support: it finds this exact request in Canopy's logs and error reports.
4123
+ * @example 6d7f2c8e-2f0b-4d0f-9b0e-2b0b2b0b2b0b
4124
+ */
4125
+ correlation_id: string | null;
3943
4126
  /**
3944
4127
  * @description Field-level validation messages, present only on 400 responses from request-body validation.
3945
4128
  * @example [
@@ -6642,6 +6825,27 @@ interface operations {
6642
6825
  "application/json": components["schemas"]["ErrorResponseDto"];
6643
6826
  };
6644
6827
  };
6828
+ /** @description The `Idempotency-Key` was already used by this caller for a request with a different method, path or body. A replay must repeat the original request exactly; a new request takes a new key. */
6829
+ 422: {
6830
+ headers: {
6831
+ [name: string]: unknown;
6832
+ };
6833
+ content: {
6834
+ /**
6835
+ * @example {
6836
+ * "error": {
6837
+ * "statusCode": 422,
6838
+ * "code": null,
6839
+ * "message": "The `Idempotency-Key` was already used by this caller for a request with a different method, path or body. A replay must repeat the original request exactly; a new request takes a new key.",
6840
+ * "timestamp": "2026-04-20T12:00:00.000Z",
6841
+ * "path": "/api/v1/identities/bulk-create",
6842
+ * "method": "POST"
6843
+ * }
6844
+ * }
6845
+ */
6846
+ "application/json": components["schemas"]["ErrorResponseDto"];
6847
+ };
6848
+ };
6645
6849
  };
6646
6850
  };
6647
6851
  ApiIdentitiesController_getIdentity: {
@@ -8802,6 +9006,27 @@ interface operations {
8802
9006
  "application/json": components["schemas"]["ErrorResponseDto"];
8803
9007
  };
8804
9008
  };
9009
+ /** @description The `Idempotency-Key` was already used by this caller for a request with a different method, path or body. A replay must repeat the original request exactly; a new request takes a new key. */
9010
+ 422: {
9011
+ headers: {
9012
+ [name: string]: unknown;
9013
+ };
9014
+ content: {
9015
+ /**
9016
+ * @example {
9017
+ * "error": {
9018
+ * "statusCode": 422,
9019
+ * "code": null,
9020
+ * "message": "The `Idempotency-Key` was already used by this caller for a request with a different method, path or body. A replay must repeat the original request exactly; a new request takes a new key.",
9021
+ * "timestamp": "2026-04-20T12:00:00.000Z",
9022
+ * "path": "/api/v1/identity-invites/bulk-create",
9023
+ * "method": "POST"
9024
+ * }
9025
+ * }
9026
+ */
9027
+ "application/json": components["schemas"]["ErrorResponseDto"];
9028
+ };
9029
+ };
8805
9030
  };
8806
9031
  };
8807
9032
  ApiIdentityInvitesController_resendInvite: {
@@ -15558,7 +15783,7 @@ interface operations {
15558
15783
  };
15559
15784
  requestBody?: never;
15560
15785
  responses: {
15561
- /** @description The organization's own provisioning events, newest first */
15786
+ /** @description The organization's own directory events (provisioning, group mapping, and changes to its connection, tokens and allowed roles), newest first */
15562
15787
  200: {
15563
15788
  headers: {
15564
15789
  [name: string]: unknown;
@@ -19768,7 +19993,7 @@ interface operations {
19768
19993
  };
19769
19994
  };
19770
19995
  };
19771
- ApiApiKeysController_list: {
19996
+ ApiOAuthClientsController_list: {
19772
19997
  parameters: {
19773
19998
  query?: {
19774
19999
  /** @description Page number (1-based) */
@@ -19795,7 +20020,7 @@ interface operations {
19795
20020
  };
19796
20021
  content: {
19797
20022
  "application/json": {
19798
- items: components["schemas"]["ApiKeyResponseDto"][];
20023
+ items: components["schemas"]["OAuthClientResponseDto"][];
19799
20024
  pagination: components["schemas"]["PageMetaDto"];
19800
20025
  };
19801
20026
  };
@@ -19813,7 +20038,7 @@ interface operations {
19813
20038
  * "code": null,
19814
20039
  * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header",
19815
20040
  * "timestamp": "2026-04-20T12:00:00.000Z",
19816
- * "path": "/api/v1/api-keys",
20041
+ * "path": "/api/v1/oauth-clients",
19817
20042
  * "method": "GET"
19818
20043
  * }
19819
20044
  * }
@@ -19834,7 +20059,7 @@ interface operations {
19834
20059
  * "code": null,
19835
20060
  * "message": "Invalid or expired token",
19836
20061
  * "timestamp": "2026-04-20T12:00:00.000Z",
19837
- * "path": "/api/v1/api-keys",
20062
+ * "path": "/api/v1/oauth-clients",
19838
20063
  * "method": "GET"
19839
20064
  * }
19840
20065
  * }
@@ -19855,7 +20080,7 @@ interface operations {
19855
20080
  * "code": null,
19856
20081
  * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
19857
20082
  * "timestamp": "2026-04-20T12:00:00.000Z",
19858
- * "path": "/api/v1/api-keys",
20083
+ * "path": "/api/v1/oauth-clients",
19859
20084
  * "method": "GET"
19860
20085
  * }
19861
20086
  * }
@@ -19865,7 +20090,7 @@ interface operations {
19865
20090
  };
19866
20091
  };
19867
20092
  };
19868
- ApiApiKeysController_create: {
20093
+ ApiOAuthClientsController_create: {
19869
20094
  parameters: {
19870
20095
  query?: never;
19871
20096
  header?: never;
@@ -19874,22 +20099,22 @@ interface operations {
19874
20099
  };
19875
20100
  requestBody: {
19876
20101
  content: {
19877
- "application/json": components["schemas"]["CreateApiKeyDto"];
20102
+ "application/json": components["schemas"]["CreateOAuthClientDto"];
19878
20103
  };
19879
20104
  };
19880
20105
  responses: {
19881
- /** @description API key created — key value is only shown once */
20106
+ /** @description Client created — client_secret is only shown once */
19882
20107
  201: {
19883
20108
  headers: {
19884
20109
  [name: string]: unknown;
19885
20110
  };
19886
20111
  content: {
19887
20112
  "application/json": {
19888
- data: components["schemas"]["ApiKeyCreatedResponseDto"];
20113
+ data: components["schemas"]["OAuthClientCreatedResponseDto"];
19889
20114
  };
19890
20115
  };
19891
20116
  };
19892
- /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header */
20117
+ /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range, `backchannel_logout_uri` names an address Canopy's servers will not call, or `initiate_login_uri` is malformed or not `https` (loopback hosts excepted); or the request sent both an `X-API-Key` and an `Authorization` header */
19893
20118
  400: {
19894
20119
  headers: {
19895
20120
  [name: string]: unknown;
@@ -19900,9 +20125,9 @@ interface operations {
19900
20125
  * "error": {
19901
20126
  * "statusCode": 400,
19902
20127
  * "code": null,
19903
- * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header",
20128
+ * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range, `backchannel_logout_uri` names an address Canopy's servers will not call, or `initiate_login_uri` is malformed or not `https` (loopback hosts excepted); or the request sent both an `X-API-Key` and an `Authorization` header",
19904
20129
  * "timestamp": "2026-04-20T12:00:00.000Z",
19905
- * "path": "/api/v1/api-keys",
20130
+ * "path": "/api/v1/oauth-clients",
19906
20131
  * "method": "POST"
19907
20132
  * }
19908
20133
  * }
@@ -19923,7 +20148,7 @@ interface operations {
19923
20148
  * "code": null,
19924
20149
  * "message": "Invalid or expired token",
19925
20150
  * "timestamp": "2026-04-20T12:00:00.000Z",
19926
- * "path": "/api/v1/api-keys",
20151
+ * "path": "/api/v1/oauth-clients",
19927
20152
  * "method": "GET"
19928
20153
  * }
19929
20154
  * }
@@ -19944,7 +20169,7 @@ interface operations {
19944
20169
  * "code": null,
19945
20170
  * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
19946
20171
  * "timestamp": "2026-04-20T12:00:00.000Z",
19947
- * "path": "/api/v1/api-keys",
20172
+ * "path": "/api/v1/oauth-clients",
19948
20173
  * "method": "GET"
19949
20174
  * }
19950
20175
  * }
@@ -19952,29 +20177,8 @@ interface operations {
19952
20177
  "application/json": components["schemas"]["ErrorResponseDto"];
19953
20178
  };
19954
20179
  };
19955
- /** @description The account has reached its plan's monthly limit on active API keys (`m2m_tokens`); `data` carries the limit, the usage and an upgrade URL */
19956
- 409: {
19957
- headers: {
19958
- [name: string]: unknown;
19959
- };
19960
- content: {
19961
- /**
19962
- * @example {
19963
- * "error": {
19964
- * "statusCode": 409,
19965
- * "code": null,
19966
- * "message": "The account has reached its plan's monthly limit on active API keys (`m2m_tokens`); `data` carries the limit, the usage and an upgrade URL",
19967
- * "timestamp": "2026-04-20T12:00:00.000Z",
19968
- * "path": "/api/v1/api-keys",
19969
- * "method": "POST"
19970
- * }
19971
- * }
19972
- */
19973
- "application/json": components["schemas"]["ErrorResponseDto"];
19974
- };
19975
- };
19976
- /** @description More than 20 create requests in a minute from this caller (`x-canopy-rate-limit`); retry after the window */
19977
- 429: {
20180
+ /** @description The `Idempotency-Key` was already used by this caller for a request with a different method, path or body. A replay must repeat the original request exactly; a new request takes a new key. */
20181
+ 422: {
19978
20182
  headers: {
19979
20183
  [name: string]: unknown;
19980
20184
  };
@@ -19982,11 +20186,11 @@ interface operations {
19982
20186
  /**
19983
20187
  * @example {
19984
20188
  * "error": {
19985
- * "statusCode": 429,
20189
+ * "statusCode": 422,
19986
20190
  * "code": null,
19987
- * "message": "More than 20 create requests in a minute from this caller (`x-canopy-rate-limit`); retry after the window",
20191
+ * "message": "The `Idempotency-Key` was already used by this caller for a request with a different method, path or body. A replay must repeat the original request exactly; a new request takes a new key.",
19988
20192
  * "timestamp": "2026-04-20T12:00:00.000Z",
19989
- * "path": "/api/v1/api-keys",
20193
+ * "path": "/api/v1/oauth-clients",
19990
20194
  * "method": "POST"
19991
20195
  * }
19992
20196
  * }
@@ -19996,23 +20200,27 @@ interface operations {
19996
20200
  };
19997
20201
  };
19998
20202
  };
19999
- ApiApiKeysController_delete: {
20203
+ ApiOAuthClientsController_summary: {
20000
20204
  parameters: {
20001
- query?: never;
20002
- header?: never;
20003
- path: {
20004
- id: string;
20205
+ query?: {
20206
+ q?: string;
20005
20207
  };
20208
+ header?: never;
20209
+ path?: never;
20006
20210
  cookie?: never;
20007
20211
  };
20008
20212
  requestBody?: never;
20009
20213
  responses: {
20010
- /** @description API key deleted */
20011
- 204: {
20214
+ /** @description OAuth client active/inactive summary returned */
20215
+ 200: {
20012
20216
  headers: {
20013
20217
  [name: string]: unknown;
20014
20218
  };
20015
- content?: never;
20219
+ content: {
20220
+ "application/json": {
20221
+ data: components["schemas"]["ActiveSummaryDto"];
20222
+ };
20223
+ };
20016
20224
  };
20017
20225
  /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header */
20018
20226
  400: {
@@ -20027,8 +20235,8 @@ interface operations {
20027
20235
  * "code": null,
20028
20236
  * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header",
20029
20237
  * "timestamp": "2026-04-20T12:00:00.000Z",
20030
- * "path": "/api/v1/api-keys/{id}",
20031
- * "method": "DELETE"
20238
+ * "path": "/api/v1/oauth-clients/summary",
20239
+ * "method": "GET"
20032
20240
  * }
20033
20241
  * }
20034
20242
  */
@@ -20048,7 +20256,7 @@ interface operations {
20048
20256
  * "code": null,
20049
20257
  * "message": "Invalid or expired token",
20050
20258
  * "timestamp": "2026-04-20T12:00:00.000Z",
20051
- * "path": "/api/v1/api-keys",
20259
+ * "path": "/api/v1/oauth-clients",
20052
20260
  * "method": "GET"
20053
20261
  * }
20054
20262
  * }
@@ -20069,7 +20277,7 @@ interface operations {
20069
20277
  * "code": null,
20070
20278
  * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
20071
20279
  * "timestamp": "2026-04-20T12:00:00.000Z",
20072
- * "path": "/api/v1/api-keys",
20280
+ * "path": "/api/v1/oauth-clients",
20073
20281
  * "method": "GET"
20074
20282
  * }
20075
20283
  * }
@@ -20077,30 +20285,9 @@ interface operations {
20077
20285
  "application/json": components["schemas"]["ErrorResponseDto"];
20078
20286
  };
20079
20287
  };
20080
- /** @description API key not found */
20081
- 404: {
20082
- headers: {
20083
- [name: string]: unknown;
20084
- };
20085
- content: {
20086
- /**
20087
- * @example {
20088
- * "error": {
20089
- * "statusCode": 404,
20090
- * "code": null,
20091
- * "message": "API key not found",
20092
- * "timestamp": "2026-04-20T12:00:00.000Z",
20093
- * "path": "/api/v1/api-keys/{id}",
20094
- * "method": "DELETE"
20095
- * }
20096
- * }
20097
- */
20098
- "application/json": components["schemas"]["ErrorResponseDto"];
20099
- };
20100
- };
20101
20288
  };
20102
20289
  };
20103
- ApiApiKeysController_update: {
20290
+ ApiOAuthClientsController_get: {
20104
20291
  parameters: {
20105
20292
  query?: never;
20106
20293
  header?: never;
@@ -20109,24 +20296,20 @@ interface operations {
20109
20296
  };
20110
20297
  cookie?: never;
20111
20298
  };
20112
- requestBody: {
20113
- content: {
20114
- "application/json": components["schemas"]["UpdateApiKeyDto"];
20115
- };
20116
- };
20299
+ requestBody?: never;
20117
20300
  responses: {
20118
- /** @description API key updated */
20301
+ /** @description OAuth client returned */
20119
20302
  200: {
20120
20303
  headers: {
20121
20304
  [name: string]: unknown;
20122
20305
  };
20123
20306
  content: {
20124
20307
  "application/json": {
20125
- data: components["schemas"]["ApiKeyResponseDto"];
20308
+ data: components["schemas"]["OAuthClientResponseDto"];
20126
20309
  };
20127
20310
  };
20128
20311
  };
20129
- /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header */
20312
+ /** @description The request sent both an `X-API-Key` and an `Authorization` header; send one */
20130
20313
  400: {
20131
20314
  headers: {
20132
20315
  [name: string]: unknown;
@@ -20137,10 +20320,10 @@ interface operations {
20137
20320
  * "error": {
20138
20321
  * "statusCode": 400,
20139
20322
  * "code": null,
20140
- * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header",
20323
+ * "message": "The request sent both an `X-API-Key` and an `Authorization` header; send one",
20141
20324
  * "timestamp": "2026-04-20T12:00:00.000Z",
20142
- * "path": "/api/v1/api-keys/{id}",
20143
- * "method": "PATCH"
20325
+ * "path": "/api/v1/oauth-clients/{id}",
20326
+ * "method": "GET"
20144
20327
  * }
20145
20328
  * }
20146
20329
  */
@@ -20160,7 +20343,7 @@ interface operations {
20160
20343
  * "code": null,
20161
20344
  * "message": "Invalid or expired token",
20162
20345
  * "timestamp": "2026-04-20T12:00:00.000Z",
20163
- * "path": "/api/v1/api-keys",
20346
+ * "path": "/api/v1/oauth-clients",
20164
20347
  * "method": "GET"
20165
20348
  * }
20166
20349
  * }
@@ -20181,7 +20364,7 @@ interface operations {
20181
20364
  * "code": null,
20182
20365
  * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
20183
20366
  * "timestamp": "2026-04-20T12:00:00.000Z",
20184
- * "path": "/api/v1/api-keys",
20367
+ * "path": "/api/v1/oauth-clients",
20185
20368
  * "method": "GET"
20186
20369
  * }
20187
20370
  * }
@@ -20189,7 +20372,7 @@ interface operations {
20189
20372
  "application/json": components["schemas"]["ErrorResponseDto"];
20190
20373
  };
20191
20374
  };
20192
- /** @description API key not found */
20375
+ /** @description No OAuth client with that id exists in this Environment */
20193
20376
  404: {
20194
20377
  headers: {
20195
20378
  [name: string]: unknown;
@@ -20200,10 +20383,10 @@ interface operations {
20200
20383
  * "error": {
20201
20384
  * "statusCode": 404,
20202
20385
  * "code": null,
20203
- * "message": "API key not found",
20386
+ * "message": "No OAuth client with that id exists in this Environment",
20204
20387
  * "timestamp": "2026-04-20T12:00:00.000Z",
20205
- * "path": "/api/v1/api-keys/{id}",
20206
- * "method": "PATCH"
20388
+ * "path": "/api/v1/oauth-clients/{id}",
20389
+ * "method": "GET"
20207
20390
  * }
20208
20391
  * }
20209
20392
  */
@@ -20212,7 +20395,7 @@ interface operations {
20212
20395
  };
20213
20396
  };
20214
20397
  };
20215
- ApiApiKeysController_rotateSecret: {
20398
+ ApiOAuthClientsController_remove: {
20216
20399
  parameters: {
20217
20400
  query?: never;
20218
20401
  header?: never;
@@ -20223,18 +20406,14 @@ interface operations {
20223
20406
  };
20224
20407
  requestBody?: never;
20225
20408
  responses: {
20226
- /** @description New key value returned once; the previous value stops working immediately */
20227
- 200: {
20409
+ /** @description OAuth client deleted */
20410
+ 204: {
20228
20411
  headers: {
20229
20412
  [name: string]: unknown;
20230
20413
  };
20231
- content: {
20232
- "application/json": {
20233
- data: components["schemas"]["ApiKeyCreatedResponseDto"];
20234
- };
20235
- };
20414
+ content?: never;
20236
20415
  };
20237
- /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header */
20416
+ /** @description The request sent both an `X-API-Key` and an `Authorization` header; send one */
20238
20417
  400: {
20239
20418
  headers: {
20240
20419
  [name: string]: unknown;
@@ -20245,10 +20424,10 @@ interface operations {
20245
20424
  * "error": {
20246
20425
  * "statusCode": 400,
20247
20426
  * "code": null,
20248
- * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header",
20427
+ * "message": "The request sent both an `X-API-Key` and an `Authorization` header; send one",
20249
20428
  * "timestamp": "2026-04-20T12:00:00.000Z",
20250
- * "path": "/api/v1/api-keys/{id}/rotate-secret",
20251
- * "method": "POST"
20429
+ * "path": "/api/v1/oauth-clients/{id}",
20430
+ * "method": "GET"
20252
20431
  * }
20253
20432
  * }
20254
20433
  */
@@ -20268,7 +20447,7 @@ interface operations {
20268
20447
  * "code": null,
20269
20448
  * "message": "Invalid or expired token",
20270
20449
  * "timestamp": "2026-04-20T12:00:00.000Z",
20271
- * "path": "/api/v1/api-keys",
20450
+ * "path": "/api/v1/oauth-clients",
20272
20451
  * "method": "GET"
20273
20452
  * }
20274
20453
  * }
@@ -20289,7 +20468,800 @@ interface operations {
20289
20468
  * "code": null,
20290
20469
  * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
20291
20470
  * "timestamp": "2026-04-20T12:00:00.000Z",
20292
- * "path": "/api/v1/api-keys",
20471
+ * "path": "/api/v1/oauth-clients",
20472
+ * "method": "GET"
20473
+ * }
20474
+ * }
20475
+ */
20476
+ "application/json": components["schemas"]["ErrorResponseDto"];
20477
+ };
20478
+ };
20479
+ /** @description No OAuth client with that id exists in this Environment */
20480
+ 404: {
20481
+ headers: {
20482
+ [name: string]: unknown;
20483
+ };
20484
+ content: {
20485
+ /**
20486
+ * @example {
20487
+ * "error": {
20488
+ * "statusCode": 404,
20489
+ * "code": null,
20490
+ * "message": "No OAuth client with that id exists in this Environment",
20491
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20492
+ * "path": "/api/v1/oauth-clients/{id}",
20493
+ * "method": "DELETE"
20494
+ * }
20495
+ * }
20496
+ */
20497
+ "application/json": components["schemas"]["ErrorResponseDto"];
20498
+ };
20499
+ };
20500
+ };
20501
+ };
20502
+ ApiOAuthClientsController_update: {
20503
+ parameters: {
20504
+ query?: never;
20505
+ header?: never;
20506
+ path: {
20507
+ id: string;
20508
+ };
20509
+ cookie?: never;
20510
+ };
20511
+ requestBody: {
20512
+ content: {
20513
+ "application/json": components["schemas"]["UpdateOAuthClientDto"];
20514
+ };
20515
+ };
20516
+ responses: {
20517
+ /** @description OAuth client updated */
20518
+ 200: {
20519
+ headers: {
20520
+ [name: string]: unknown;
20521
+ };
20522
+ content: {
20523
+ "application/json": {
20524
+ data: components["schemas"]["OAuthClientResponseDto"];
20525
+ };
20526
+ };
20527
+ };
20528
+ /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range, `backchannel_logout_uri` names an address Canopy's servers will not call, or `initiate_login_uri` is malformed or not `https` (loopback hosts excepted); or the request sent both an `X-API-Key` and an `Authorization` header */
20529
+ 400: {
20530
+ headers: {
20531
+ [name: string]: unknown;
20532
+ };
20533
+ content: {
20534
+ /**
20535
+ * @example {
20536
+ * "error": {
20537
+ * "statusCode": 400,
20538
+ * "code": null,
20539
+ * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range, `backchannel_logout_uri` names an address Canopy's servers will not call, or `initiate_login_uri` is malformed or not `https` (loopback hosts excepted); or the request sent both an `X-API-Key` and an `Authorization` header",
20540
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20541
+ * "path": "/api/v1/oauth-clients/{id}",
20542
+ * "method": "PATCH"
20543
+ * }
20544
+ * }
20545
+ */
20546
+ "application/json": components["schemas"]["ErrorResponseDto"];
20547
+ };
20548
+ };
20549
+ /** @description Invalid or expired token */
20550
+ 401: {
20551
+ headers: {
20552
+ [name: string]: unknown;
20553
+ };
20554
+ content: {
20555
+ /**
20556
+ * @example {
20557
+ * "error": {
20558
+ * "statusCode": 401,
20559
+ * "code": null,
20560
+ * "message": "Invalid or expired token",
20561
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20562
+ * "path": "/api/v1/oauth-clients",
20563
+ * "method": "GET"
20564
+ * }
20565
+ * }
20566
+ */
20567
+ "application/json": components["schemas"]["ErrorResponseDto"];
20568
+ };
20569
+ };
20570
+ /** @description The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment */
20571
+ 403: {
20572
+ headers: {
20573
+ [name: string]: unknown;
20574
+ };
20575
+ content: {
20576
+ /**
20577
+ * @example {
20578
+ * "error": {
20579
+ * "statusCode": 403,
20580
+ * "code": null,
20581
+ * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
20582
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20583
+ * "path": "/api/v1/oauth-clients",
20584
+ * "method": "GET"
20585
+ * }
20586
+ * }
20587
+ */
20588
+ "application/json": components["schemas"]["ErrorResponseDto"];
20589
+ };
20590
+ };
20591
+ /** @description No OAuth client with that id exists in this Environment */
20592
+ 404: {
20593
+ headers: {
20594
+ [name: string]: unknown;
20595
+ };
20596
+ content: {
20597
+ /**
20598
+ * @example {
20599
+ * "error": {
20600
+ * "statusCode": 404,
20601
+ * "code": null,
20602
+ * "message": "No OAuth client with that id exists in this Environment",
20603
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20604
+ * "path": "/api/v1/oauth-clients/{id}",
20605
+ * "method": "PATCH"
20606
+ * }
20607
+ * }
20608
+ */
20609
+ "application/json": components["schemas"]["ErrorResponseDto"];
20610
+ };
20611
+ };
20612
+ };
20613
+ };
20614
+ ApiOAuthClientsController_rotateSecret: {
20615
+ parameters: {
20616
+ query?: never;
20617
+ header?: never;
20618
+ path: {
20619
+ id: string;
20620
+ };
20621
+ cookie?: never;
20622
+ };
20623
+ requestBody?: never;
20624
+ responses: {
20625
+ /** @description OAuth client secret rotated — the new secret is only shown once */
20626
+ 200: {
20627
+ headers: {
20628
+ [name: string]: unknown;
20629
+ };
20630
+ content: {
20631
+ "application/json": {
20632
+ data: components["schemas"]["OAuthClientSecretRotatedResponseDto"];
20633
+ };
20634
+ };
20635
+ };
20636
+ /** @description The request sent both an `X-API-Key` and an `Authorization` header; send one */
20637
+ 400: {
20638
+ headers: {
20639
+ [name: string]: unknown;
20640
+ };
20641
+ content: {
20642
+ /**
20643
+ * @example {
20644
+ * "error": {
20645
+ * "statusCode": 400,
20646
+ * "code": null,
20647
+ * "message": "The request sent both an `X-API-Key` and an `Authorization` header; send one",
20648
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20649
+ * "path": "/api/v1/oauth-clients/{id}",
20650
+ * "method": "GET"
20651
+ * }
20652
+ * }
20653
+ */
20654
+ "application/json": components["schemas"]["ErrorResponseDto"];
20655
+ };
20656
+ };
20657
+ /** @description Invalid or expired token */
20658
+ 401: {
20659
+ headers: {
20660
+ [name: string]: unknown;
20661
+ };
20662
+ content: {
20663
+ /**
20664
+ * @example {
20665
+ * "error": {
20666
+ * "statusCode": 401,
20667
+ * "code": null,
20668
+ * "message": "Invalid or expired token",
20669
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20670
+ * "path": "/api/v1/oauth-clients",
20671
+ * "method": "GET"
20672
+ * }
20673
+ * }
20674
+ */
20675
+ "application/json": components["schemas"]["ErrorResponseDto"];
20676
+ };
20677
+ };
20678
+ /** @description The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment */
20679
+ 403: {
20680
+ headers: {
20681
+ [name: string]: unknown;
20682
+ };
20683
+ content: {
20684
+ /**
20685
+ * @example {
20686
+ * "error": {
20687
+ * "statusCode": 403,
20688
+ * "code": null,
20689
+ * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
20690
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20691
+ * "path": "/api/v1/oauth-clients",
20692
+ * "method": "GET"
20693
+ * }
20694
+ * }
20695
+ */
20696
+ "application/json": components["schemas"]["ErrorResponseDto"];
20697
+ };
20698
+ };
20699
+ /** @description No OAuth client with that id exists in this Environment */
20700
+ 404: {
20701
+ headers: {
20702
+ [name: string]: unknown;
20703
+ };
20704
+ content: {
20705
+ /**
20706
+ * @example {
20707
+ * "error": {
20708
+ * "statusCode": 404,
20709
+ * "code": null,
20710
+ * "message": "No OAuth client with that id exists in this Environment",
20711
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20712
+ * "path": "/api/v1/oauth-clients/{id}/rotate-secret",
20713
+ * "method": "POST"
20714
+ * }
20715
+ * }
20716
+ */
20717
+ "application/json": components["schemas"]["ErrorResponseDto"];
20718
+ };
20719
+ };
20720
+ };
20721
+ };
20722
+ ApiApiKeysController_list: {
20723
+ parameters: {
20724
+ query?: {
20725
+ /** @description Page number (1-based) */
20726
+ page?: number;
20727
+ /** @description Items per page (1-100, default 20) */
20728
+ take?: number;
20729
+ /** @description Search term */
20730
+ q?: string;
20731
+ /** @description Column to sort by. Allowed values depend on the endpoint. */
20732
+ sort_by?: string;
20733
+ /** @description Sort direction */
20734
+ order?: "asc" | "desc";
20735
+ };
20736
+ header?: never;
20737
+ path?: never;
20738
+ cookie?: never;
20739
+ };
20740
+ requestBody?: never;
20741
+ responses: {
20742
+ /** @description Paginated list */
20743
+ 200: {
20744
+ headers: {
20745
+ [name: string]: unknown;
20746
+ };
20747
+ content: {
20748
+ "application/json": {
20749
+ items: components["schemas"]["ApiKeyResponseDto"][];
20750
+ pagination: components["schemas"]["PageMetaDto"];
20751
+ };
20752
+ };
20753
+ };
20754
+ /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header */
20755
+ 400: {
20756
+ headers: {
20757
+ [name: string]: unknown;
20758
+ };
20759
+ content: {
20760
+ /**
20761
+ * @example {
20762
+ * "error": {
20763
+ * "statusCode": 400,
20764
+ * "code": null,
20765
+ * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header",
20766
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20767
+ * "path": "/api/v1/api-keys",
20768
+ * "method": "GET"
20769
+ * }
20770
+ * }
20771
+ */
20772
+ "application/json": components["schemas"]["ErrorResponseDto"];
20773
+ };
20774
+ };
20775
+ /** @description Invalid or expired token */
20776
+ 401: {
20777
+ headers: {
20778
+ [name: string]: unknown;
20779
+ };
20780
+ content: {
20781
+ /**
20782
+ * @example {
20783
+ * "error": {
20784
+ * "statusCode": 401,
20785
+ * "code": null,
20786
+ * "message": "Invalid or expired token",
20787
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20788
+ * "path": "/api/v1/api-keys",
20789
+ * "method": "GET"
20790
+ * }
20791
+ * }
20792
+ */
20793
+ "application/json": components["schemas"]["ErrorResponseDto"];
20794
+ };
20795
+ };
20796
+ /** @description The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment */
20797
+ 403: {
20798
+ headers: {
20799
+ [name: string]: unknown;
20800
+ };
20801
+ content: {
20802
+ /**
20803
+ * @example {
20804
+ * "error": {
20805
+ * "statusCode": 403,
20806
+ * "code": null,
20807
+ * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
20808
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20809
+ * "path": "/api/v1/api-keys",
20810
+ * "method": "GET"
20811
+ * }
20812
+ * }
20813
+ */
20814
+ "application/json": components["schemas"]["ErrorResponseDto"];
20815
+ };
20816
+ };
20817
+ };
20818
+ };
20819
+ ApiApiKeysController_create: {
20820
+ parameters: {
20821
+ query?: never;
20822
+ header?: never;
20823
+ path?: never;
20824
+ cookie?: never;
20825
+ };
20826
+ requestBody: {
20827
+ content: {
20828
+ "application/json": components["schemas"]["CreateApiKeyDto"];
20829
+ };
20830
+ };
20831
+ responses: {
20832
+ /** @description API key created — key value is only shown once */
20833
+ 201: {
20834
+ headers: {
20835
+ [name: string]: unknown;
20836
+ };
20837
+ content: {
20838
+ "application/json": {
20839
+ data: components["schemas"]["ApiKeyCreatedResponseDto"];
20840
+ };
20841
+ };
20842
+ };
20843
+ /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header */
20844
+ 400: {
20845
+ headers: {
20846
+ [name: string]: unknown;
20847
+ };
20848
+ content: {
20849
+ /**
20850
+ * @example {
20851
+ * "error": {
20852
+ * "statusCode": 400,
20853
+ * "code": null,
20854
+ * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header",
20855
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20856
+ * "path": "/api/v1/api-keys",
20857
+ * "method": "POST"
20858
+ * }
20859
+ * }
20860
+ */
20861
+ "application/json": components["schemas"]["ErrorResponseDto"];
20862
+ };
20863
+ };
20864
+ /** @description Invalid or expired token */
20865
+ 401: {
20866
+ headers: {
20867
+ [name: string]: unknown;
20868
+ };
20869
+ content: {
20870
+ /**
20871
+ * @example {
20872
+ * "error": {
20873
+ * "statusCode": 401,
20874
+ * "code": null,
20875
+ * "message": "Invalid or expired token",
20876
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20877
+ * "path": "/api/v1/api-keys",
20878
+ * "method": "GET"
20879
+ * }
20880
+ * }
20881
+ */
20882
+ "application/json": components["schemas"]["ErrorResponseDto"];
20883
+ };
20884
+ };
20885
+ /** @description The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment */
20886
+ 403: {
20887
+ headers: {
20888
+ [name: string]: unknown;
20889
+ };
20890
+ content: {
20891
+ /**
20892
+ * @example {
20893
+ * "error": {
20894
+ * "statusCode": 403,
20895
+ * "code": null,
20896
+ * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
20897
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20898
+ * "path": "/api/v1/api-keys",
20899
+ * "method": "GET"
20900
+ * }
20901
+ * }
20902
+ */
20903
+ "application/json": components["schemas"]["ErrorResponseDto"];
20904
+ };
20905
+ };
20906
+ /** @description The account has reached its plan's monthly limit on active API keys (`m2m_tokens`); `data` carries the limit, the usage and an upgrade URL */
20907
+ 409: {
20908
+ headers: {
20909
+ [name: string]: unknown;
20910
+ };
20911
+ content: {
20912
+ /**
20913
+ * @example {
20914
+ * "error": {
20915
+ * "statusCode": 409,
20916
+ * "code": null,
20917
+ * "message": "The account has reached its plan's monthly limit on active API keys (`m2m_tokens`); `data` carries the limit, the usage and an upgrade URL",
20918
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20919
+ * "path": "/api/v1/api-keys",
20920
+ * "method": "POST"
20921
+ * }
20922
+ * }
20923
+ */
20924
+ "application/json": components["schemas"]["ErrorResponseDto"];
20925
+ };
20926
+ };
20927
+ /** @description The `Idempotency-Key` was already used by this caller for a request with a different method, path or body. A replay must repeat the original request exactly; a new request takes a new key. */
20928
+ 422: {
20929
+ headers: {
20930
+ [name: string]: unknown;
20931
+ };
20932
+ content: {
20933
+ /**
20934
+ * @example {
20935
+ * "error": {
20936
+ * "statusCode": 422,
20937
+ * "code": null,
20938
+ * "message": "The `Idempotency-Key` was already used by this caller for a request with a different method, path or body. A replay must repeat the original request exactly; a new request takes a new key.",
20939
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20940
+ * "path": "/api/v1/api-keys",
20941
+ * "method": "POST"
20942
+ * }
20943
+ * }
20944
+ */
20945
+ "application/json": components["schemas"]["ErrorResponseDto"];
20946
+ };
20947
+ };
20948
+ /** @description More than 20 create requests in a minute from this caller (`x-canopy-rate-limit`); retry after the window */
20949
+ 429: {
20950
+ headers: {
20951
+ [name: string]: unknown;
20952
+ };
20953
+ content: {
20954
+ /**
20955
+ * @example {
20956
+ * "error": {
20957
+ * "statusCode": 429,
20958
+ * "code": null,
20959
+ * "message": "More than 20 create requests in a minute from this caller (`x-canopy-rate-limit`); retry after the window",
20960
+ * "timestamp": "2026-04-20T12:00:00.000Z",
20961
+ * "path": "/api/v1/api-keys",
20962
+ * "method": "POST"
20963
+ * }
20964
+ * }
20965
+ */
20966
+ "application/json": components["schemas"]["ErrorResponseDto"];
20967
+ };
20968
+ };
20969
+ };
20970
+ };
20971
+ ApiApiKeysController_delete: {
20972
+ parameters: {
20973
+ query?: never;
20974
+ header?: never;
20975
+ path: {
20976
+ id: string;
20977
+ };
20978
+ cookie?: never;
20979
+ };
20980
+ requestBody?: never;
20981
+ responses: {
20982
+ /** @description API key deleted */
20983
+ 204: {
20984
+ headers: {
20985
+ [name: string]: unknown;
20986
+ };
20987
+ content?: never;
20988
+ };
20989
+ /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header */
20990
+ 400: {
20991
+ headers: {
20992
+ [name: string]: unknown;
20993
+ };
20994
+ content: {
20995
+ /**
20996
+ * @example {
20997
+ * "error": {
20998
+ * "statusCode": 400,
20999
+ * "code": null,
21000
+ * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header",
21001
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21002
+ * "path": "/api/v1/api-keys/{id}",
21003
+ * "method": "DELETE"
21004
+ * }
21005
+ * }
21006
+ */
21007
+ "application/json": components["schemas"]["ErrorResponseDto"];
21008
+ };
21009
+ };
21010
+ /** @description Invalid or expired token */
21011
+ 401: {
21012
+ headers: {
21013
+ [name: string]: unknown;
21014
+ };
21015
+ content: {
21016
+ /**
21017
+ * @example {
21018
+ * "error": {
21019
+ * "statusCode": 401,
21020
+ * "code": null,
21021
+ * "message": "Invalid or expired token",
21022
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21023
+ * "path": "/api/v1/api-keys",
21024
+ * "method": "GET"
21025
+ * }
21026
+ * }
21027
+ */
21028
+ "application/json": components["schemas"]["ErrorResponseDto"];
21029
+ };
21030
+ };
21031
+ /** @description The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment */
21032
+ 403: {
21033
+ headers: {
21034
+ [name: string]: unknown;
21035
+ };
21036
+ content: {
21037
+ /**
21038
+ * @example {
21039
+ * "error": {
21040
+ * "statusCode": 403,
21041
+ * "code": null,
21042
+ * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
21043
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21044
+ * "path": "/api/v1/api-keys",
21045
+ * "method": "GET"
21046
+ * }
21047
+ * }
21048
+ */
21049
+ "application/json": components["schemas"]["ErrorResponseDto"];
21050
+ };
21051
+ };
21052
+ /** @description API key not found */
21053
+ 404: {
21054
+ headers: {
21055
+ [name: string]: unknown;
21056
+ };
21057
+ content: {
21058
+ /**
21059
+ * @example {
21060
+ * "error": {
21061
+ * "statusCode": 404,
21062
+ * "code": null,
21063
+ * "message": "API key not found",
21064
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21065
+ * "path": "/api/v1/api-keys/{id}",
21066
+ * "method": "DELETE"
21067
+ * }
21068
+ * }
21069
+ */
21070
+ "application/json": components["schemas"]["ErrorResponseDto"];
21071
+ };
21072
+ };
21073
+ };
21074
+ };
21075
+ ApiApiKeysController_update: {
21076
+ parameters: {
21077
+ query?: never;
21078
+ header?: never;
21079
+ path: {
21080
+ id: string;
21081
+ };
21082
+ cookie?: never;
21083
+ };
21084
+ requestBody: {
21085
+ content: {
21086
+ "application/json": components["schemas"]["UpdateApiKeyDto"];
21087
+ };
21088
+ };
21089
+ responses: {
21090
+ /** @description API key updated */
21091
+ 200: {
21092
+ headers: {
21093
+ [name: string]: unknown;
21094
+ };
21095
+ content: {
21096
+ "application/json": {
21097
+ data: components["schemas"]["ApiKeyResponseDto"];
21098
+ };
21099
+ };
21100
+ };
21101
+ /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header */
21102
+ 400: {
21103
+ headers: {
21104
+ [name: string]: unknown;
21105
+ };
21106
+ content: {
21107
+ /**
21108
+ * @example {
21109
+ * "error": {
21110
+ * "statusCode": 400,
21111
+ * "code": null,
21112
+ * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header",
21113
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21114
+ * "path": "/api/v1/api-keys/{id}",
21115
+ * "method": "PATCH"
21116
+ * }
21117
+ * }
21118
+ */
21119
+ "application/json": components["schemas"]["ErrorResponseDto"];
21120
+ };
21121
+ };
21122
+ /** @description Invalid or expired token */
21123
+ 401: {
21124
+ headers: {
21125
+ [name: string]: unknown;
21126
+ };
21127
+ content: {
21128
+ /**
21129
+ * @example {
21130
+ * "error": {
21131
+ * "statusCode": 401,
21132
+ * "code": null,
21133
+ * "message": "Invalid or expired token",
21134
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21135
+ * "path": "/api/v1/api-keys",
21136
+ * "method": "GET"
21137
+ * }
21138
+ * }
21139
+ */
21140
+ "application/json": components["schemas"]["ErrorResponseDto"];
21141
+ };
21142
+ };
21143
+ /** @description The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment */
21144
+ 403: {
21145
+ headers: {
21146
+ [name: string]: unknown;
21147
+ };
21148
+ content: {
21149
+ /**
21150
+ * @example {
21151
+ * "error": {
21152
+ * "statusCode": 403,
21153
+ * "code": null,
21154
+ * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
21155
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21156
+ * "path": "/api/v1/api-keys",
21157
+ * "method": "GET"
21158
+ * }
21159
+ * }
21160
+ */
21161
+ "application/json": components["schemas"]["ErrorResponseDto"];
21162
+ };
21163
+ };
21164
+ /** @description API key not found */
21165
+ 404: {
21166
+ headers: {
21167
+ [name: string]: unknown;
21168
+ };
21169
+ content: {
21170
+ /**
21171
+ * @example {
21172
+ * "error": {
21173
+ * "statusCode": 404,
21174
+ * "code": null,
21175
+ * "message": "API key not found",
21176
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21177
+ * "path": "/api/v1/api-keys/{id}",
21178
+ * "method": "PATCH"
21179
+ * }
21180
+ * }
21181
+ */
21182
+ "application/json": components["schemas"]["ErrorResponseDto"];
21183
+ };
21184
+ };
21185
+ };
21186
+ };
21187
+ ApiApiKeysController_rotateSecret: {
21188
+ parameters: {
21189
+ query?: never;
21190
+ header?: never;
21191
+ path: {
21192
+ id: string;
21193
+ };
21194
+ cookie?: never;
21195
+ };
21196
+ requestBody?: never;
21197
+ responses: {
21198
+ /** @description New key value returned once; the previous value stops working immediately */
21199
+ 200: {
21200
+ headers: {
21201
+ [name: string]: unknown;
21202
+ };
21203
+ content: {
21204
+ "application/json": {
21205
+ data: components["schemas"]["ApiKeyCreatedResponseDto"];
21206
+ };
21207
+ };
21208
+ };
21209
+ /** @description The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header */
21210
+ 400: {
21211
+ headers: {
21212
+ [name: string]: unknown;
21213
+ };
21214
+ content: {
21215
+ /**
21216
+ * @example {
21217
+ * "error": {
21218
+ * "statusCode": 400,
21219
+ * "code": null,
21220
+ * "message": "The request failed validation: a body field, a query parameter or an id in the path is missing, malformed or out of range; or the request sent both an `X-API-Key` and an `Authorization` header",
21221
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21222
+ * "path": "/api/v1/api-keys/{id}/rotate-secret",
21223
+ * "method": "POST"
21224
+ * }
21225
+ * }
21226
+ */
21227
+ "application/json": components["schemas"]["ErrorResponseDto"];
21228
+ };
21229
+ };
21230
+ /** @description Invalid or expired token */
21231
+ 401: {
21232
+ headers: {
21233
+ [name: string]: unknown;
21234
+ };
21235
+ content: {
21236
+ /**
21237
+ * @example {
21238
+ * "error": {
21239
+ * "statusCode": 401,
21240
+ * "code": null,
21241
+ * "message": "Invalid or expired token",
21242
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21243
+ * "path": "/api/v1/api-keys",
21244
+ * "method": "GET"
21245
+ * }
21246
+ * }
21247
+ */
21248
+ "application/json": components["schemas"]["ErrorResponseDto"];
21249
+ };
21250
+ };
21251
+ /** @description The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment */
21252
+ 403: {
21253
+ headers: {
21254
+ [name: string]: unknown;
21255
+ };
21256
+ content: {
21257
+ /**
21258
+ * @example {
21259
+ * "error": {
21260
+ * "statusCode": 403,
21261
+ * "code": null,
21262
+ * "message": "The bearer token is not an admin or platform token, or the caller lacks the permission this operation checks: a scoped API key without that scope, an admin without the Account capability that covers it, or, for a node-scoped check, a node outside this Environment",
21263
+ * "timestamp": "2026-04-20T12:00:00.000Z",
21264
+ * "path": "/api/v1/api-keys",
20293
21265
  * "method": "GET"
20294
21266
  * }
20295
21267
  * }
@@ -20749,6 +21721,12 @@ declare class Canopy {
20749
21721
  constructor(options: CanopyClientOptions);
20750
21722
  }
20751
21723
 
21724
+ /**
21725
+ * The longest a held answer may be kept: five minutes. `ttlMs` is the delay
21726
+ * between an access change and it taking effect, and Canopy promises that
21727
+ * delay is short, so a longer value is refused rather than honoured.
21728
+ */
21729
+ declare const MAX_TTL_MS = 300000;
20752
21730
  interface LocalAuthorizerOptions {
20753
21731
  /**
20754
21732
  * How long grant roots and the hierarchy are reused, in milliseconds.
@@ -20765,6 +21743,10 @@ interface LocalAuthorizerOptions {
20765
21743
  * for a caller who cannot accept a stale allow at all — it costs a round trip
20766
21744
  * per request, which is what this class exists to avoid, so reach for it
20767
21745
  * knowingly rather than as a default.
21746
+ *
21747
+ * **At most {@link MAX_TTL_MS} (five minutes).** A longer value, a negative
21748
+ * one or a non-number throws when the authorizer is created, rather than
21749
+ * quietly stretching how long a revoked user keeps access.
20768
21750
  */
20769
21751
  ttlMs?: number;
20770
21752
  /**
@@ -21011,11 +21993,22 @@ declare function isCanopyTokenError(error: unknown): error is CanopyTokenError;
21011
21993
 
21012
21994
  interface TokenVerifierOptions {
21013
21995
  /**
21014
- * The issuer whose tokens are accepted, matched against `iss` exactly.
21015
- * Defaults to Canopy's hosted issuer; set it for a self-hosted instance.
21996
+ * The Environment whose tokens are accepted. Every Environment is its own
21997
+ * issuer with its own signing keys, at
21998
+ * `https://auth.canopy-io.com/environments/<id>`, so on hosted Canopy this is
21999
+ * all verification needs. A token from any other Environment fails.
22000
+ *
22001
+ * Set exactly one of `environmentId` and `issuer`; the constructor throws
22002
+ * with neither or both.
22003
+ */
22004
+ environmentId?: string;
22005
+ /**
22006
+ * The issuer whose tokens are accepted, matched against `iss` exactly. Set it
22007
+ * instead of `environmentId` on a custom auth domain (`https://auth.acme.com`)
22008
+ * or a self-hosted instance (`<origin>/environments/<id>`).
21016
22009
  *
21017
- * Safe to default because it fails closed: pointed at the wrong issuer, a
21018
- * token is rejected rather than accepted.
22010
+ * Pointed at the wrong issuer, verification fails closed: a token is
22011
+ * rejected, never mistakenly accepted.
21019
22012
  */
21020
22013
  issuer?: string;
21021
22014
  /**
@@ -21239,4 +22232,4 @@ type WebhookEventData<Name extends WebhookEventName> = WebhookEvent<Name>["data"
21239
22232
  */
21240
22233
  declare function isWebhookEvent<Name extends WebhookEventName>(delivery: WebhookDelivery, name: Name): delivery is WebhookEvent<Name>;
21241
22234
 
21242
- export { type AssignmentItem, Assignments, type CallOptions, Canopy, CanopyAuthorizerError, CanopyClient, type CanopyClientOptions, CanopyConnectionError, CanopyError, type CanopyErrorBody, type CanopyOrgContext, type CanopyTokenClaims, CanopyTokenError, type Collection, type ConcurrencyOptions, type ConditionalResult, type CursorPagination, Identities, type IdentityAssignmentItem, type IdentityItem, type IdentitySessionItem, type LocalAuthorizationQuery, LocalAuthorizer, type LocalAuthorizerOptions, type LocalAuthorizerStats, type OffsetPagination, type OperationId, type OrganizationInviteItem, type OrganizationItem, type OrganizationMemberItem, Organizations, type PageFetcher, type PageParams, type PaginateOptions, type Pagination, Paginator, type PartialSuccess, type PermissionItem, Permissions, type QueryParams, type RequestBody, type RequestOptions, type ResponseBody, type RoleItem, Roles, type Schema, TokenVerifier, type TokenVerifierOptions, type WebhookDelivery, type WebhookEvent, type WebhookEventData, type WebhookEventName, type components, isCanopyAuthorizerError, isCanopyConnectionError, isCanopyError, isCanopyTokenError, isCursorPagination, isWebhookEvent, type operations, orgContext, paginate, type paths, withConcurrency };
22235
+ export { type AssignmentItem, Assignments, type CallOptions, Canopy, CanopyAuthorizerError, CanopyClient, type CanopyClientOptions, CanopyConnectionError, CanopyError, type CanopyErrorBody, type CanopyOrgContext, type CanopyTokenClaims, CanopyTokenError, type Collection, type ConcurrencyOptions, type ConditionalResult, type CursorPagination, Identities, type IdentityAssignmentItem, type IdentityItem, type IdentitySessionItem, type LocalAuthorizationQuery, LocalAuthorizer, type LocalAuthorizerOptions, type LocalAuthorizerStats, MAX_TTL_MS, type OffsetPagination, type OperationId, type OrganizationInviteItem, type OrganizationItem, type OrganizationMemberItem, Organizations, type PageFetcher, type PageParams, type PaginateOptions, type Pagination, Paginator, type PartialSuccess, type PermissionItem, Permissions, type QueryParams, type RequestBody, type RequestOptions, type ResponseBody, type RoleItem, Roles, type Schema, TokenVerifier, type TokenVerifierOptions, type WebhookDelivery, type WebhookEvent, type WebhookEventData, type WebhookEventName, type components, isCanopyAuthorizerError, isCanopyConnectionError, isCanopyError, isCanopyTokenError, isCursorPagination, isWebhookEvent, type operations, orgContext, paginate, type paths, withConcurrency };