diff --git a/.changeset/wild-spies-punch.md b/.changeset/wild-spies-punch.md new file mode 100644 index 0000000000..99cf6c5b91 --- /dev/null +++ b/.changeset/wild-spies-punch.md @@ -0,0 +1,5 @@ +--- +"@unkey/api": minor +--- + +Add ratelimit override API diff --git a/apps/api/src/routes/v1_keys_getVerifications.ts b/apps/api/src/routes/v1_keys_getVerifications.ts index 387e9d534f..ba69979779 100644 --- a/apps/api/src/routes/v1_keys_getVerifications.ts +++ b/apps/api/src/routes/v1_keys_getVerifications.ts @@ -116,10 +116,10 @@ export const registerV1KeysGetVerifications = (app: App) => roles: dbRes.roles.map((p) => p.role.name), identity: dbRes.identity ? { - id: dbRes.identity.id, - externalId: dbRes.identity.externalId, - meta: dbRes.identity.meta, - } + id: dbRes.identity.id, + externalId: dbRes.identity.externalId, + meta: dbRes.identity.meta, + } : null, }; }); @@ -249,20 +249,20 @@ export const registerV1KeysGetVerifications = (app: App) => verifications[d.time] = { success: 0, rateLimited: 0, usageExceeded: 0 }; } switch (d.outcome) { - case "VALID": + // case "VALID": verifications[d.time].success += d.count; - break; + break; case "RATE_LIMITED": - verifications[d.time].rateLimited += d.count; - break; +verifications[d.time].rateLimited += d.count; +break; case "USAGE_EXCEEDED": - verifications[d.time].usageExceeded += d.count; - break; +verifications[d.time].usageExceeded += d.count; +break; } } } - // really ugly hack to return an emoty array in case there wasn't a single verification + // really ugly hack to return an empty array in case there wasn't a single verification // this became necessary when we switched to clickhouse, due to the different responses if ( Object.values(verifications).every(({ success, rateLimited, usageExceeded }) => { diff --git a/packages/api/src/client.ts b/packages/api/src/client.ts index c70ddbb35d..de2e79c1df 100644 --- a/packages/api/src/client.ts +++ b/packages/api/src/client.ts @@ -6,25 +6,25 @@ import { type Telemetry, getTelemetry } from "./telemetry"; export type UnkeyOptions = ( | { - token?: never; + token?: never; - /** - * The root key from unkey.dev. - * - * You can create/manage your root keys here: - * https://unkey.dev/app/settings/root-keys - */ - rootKey: string; - } + /** + * The root key from unkey.dev. + * + * You can create/manage your root keys here: + * https://unkey.dev/app/settings/root-keys + */ + rootKey: string; + } | { - /** - * The workspace key from unkey.dev - * - * @deprecated Use `rootKey` - */ - token: string; - rootKey?: never; - } + /** + * The workspace key from unkey.dev + * + * @deprecated Use `rootKey` + */ + token: string; + rootKey?: never; + } ) & { /** * @default https://api.unkey.dev @@ -77,32 +77,32 @@ export type UnkeyOptions = ( type ApiRequest = { path: string[]; } & ( - | { + | { method: "GET"; body?: never; query?: Record; } - | { + | { method: "POST"; body?: unknown; query?: never; } -); + ); type Result = | { - result: R; - error?: never; - } + result: R; + error?: never; + } | { - result?: never; - error: { - code: ErrorResponse["error"]["code"]; - message: ErrorResponse["error"]["message"]; - docs: ErrorResponse["error"]["docs"]; - requestId: string; - }; + result?: never; + error: { + code: ErrorResponse["error"]["code"]; + message: ErrorResponse["error"]["message"]; + docs: ErrorResponse["error"]["docs"]; + requestId: string; }; + }; export class Unkey { public readonly baseUrl: string; @@ -376,60 +376,60 @@ export class Unkey { body: req, }); }, - // getOverride: async ( - // req: paths["/v1/ratelimits.getOverride"]["get"]["parameters"]["query"], - // ): Promise< - // Result< - // paths["/v1/ratelimits.getOverride"]["get"]["responses"]["200"]["content"]["application/json"] - // > - // > => { - // return await this.fetch({ - // path: ["v1", "ratelimits.getOverride"], - // method: "GET", - // query: req, - // }); - // }, - // listOverrides: async ( - // req: paths["/v1/ratelimits.listOverrides"]["get"]["parameters"]["query"], - // ): Promise< - // Result< - // paths["/v1/ratelimits.listOverrides"]["get"]["responses"]["200"]["content"]["application/json"] - // > - // > => { - // return await this.fetch({ - // path: ["v1", "ratelimits.listOverrides"], - // method: "GET", - // query: req, - // }); - // }, + getOverride: async ( + req: paths["/v1/ratelimits.getOverride"]["get"]["parameters"]["query"], + ): Promise< + Result< + paths["/v1/ratelimits.getOverride"]["get"]["responses"]["200"]["content"]["application/json"] + > + > => { + return await this.fetch({ + path: ["v1", "ratelimits.getOverride"], + method: "GET", + query: req, + }); + }, + listOverrides: async ( + req: paths["/v1/ratelimits.listOverrides"]["get"]["parameters"]["query"], + ): Promise< + Result< + paths["/v1/ratelimits.listOverrides"]["get"]["responses"]["200"]["content"]["application/json"] + > + > => { + return await this.fetch({ + path: ["v1", "ratelimits.listOverrides"], + method: "GET", + query: req, + }); + }, - // setOverride: async ( - // req: paths["/v1/ratelimits.setOverride"]["post"]["requestBody"]["content"]["application/json"], - // ): Promise< - // Result< - // paths["/v1/ratelimits.setOverride"]["post"]["responses"]["200"]["content"]["application/json"] - // > - // > => { - // return await this.fetch({ - // path: ["v1", "ratelimits.setOverride"], - // method: "POST", - // body: req, - // }); - // }, + setOverride: async ( + req: paths["/v1/ratelimits.setOverride"]["post"]["requestBody"]["content"]["application/json"], + ): Promise< + Result< + paths["/v1/ratelimits.setOverride"]["post"]["responses"]["200"]["content"]["application/json"] + > + > => { + return await this.fetch({ + path: ["v1", "ratelimits.setOverride"], + method: "POST", + body: req, + }); + }, - // deleteOverride: async ( - // req: paths["/v1/ratelimits.deleteOverride"]["post"]["requestBody"]["content"]["application/json"], - // ): Promise< - // Result< - // paths["/v1/ratelimits.deleteOverride"]["post"]["responses"]["200"]["content"]["application/json"] - // > - // > => { - // return await this.fetch({ - // path: ["v1", "ratelimits.deleteOverride"], - // method: "POST", - // body: req, - // }); - // }, + deleteOverride: async ( + req: paths["/v1/ratelimits.deleteOverride"]["post"]["requestBody"]["content"]["application/json"], + ): Promise< + Result< + paths["/v1/ratelimits.deleteOverride"]["post"]["responses"]["200"]["content"]["application/json"] + > + > => { + return await this.fetch({ + path: ["v1", "ratelimits.deleteOverride"], + method: "POST", + body: req, + }); + }, }; } public get identities() { diff --git a/packages/api/src/openapi.d.ts b/packages/api/src/openapi.d.ts index d633b02af7..365fdff9f7 100644 --- a/packages/api/src/openapi.d.ts +++ b/packages/api/src/openapi.d.ts @@ -3,14 +3,11 @@ * Do not make direct changes to the file. */ + /** OneOf type helpers */ type Without = { [P in Exclude]?: never }; -type XOR = T | U extends object ? (Without & U) | (Without & T) : T | U; -type OneOf = T extends [infer Only] - ? Only - : T extends [infer A, infer B, ...infer Rest] - ? OneOf<[XOR, ...Rest]> - : never; +type XOR = (T | U) extends object ? (Without & U) | (Without & T) : T | U; +type OneOf = T extends [infer Only] ? Only : T extends [infer A, infer B, ...infer Rest] ? OneOf<[XOR, ...Rest]> : never; export interface paths { "/v1/liveness": { @@ -545,16 +542,7 @@ export interface components { * * @enum {string} */ - code: - | "VALID" - | "NOT_FOUND" - | "FORBIDDEN" - | "USAGE_EXCEEDED" - | "RATE_LIMITED" - | "UNAUTHORIZED" - | "DISABLED" - | "INSUFFICIENT_PERMISSIONS" - | "EXPIRED"; + code: "VALID" | "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED" | "UNAUTHORIZED" | "DISABLED" | "INSUFFICIENT_PERMISSIONS" | "EXPIRED"; /** @description Sets the key to be enabled or disabled. Disabled keys will not verify. */ enabled?: boolean; /** @@ -580,18 +568,11 @@ export interface components { }; }; /** @description A query for which permissions you require */ - PermissionQuery: OneOf< - [ - string, - { - and: components["schemas"]["PermissionQuery"][]; - }, - { - or: components["schemas"]["PermissionQuery"][]; - }, - null, - ] - >; + PermissionQuery: OneOf<[string, { + and: components["schemas"]["PermissionQuery"][]; + }, { + or: components["schemas"]["PermissionQuery"][]; + }, null]>; V1KeysVerifyKeyRequest: { /** * @description The id of the api where the key belongs to. This is optional for now but will be required soon. @@ -636,21 +617,21 @@ export interface components { * ] */ ratelimits?: { - /** - * @description The name of the ratelimit. - * @example tokens - */ - name: string; - /** - * @description Optionally override how expensive this operation is and how many tokens are deducted from the current limit. - * @default 1 - */ - cost?: number; - /** @description Optionally override the limit. */ - limit?: number; - /** @description Optionally override the ratelimit window duration. */ - duration?: number; - }[]; + /** + * @description The name of the ratelimit. + * @example tokens + */ + name: string; + /** + * @description Optionally override how expensive this operation is and how many tokens are deducted from the current limit. + * @default 1 + */ + cost?: number; + /** @description Optionally override the limit. */ + limit?: number; + /** @description Optionally override the ratelimit window duration. */ + duration?: number; + }[]; }; ErrDeleteProtected: { error: { @@ -676,7 +657,8 @@ export interface components { }; }; responses: never; - parameters: {}; + parameters: { + }; requestBodies: never; headers: never; pathItems: never; @@ -687,6 +669,7 @@ export type $defs = Record; export type external = Record; export interface operations { + "v1.liveness": { responses: { /** @description The configured services and their status */ @@ -1335,7 +1318,7 @@ export interface operations { * "refillInterval": 60 * } */ - ratelimit?: { + ratelimit?: ({ /** * @deprecated * @description Fast ratelimiting doesn't add latency, while consistent ratelimiting is more accurate. @@ -1367,7 +1350,7 @@ export interface operations { * This field will become required in a future version. */ duration?: number; - } | null; + }) | null; /** * @description The number of requests that can be made with this key before it becomes invalid. Set `null` to disable. * @example 1000 @@ -1380,7 +1363,7 @@ export interface operations { * "amount": 100 * } */ - refill?: { + refill?: ({ /** * @description Unkey will automatically refill verifications at the set interval. If null is used the refill functionality will be removed from the key. * @enum {string} @@ -1390,7 +1373,7 @@ export interface operations { amount: number; /** @description The day verifications will refill each month, when interval is set to 'monthly' */ refillDay?: number; - } | null; + }) | null; /** * @description Set if key is enabled or disabled. If disabled, the key cannot be used to verify. * @example true @@ -1413,16 +1396,16 @@ export interface operations { * ] */ roles?: { - /** @description The id of the role. Provide either `id` or `name`. If both are provided `id` is used. */ - id?: string; - /** @description Identify the role via its name. Provide either `id` or `name`. If both are provided `id` is used. */ - name?: string; - /** - * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. - * Autocreating roles requires your root key to have the `rbac.*.create_role` permission, otherwise the request will get rejected - */ - create?: boolean; - }[]; + /** @description The id of the role. Provide either `id` or `name`. If both are provided `id` is used. */ + id?: string; + /** @description Identify the role via its name. Provide either `id` or `name`. If both are provided `id` is used. */ + name?: string; + /** + * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. + * Autocreating roles requires your root key to have the `rbac.*.create_role` permission, otherwise the request will get rejected + */ + create?: boolean; + }[]; /** * @description The permissions you want to set for this key. This overwrites all existing permissions. * Setting permissions requires the `rbac.*.add_permission_to_key` permission. @@ -1440,16 +1423,16 @@ export interface operations { * ] */ permissions?: { - /** @description The id of the permission. Provide either `id` or `name`. If both are provided `id` is used. */ - id?: string; - /** @description Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used. */ - name?: string; - /** - * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. - * Autocreating permissions requires your root key to have the `rbac.*.create_permission` permission, otherwise the request will get rejected - */ - create?: boolean; - }[]; + /** @description The id of the permission. Provide either `id` or `name`. If both are provided `id` is used. */ + id?: string; + /** @description Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used. */ + name?: string; + /** + * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. + * Autocreating permissions requires your root key to have the `rbac.*.create_permission` permission, otherwise the request will get rejected + */ + create?: boolean; + }[]; }; }; }; @@ -1599,27 +1582,27 @@ export interface operations { content: { "application/json": { verifications: { - /** - * @description The timestamp of the usage data - * @example 1620000000000 - */ - time: number; - /** - * @description The number of successful requests - * @example 100 - */ - success: number; - /** - * @description The number of requests that were rate limited - * @example 10 - */ - rateLimited: number; - /** - * @description The number of requests that exceeded the usage limit - * @example 0 - */ - usageExceeded: number; - }[]; + /** + * @description The timestamp of the usage data + * @example 1620000000000 + */ + time: number; + /** + * @description The number of successful requests + * @example 100 + */ + success: number; + /** + * @description The number of requests that were rate limited + * @example 10 + */ + rateLimited: number; + /** + * @description The number of requests that exceeded the usage limit + * @example 0 + */ + usageExceeded: number; + }[]; }; }; }; @@ -1675,16 +1658,16 @@ export interface operations { keyId: string; /** @description The permissions you want to add to this key */ permissions: { - /** @description The id of the permission. Provide either `id` or `name`. If both are provided `id` is used. */ - id?: string; - /** @description Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used. */ - name?: string; - /** - * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. - * Autocreating permissions requires your root key to have the `rbac.*.create_permission` permission, otherwise the request will get rejected - */ - create?: boolean; - }[]; + /** @description The id of the permission. Provide either `id` or `name`. If both are provided `id` is used. */ + id?: string; + /** @description Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used. */ + name?: string; + /** + * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. + * Autocreating permissions requires your root key to have the `rbac.*.create_permission` permission, otherwise the request will get rejected + */ + create?: boolean; + }[]; }; }; }; @@ -1693,17 +1676,17 @@ export interface operations { 200: { content: { "application/json": { - /** - * @description The id of the permission. This is used internally - * @example perm_123 - */ - id: string; - /** - * @description The name of the permission - * @example dns.record.create - */ - name: string; - }[]; + /** + * @description The id of the permission. This is used internally + * @example perm_123 + */ + id: string; + /** + * @description The name of the permission + * @example dns.record.create + */ + name: string; + }[]; }; }; /** @description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */ @@ -1768,11 +1751,11 @@ export interface operations { * ] */ permissions: { - /** @description The id of the permission. Provide either `id` or `name`. If both are provided `id` is used. */ - id?: string; - /** @description Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used. */ - name?: string; - }[]; + /** @description The id of the permission. Provide either `id` or `name`. If both are provided `id` is used. */ + id?: string; + /** @description Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used. */ + name?: string; + }[]; }; }; }; @@ -1850,16 +1833,16 @@ export interface operations { * ] */ permissions: { - /** @description The id of the permission. Provide either `id` or `name`. If both are provided `id` is used. */ - id?: string; - /** @description Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used. */ - name?: string; - /** - * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. - * Autocreating permissions requires your root key to have the `rbac.*.create_permission` permission, otherwise the request will get rejected - */ - create?: boolean; - }[]; + /** @description The id of the permission. Provide either `id` or `name`. If both are provided `id` is used. */ + id?: string; + /** @description Identify the permission via its name. Provide either `id` or `name`. If both are provided `id` is used. */ + name?: string; + /** + * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. + * Autocreating permissions requires your root key to have the `rbac.*.create_permission` permission, otherwise the request will get rejected + */ + create?: boolean; + }[]; }; }; }; @@ -1868,17 +1851,17 @@ export interface operations { 200: { content: { "application/json": { - /** - * @description The id of the permission. This is used internally - * @example perm_123 - */ - id: string; - /** - * @description The name of the permission - * @example dns.record.create - */ - name: string; - }[]; + /** + * @description The id of the permission. This is used internally + * @example perm_123 + */ + id: string; + /** + * @description The name of the permission + * @example dns.record.create + */ + name: string; + }[]; }; }; /** @description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */ @@ -1948,16 +1931,16 @@ export interface operations { * ] */ roles: { - /** @description The id of the role. Provide either `id` or `name`. If both are provided `id` is used. */ - id?: string; - /** @description Identify the role via its name. Provide either `id` or `name`. If both are provided `id` is used. */ - name?: string; - /** - * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. - * Autocreating roles requires your root key to have the `rbac.*.create_role` permission, otherwise the request will get rejected - */ - create?: boolean; - }[]; + /** @description The id of the role. Provide either `id` or `name`. If both are provided `id` is used. */ + id?: string; + /** @description Identify the role via its name. Provide either `id` or `name`. If both are provided `id` is used. */ + name?: string; + /** + * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. + * Autocreating roles requires your root key to have the `rbac.*.create_role` permission, otherwise the request will get rejected + */ + create?: boolean; + }[]; }; }; }; @@ -1966,17 +1949,17 @@ export interface operations { 200: { content: { "application/json": { - /** - * @description The id of the role. This is used internally - * @example role_123 - */ - id: string; - /** - * @description The name of the role - * @example dns.record.create - */ - name: string; - }[]; + /** + * @description The id of the role. This is used internally + * @example role_123 + */ + id: string; + /** + * @description The name of the role + * @example dns.record.create + */ + name: string; + }[]; }; }; /** @description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */ @@ -2041,11 +2024,11 @@ export interface operations { * ] */ roles: { - /** @description The id of the role. Provide either `id` or `name`. If both are provided `id` is used. */ - id?: string; - /** @description Identify the role via its name. Provide either `id` or `name`. If both are provided `id` is used. */ - name?: string; - }[]; + /** @description The id of the role. Provide either `id` or `name`. If both are provided `id` is used. */ + id?: string; + /** @description Identify the role via its name. Provide either `id` or `name`. If both are provided `id` is used. */ + name?: string; + }[]; }; }; }; @@ -2123,16 +2106,16 @@ export interface operations { * ] */ roles: { - /** @description The id of the role. Provide either `id` or `name`. If both are provided `id` is used. */ - id?: string; - /** @description Identify the role via its name. Provide either `id` or `name`. If both are provided `id` is used. */ - name?: string; - /** - * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. - * Autocreating roles requires your root key to have the `rbac.*.create_role` permission, otherwise the request will get rejected - */ - create?: boolean; - }[]; + /** @description The id of the role. Provide either `id` or `name`. If both are provided `id` is used. */ + id?: string; + /** @description Identify the role via its name. Provide either `id` or `name`. If both are provided `id` is used. */ + name?: string; + /** + * @description Set to true to automatically create the permissions they do not exist yet. Only works when specifying `name`. + * Autocreating roles requires your root key to have the `rbac.*.create_role` permission, otherwise the request will get rejected + */ + create?: boolean; + }[]; }; }; }; @@ -2141,17 +2124,17 @@ export interface operations { 200: { content: { "application/json": { - /** - * @description The id of the role. This is used internally - * @example role_123 - */ - id: string; - /** - * @description The name of the role - * @example dns.record.create - */ - name: string; - }[]; + /** + * @description The id of the role. This is used internally + * @example role_123 + */ + id: string; + /** + * @description The name of the role + * @example dns.record.create + */ + name: string; + }[]; }; }; /** @description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */ @@ -2600,26 +2583,26 @@ export interface operations { * ] */ resources?: { - /** - * @description The type of resource - * @example organization - */ - type: string; - /** - * @description The unique identifier for the resource - * @example org_123 - */ - id: string; - /** - * @description A human readable name for this resource - * @example unkey - */ - name?: string; - /** @description Attach any metadata to this resources */ - meta?: { - [key: string]: unknown; - }; - }[]; + /** + * @description The type of resource + * @example organization + */ + type: string; + /** + * @description The unique identifier for the resource + * @example org_123 + */ + id: string; + /** + * @description A human readable name for this resource + * @example unkey + */ + name?: string; + /** @description Attach any metadata to this resources */ + meta?: { + [key: string]: unknown; + }; + }[]; }; }; }; @@ -3004,232 +2987,18 @@ export interface operations { "v1.migrations.createKeys": { requestBody: { content: { - "application/json": { - /** - * @description Choose an `API` where this key should be created. - * @example api_123 - */ - apiId: string; - /** - * @description To make it easier for your users to understand which product an api key belongs to, you can add prefix them. - * - * For example Stripe famously prefixes their customer ids with cus_ or their api keys with sk_live_. - * - * The underscore is automatically added if you are defining a prefix, for example: "prefix": "abc" will result in a key like abc_xxxxxxxxx - */ - prefix?: string; - /** - * @description The name for your Key. This is not customer facing. - * @example my key - */ - name?: string; - /** @description The raw key in plaintext. If provided, unkey encrypts this value and stores it securely. Provide either `hash` or `plaintext` */ - plaintext?: string; - /** @description Provide either `hash` or `plaintext` */ - hash?: { - /** @description The hashed and encoded key */ - value: string; + "application/json": ({ /** - * @description The algorithm for hashing and encoding, currently only sha256 and base64 are supported - * @enum {string} + * @description Choose an `API` where this key should be created. + * @example api_123 */ - variant: "sha256_base64"; - }; - /** - * @description The first 4 characters of the key. If a prefix is used, it should be the prefix plus 4 characters. - * @example unkey_32kq - */ - start?: string; - /** - * @description Your user’s Id. This will provide a link between Unkey and your customer record. - * When validating a key, we will return this back to you, so you can clearly identify your user from their api key. - * @example team_123 - */ - ownerId?: string; - /** - * @description This is a place for dynamic meta data, anything that feels useful for you should go here - * @example { - * "billingTier": "PRO", - * "trialEnds": "2023-06-16T17:16:37.161Z" - * } - */ - meta?: { - [key: string]: unknown; - }; - /** - * @description A list of roles that this key should have. If the role does not exist, an error is thrown - * @example [ - * "admin", - * "finance" - * ] - */ - roles?: string[]; - /** - * @description A list of permissions that this key should have. If the permission does not exist, an error is thrown - * @example [ - * "domains.create_record", - * "say_hello" - * ] - */ - permissions?: string[]; - /** - * @description You can auto expire keys by providing a unix timestamp in milliseconds. Once Keys expire they will automatically be disabled and are no longer valid unless you enable them again. - * @example 1623869797161 - */ - expires?: number; - /** - * @description You can limit the number of requests a key can make. Once a key reaches 0 remaining requests, it will automatically be disabled and is no longer valid unless you update it. - * @example 1000 - */ - remaining?: number; - /** - * @description Unkey enables you to refill verifications for each key at regular intervals. - * @example { - * "interval": "daily", - * "amount": 100 - * } - */ - refill?: { + apiId: string; /** - * @description Unkey will automatically refill verifications at the set interval. - * @enum {string} - */ - interval: "daily" | "monthly"; - /** @description The number of verifications to refill for each occurrence is determined individually for each key. */ - amount: number; - /** @description The day verifications will refill each month, when interval is set to 'monthly' */ - refillDay?: number; - }; - /** - * @description Unkey comes with per-key ratelimiting out of the box. - * @example { - * "type": "fast", - * "limit": 10, - * "refillRate": 1, - * "refillInterval": 60 - * } - */ - ratelimit?: { - /** - * @description Async will return a response immediately, lowering latency at the cost of accuracy. - * @default false - */ - async?: boolean; - /** - * @deprecated - * @description Fast ratelimiting doesn't add latency, while consistent ratelimiting is more accurate. - * @default fast - * @enum {string} - */ - type?: "fast" | "consistent"; - /** @description The total amount of burstable requests. */ - limit: number; - /** - * @deprecated - * @description How many tokens to refill during each refillInterval. - */ - refillRate: number; - /** - * @deprecated - * @description Determines the speed at which tokens are refilled, in milliseconds. - */ - refillInterval: number; - }; - /** - * @description Sets if key is enabled or disabled. Disabled keys are not valid. - * @default true - * @example false - */ - enabled?: boolean; - /** - * @description Environments allow you to divide your keyspace. - * - * Some applications like Stripe, Clerk, WorkOS and others have a concept of "live" and "test" keys to - * give the developer a way to develop their own application without the risk of modifying real world - * resources. - * - * When you set an environment, we will return it back to you when validating the key, so you can - * handle it correctly. - */ - environment?: string; - }[]; - }; - }; - responses: { - /** @description The key ids of all created keys */ - 200: { - content: { - "application/json": { - /** - * @description The ids of the keys. This is not a secret and can be stored as a reference if you wish. You need the keyId to update or delete a key later. - * @example [ - * "key_123", - * "key_456" - * ] - */ - keyIds: string[]; - }; - }; - }; - /** @description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */ - 400: { - content: { - "application/json": components["schemas"]["ErrBadRequest"]; - }; - }; - /** @description Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. */ - 401: { - content: { - "application/json": components["schemas"]["ErrUnauthorized"]; - }; - }; - /** @description The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. */ - 403: { - content: { - "application/json": components["schemas"]["ErrForbidden"]; - }; - }; - /** @description The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web. */ - 404: { - content: { - "application/json": components["schemas"]["ErrNotFound"]; - }; - }; - /** @description This response is sent when a request conflicts with the current state of the server. */ - 409: { - content: { - "application/json": components["schemas"]["ErrConflict"]; - }; - }; - /** @description The user has sent too many requests in a given amount of time ("rate limiting") */ - 429: { - content: { - "application/json": components["schemas"]["ErrTooManyRequests"]; - }; - }; - /** @description The server has encountered a situation it does not know how to handle. */ - 500: { - content: { - "application/json": components["schemas"]["ErrInternalServerError"]; - }; - }; - }; - }; - "v1.migrations.enqueueKeys": { - requestBody: { - content: { - "application/json": { - /** @description Contact support@unkey.dev to receive your migration id. */ - migrationId: string; - /** @description The id of the api, you want to migrate keys to */ - apiId: string; - keys: { - /** - * @description To make it easier for your users to understand which product an api key belongs to, you can add prefix them. - * - * For example Stripe famously prefixes their customer ids with cus_ or their api keys with sk_live_. - * - * The underscore is automatically added if you are defining a prefix, for example: "prefix": "abc" will result in a key like abc_xxxxxxxxx + * @description To make it easier for your users to understand which product an api key belongs to, you can add prefix them. + * + * For example Stripe famously prefixes their customer ids with cus_ or their api keys with sk_live_. + * + * The underscore is automatically added if you are defining a prefix, for example: "prefix": "abc" will result in a key like abc_xxxxxxxxx */ prefix?: string; /** @@ -3315,43 +3084,39 @@ export interface operations { refillDay?: number; }; /** - * @description Unkey comes with per-key fixed-window ratelimiting out of the box. + * @description Unkey comes with per-key ratelimiting out of the box. * @example { * "type": "fast", * "limit": 10, - * "duration": 60000 + * "refillRate": 1, + * "refillInterval": 60 * } */ ratelimit?: { /** * @description Async will return a response immediately, lowering latency at the cost of accuracy. - * @default true + * @default false */ async?: boolean; /** * @deprecated - * @description Deprecated, use `async`. Fast ratelimiting doesn't add latency, while consistent ratelimiting is more accurate. + * @description Fast ratelimiting doesn't add latency, while consistent ratelimiting is more accurate. * @default fast * @enum {string} */ type?: "fast" | "consistent"; - /** @description The total amount of requests in a given interval. */ + /** @description The total amount of burstable requests. */ limit: number; - /** - * @description The window duration in milliseconds - * @example 60000 - */ - duration: number; /** * @deprecated * @description How many tokens to refill during each refillInterval. */ - refillRate?: number; + refillRate: number; /** * @deprecated - * @description The refill timeframe, in milliseconds. + * @description Determines the speed at which tokens are refilled, in milliseconds. */ - refillInterval?: number; + refillInterval: number; }; /** * @description Sets if key is enabled or disabled. Disabled keys are not valid. @@ -3370,7 +3135,225 @@ export interface operations { * handle it correctly. */ environment?: string; - }[]; + })[]; + }; + }; + responses: { + /** @description The key ids of all created keys */ + 200: { + content: { + "application/json": { + /** + * @description The ids of the keys. This is not a secret and can be stored as a reference if you wish. You need the keyId to update or delete a key later. + * @example [ + * "key_123", + * "key_456" + * ] + */ + keyIds: string[]; + }; + }; + }; + /** @description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */ + 400: { + content: { + "application/json": components["schemas"]["ErrBadRequest"]; + }; + }; + /** @description Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. */ + 401: { + content: { + "application/json": components["schemas"]["ErrUnauthorized"]; + }; + }; + /** @description The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. */ + 403: { + content: { + "application/json": components["schemas"]["ErrForbidden"]; + }; + }; + /** @description The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web. */ + 404: { + content: { + "application/json": components["schemas"]["ErrNotFound"]; + }; + }; + /** @description This response is sent when a request conflicts with the current state of the server. */ + 409: { + content: { + "application/json": components["schemas"]["ErrConflict"]; + }; + }; + /** @description The user has sent too many requests in a given amount of time ("rate limiting") */ + 429: { + content: { + "application/json": components["schemas"]["ErrTooManyRequests"]; + }; + }; + /** @description The server has encountered a situation it does not know how to handle. */ + 500: { + content: { + "application/json": components["schemas"]["ErrInternalServerError"]; + }; + }; + }; + }; + "v1.migrations.enqueueKeys": { + requestBody: { + content: { + "application/json": { + /** @description Contact support@unkey.dev to receive your migration id. */ + migrationId: string; + /** @description The id of the api, you want to migrate keys to */ + apiId: string; + keys: ({ + /** + * @description To make it easier for your users to understand which product an api key belongs to, you can add prefix them. + * + * For example Stripe famously prefixes their customer ids with cus_ or their api keys with sk_live_. + * + * The underscore is automatically added if you are defining a prefix, for example: "prefix": "abc" will result in a key like abc_xxxxxxxxx + */ + prefix?: string; + /** + * @description The name for your Key. This is not customer facing. + * @example my key + */ + name?: string; + /** @description The raw key in plaintext. If provided, unkey encrypts this value and stores it securely. Provide either `hash` or `plaintext` */ + plaintext?: string; + /** @description Provide either `hash` or `plaintext` */ + hash?: { + /** @description The hashed and encoded key */ + value: string; + /** + * @description The algorithm for hashing and encoding, currently only sha256 and base64 are supported + * @enum {string} + */ + variant: "sha256_base64"; + }; + /** + * @description The first 4 characters of the key. If a prefix is used, it should be the prefix plus 4 characters. + * @example unkey_32kq + */ + start?: string; + /** + * @description Your user’s Id. This will provide a link between Unkey and your customer record. + * When validating a key, we will return this back to you, so you can clearly identify your user from their api key. + * @example team_123 + */ + ownerId?: string; + /** + * @description This is a place for dynamic meta data, anything that feels useful for you should go here + * @example { + * "billingTier": "PRO", + * "trialEnds": "2023-06-16T17:16:37.161Z" + * } + */ + meta?: { + [key: string]: unknown; + }; + /** + * @description A list of roles that this key should have. If the role does not exist, an error is thrown + * @example [ + * "admin", + * "finance" + * ] + */ + roles?: string[]; + /** + * @description A list of permissions that this key should have. If the permission does not exist, an error is thrown + * @example [ + * "domains.create_record", + * "say_hello" + * ] + */ + permissions?: string[]; + /** + * @description You can auto expire keys by providing a unix timestamp in milliseconds. Once Keys expire they will automatically be disabled and are no longer valid unless you enable them again. + * @example 1623869797161 + */ + expires?: number; + /** + * @description You can limit the number of requests a key can make. Once a key reaches 0 remaining requests, it will automatically be disabled and is no longer valid unless you update it. + * @example 1000 + */ + remaining?: number; + /** + * @description Unkey enables you to refill verifications for each key at regular intervals. + * @example { + * "interval": "daily", + * "amount": 100 + * } + */ + refill?: { + /** + * @description Unkey will automatically refill verifications at the set interval. + * @enum {string} + */ + interval: "daily" | "monthly"; + /** @description The number of verifications to refill for each occurrence is determined individually for each key. */ + amount: number; + /** @description The day verifications will refill each month, when interval is set to 'monthly' */ + refillDay?: number; + }; + /** + * @description Unkey comes with per-key fixed-window ratelimiting out of the box. + * @example { + * "type": "fast", + * "limit": 10, + * "duration": 60000 + * } + */ + ratelimit?: { + /** + * @description Async will return a response immediately, lowering latency at the cost of accuracy. + * @default true + */ + async?: boolean; + /** + * @deprecated + * @description Deprecated, use `async`. Fast ratelimiting doesn't add latency, while consistent ratelimiting is more accurate. + * @default fast + * @enum {string} + */ + type?: "fast" | "consistent"; + /** @description The total amount of requests in a given interval. */ + limit: number; + /** + * @description The window duration in milliseconds + * @example 60000 + */ + duration: number; + /** + * @deprecated + * @description How many tokens to refill during each refillInterval. + */ + refillRate?: number; + /** + * @deprecated + * @description The refill timeframe, in milliseconds. + */ + refillInterval?: number; + }; + /** + * @description Sets if key is enabled or disabled. Disabled keys are not valid. + * @default true + * @example false + */ + enabled?: boolean; + /** + * @description Environments allow you to divide your keyspace. + * + * Some applications like Stripe, Clerk, WorkOS and others have a concept of "live" and "test" keys to + * give the developer a way to develop their own application without the risk of modifying real world + * resources. + * + * When you set an environment, we will return it back to you when validating the key, so you can + * handle it correctly. + */ + environment?: string; + })[]; }; }; }; @@ -3641,22 +3624,22 @@ export interface operations { 200: { content: { "application/json": { - /** - * @description The id of the permission - * @example perm_123 - */ - id: string; - /** - * @description The name of the permission. - * @example domain.record.manager - */ - name: string; - /** - * @description The description of what this permission does. This is just for your team, your users will not see this. - * @example Can manage dns records - */ - description?: string; - }[]; + /** + * @description The id of the permission + * @example perm_123 + */ + id: string; + /** + * @description The name of the permission. + * @example domain.record.manager + */ + name: string; + /** + * @description The description of what this permission does. This is just for your team, your users will not see this. + * @example Can manage dns records + */ + description?: string; + }[]; }; }; /** @description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */ @@ -3919,22 +3902,22 @@ export interface operations { 200: { content: { "application/json": { - /** - * @description The id of the role - * @example role_1234 - */ - id: string; - /** - * @description The name of the role. - * @example domain.record.manager - */ - name: string; - /** - * @description The description of what this role does. This is just for your team, your users will not see this. - * @example Can manage dns records - */ - description?: string; - }[]; + /** + * @description The id of the role + * @example role_1234 + */ + id: string; + /** + * @description The name of the role. + * @example domain.record.manager + */ + name: string; + /** + * @description The description of what this role does. This is just for your team, your users will not see this. + * @example Can manage dns records + */ + description?: string; + }[]; }; }; /** @description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). */ @@ -4010,22 +3993,22 @@ export interface operations { * When verifying keys, you can specify which limits you want to use and all keys attached to this identity, will share the limits. */ ratelimits?: { - /** - * @description The name of this limit. You will need to use this again when verifying a key. - * @example tokens - */ - name: string; - /** - * @description How many requests may pass within a given window before requests are rejected. - * @example 10 - */ - limit: number; - /** - * @description The duration for each ratelimit window in milliseconds. - * @example 1000 - */ - duration: number; - }[]; + /** + * @description The name of this limit. You will need to use this again when verifying a key. + * @example tokens + */ + name: string; + /** + * @description How many requests may pass within a given window before requests are rejected. + * @example 10 + */ + limit: number; + /** + * @description The duration for each ratelimit window in milliseconds. + * @example 1000 + */ + duration: number; + }[]; }; }; }; @@ -4108,22 +4091,22 @@ export interface operations { }; /** @description When verifying keys, you can specify which limits you want to use and all keys attached to this identity, will share the limits. */ ratelimits: { - /** - * @description The name of this limit. You will need to use this again when verifying a key. - * @example tokens - */ - name: string; - /** - * @description How many requests may pass within a given window before requests are rejected. - * @example 10 - */ - limit: number; - /** - * @description The duration for each ratelimit window in milliseconds. - * @example 1000 - */ - duration: number; - }[]; + /** + * @description The name of this limit. You will need to use this again when verifying a key. + * @example tokens + */ + name: string; + /** + * @description How many requests may pass within a given window before requests are rejected. + * @example 10 + */ + limit: number; + /** + * @description The duration for each ratelimit window in milliseconds. + * @example 1000 + */ + duration: number; + }[]; }; }; }; @@ -4186,29 +4169,29 @@ export interface operations { "application/json": { /** @description A list of identities. */ identities: { - /** @description The id of this identity. Used to interact with unkey's API */ - id: string; - /** @description The id in your system */ - externalId: string; - /** @description When verifying keys, you can specify which limits you want to use and all keys attached to this identity, will share the limits. */ - ratelimits: { - /** - * @description The name of this limit. You will need to use this again when verifying a key. - * @example tokens - */ - name: string; - /** - * @description How many requests may pass within a given window before requests are rejected. - * @example 10 - */ - limit: number; - /** - * @description The duration for each ratelimit window in milliseconds. - * @example 1000 - */ - duration: number; + /** @description The id of this identity. Used to interact with unkey's API */ + id: string; + /** @description The id in your system */ + externalId: string; + /** @description When verifying keys, you can specify which limits you want to use and all keys attached to this identity, will share the limits. */ + ratelimits: { + /** + * @description The name of this limit. You will need to use this again when verifying a key. + * @example tokens + */ + name: string; + /** + * @description How many requests may pass within a given window before requests are rejected. + * @example 10 + */ + limit: number; + /** + * @description The duration for each ratelimit window in milliseconds. + * @example 1000 + */ + duration: number; + }[]; }[]; - }[]; /** * @description The cursor to use for the next page of results, if no cursor is returned, there are no more results * @example eyJrZXkiOiJrZXlfMTIzNCJ9 @@ -4301,22 +4284,22 @@ export interface operations { * When verifying keys, you can specify which limits you want to use and all keys attached to this identity, will share the limits. */ ratelimits?: { - /** - * @description The name of this limit. You will need to use this again when verifying a key. - * @example tokens - */ - name: string; - /** - * @description How many requests may pass within a given window before requests are rejected. - * @example 10 - */ - limit: number; - /** - * @description The duration for each ratelimit window in milliseconds. - * @example 1000 - */ - duration: number; - }[]; + /** + * @description The name of this limit. You will need to use this again when verifying a key. + * @example tokens + */ + name: string; + /** + * @description How many requests may pass within a given window before requests are rejected. + * @example 10 + */ + limit: number; + /** + * @description The duration for each ratelimit window in milliseconds. + * @example 1000 + */ + duration: number; + }[]; }; }; }; @@ -4345,22 +4328,22 @@ export interface operations { [key: string]: unknown; }; ratelimits: { - /** - * @description The name of this limit. - * @example tokens - */ - name: string; - /** - * @description How many requests may pass within a given window before requests are rejected. - * @example 10 - */ - limit: number; - /** - * @description The duration for each ratelimit window in milliseconds. - * @example 1000 - */ - duration: number; - }[]; + /** + * @description The name of this limit. + * @example tokens + */ + name: string; + /** + * @description How many requests may pass within a given window before requests are rejected. + * @example 10 + */ + limit: number; + /** + * @description The duration for each ratelimit window in milliseconds. + * @example 1000 + */ + duration: number; + }[]; }; }; }; @@ -4722,15 +4705,7 @@ export interface operations { * @example NOT_FOUND * @enum {string} */ - code?: - | "NOT_FOUND" - | "FORBIDDEN" - | "USAGE_EXCEEDED" - | "RATE_LIMITED" - | "UNAUTHORIZED" - | "DISABLED" - | "INSUFFICIENT_PERMISSIONS" - | "EXPIRED"; + code?: "NOT_FOUND" | "FORBIDDEN" | "USAGE_EXCEEDED" | "RATE_LIMITED" | "UNAUTHORIZED" | "DISABLED" | "INSUFFICIENT_PERMISSIONS" | "EXPIRED"; }; }; };