deploy

Install

Select a method below to install the server.
Cursor
Claude Code
Claude Desktop
ChatGPT Desktop
VS Code
Antigravity CLI
Antigravity IDE
Codex CLI
opencode
Available Tools (38)
unkey_v2_deployments_create_deployment_v3 Create a deployment for an app in a project. Omit the source to use the app's configured default. A Git app builds its default branch. An OCI app deploys its default image. Optionally provide one source override: - `oci`: deploy a prebuilt OCI image without a build. Mutable tags are resolved to immutable digests before rollout. - `git`: build and deploy from the app's connected GitHub repository, a branch, a specific commit, or a fork commit. Requires the app to have a repository connected. - `deployment`: re-run an existing deployment by its id. Git deployments rebuild from the recorded commit; OCI deployments reuse the recorded resolved image. Returns immediately with a `deploymentId`. The build and rollout run asynchronously. Poll `deployments.getDeployment` to watch status until it is ready. **Authentication**: requires a root key with permission to create deployments. ▾
Create a deployment for an app in a project. Omit the source to use the app's configured default. A Git app builds its default branch. An OCI app deploys its default image. Optionally provide one source override: - `oci`: deploy a prebuilt OCI image without a build. Mutable tags are resolved to immutable digests before rollout. - `git`: build and deploy from the app's connected GitHub repository, a branch, a specific commit, or a fork commit. Requires the app to have a repository connected. - `deployment`: re-run an existing deployment by its id. Git deployments rebuild from the recorded commit; OCI deployments reuse the recorded resolved image. Returns immediately with a `deploymentId`. The build and rollout run asynchronously. Poll `deployments.getDeployment` to watch status until it is ready. **Authentication**: requires a root key with permission to create deployments.
Open-world
unkey_v2_workspace_get_usage Get the usage of your workspace for one calendar month (UTC): billable API operations, compute usage per environment, and active keys per app. Use this to track usage during the month or to look back at a past month. The response has no prices. Your invoice is the source of truth. Compute usage can be up to 15 minutes late, and it can change for up to 7 days. Send `{}` for the current month to date, or `{"period": {"year": 2026, "month": 9}}` for a full past month. The month must start within the last 90 days. **Required Permissions** Your root key must have this permission: - `unkey:v1:<workspace_id>:usage#read` ▾
Get the usage of your workspace for one calendar month (UTC): billable API operations, compute usage per environment, and active keys per app. Use this to track usage during the month or to look back at a past month. The response has no prices. Your invoice is the source of truth. Compute usage can be up to 15 minutes late, and it can change for up to 7 days. Send `{}` for the current month to date, or `{"period": {"year": 2026, "month": 9}}` for a full past month. The month must start within the last 90 days. **Required Permissions** Your root key must have this permission: - `unkey:v1:<workspace_id>:usage#read`
Open-world
unkey_v2_workspace_get_limits Get every limit of your workspace, with the current value against each limit that has one. Use this before an operation that a limit can reject, for example to see how many custom domains or log drains remain, or how much CPU, memory, and disk a new deployment can still reserve. The request takes no parameters. Each limit has a `limit`, which is `null` when unlimited, and a `current` value when the limit has one. Billable operations count the current calendar month in UTC. The Compute limits are present only when the workspace has a Compute plan. **Required Permissions** Your root key must have the following permission: - `unkey:v1:<workspace_id>:limits#read` ▾
Get every limit of your workspace, with the current value against each limit that has one. Use this before an operation that a limit can reject, for example to see how many custom domains or log drains remain, or how much CPU, memory, and disk a new deployment can still reserve. The request takes no parameters. Each limit has a `limit`, which is `null` when unlimited, and a `current` value when the limit has one. Billable operations count the current calendar month in UTC. The Compute limits are present only when the workspace has a Compute plan. **Required Permissions** Your root key must have the following permission: - `unkey:v1:<workspace_id>:limits#read`
Open-world
unkey_v2_projects_update_project Update an existing project in your workspace, identified by its id. The project name, slug, and delete protection setting can be changed. Omitted fields are left unchanged. Changing the slug affects the deployment domains generated for this project. **Required Permissions** Your root key must have one of the following permissions: - `project.*.update_project` (to update any project) - `project.<project_id>.update_project` (to update a specific project) ▾
Update an existing project in your workspace, identified by its id. The project name, slug, and delete protection setting can be changed. Omitted fields are left unchanged. Changing the slug affects the deployment domains generated for this project. **Required Permissions** Your root key must have one of the following permissions: - `project.*.update_project` (to update any project) - `project.<project_id>.update_project` (to update a specific project)
Open-world
unkey_v2_projects_list_projects Retrieve a paginated list of projects in your workspace. Use this to build project management dashboards or to enumerate projects for administrative purposes. Results are ordered by project id and returned in pages. When `hasMore` is true, pass the returned `cursor` to fetch the next page. **Required Permissions** Your root key must have the following permission: - `project.*.read_project` (to read projects in your workspace) ▾
Retrieve a paginated list of projects in your workspace. Use this to build project management dashboards or to enumerate projects for administrative purposes. Results are ordered by project id and returned in pages. When `hasMore` is true, pass the returned `cursor` to fetch the next page. **Required Permissions** Your root key must have the following permission: - `project.*.read_project` (to read projects in your workspace)
Open-world
unkey_v2_projects_get_project Retrieve a single project in your workspace by its id. Use this to fetch project details after creation, verify a project exists before performing operations, or resolve a project's metadata from its id. **Required Permissions** Your root key must have one of the following permissions: - `project.*.read_project` (to read any project) - `project.<project_id>.read_project` (to read a specific project) ▾
Retrieve a single project in your workspace by its id. Use this to fetch project details after creation, verify a project exists before performing operations, or resolve a project's metadata from its id. **Required Permissions** Your root key must have one of the following permissions: - `project.*.read_project` (to read any project) - `project.<project_id>.read_project` (to read a specific project)
Open-world
unkey_v2_projects_delete_project Delete an existing project in your workspace, identified by its id. Deletion is asynchronous and eventually consistent. The project and all of its associated resources (apps, environments, deployments, custom domains) are torn down by a background workflow. A successful response indicates the deletion was enqueued, not that every resource has already been removed. Projects with delete protection enabled cannot be deleted until protection is disabled. **Required Permissions** Your root key must have one of the following permissions: - `project.*.delete_project` (to delete any project) - `project.<project_id>.delete_project` (to delete a specific project) ▾
Delete an existing project in your workspace, identified by its id. Deletion is asynchronous and eventually consistent. The project and all of its associated resources (apps, environments, deployments, custom domains) are torn down by a background workflow. A successful response indicates the deletion was enqueued, not that every resource has already been removed. Projects with delete protection enabled cannot be deleted until protection is disabled. **Required Permissions** Your root key must have one of the following permissions: - `project.*.delete_project` (to delete any project) - `project.<project_id>.delete_project` (to delete a specific project)
Open-world
unkey_v2_projects_create_project Create a project to group deployments and applications under a workspace-scoped slug. The slug you provide is the stable, caller-defined handle used to reference this project in subsequent operations (get, update, delete). It must be unique within your workspace. **Important**: The slug cannot collide with an existing project in your workspace. A duplicate slug returns a 409 conflict. **Required Permissions** Your root key must have the following permission: - `project.*.create_project` (to create projects in your workspace) ▾
Create a project to group deployments and applications under a workspace-scoped slug. The slug you provide is the stable, caller-defined handle used to reference this project in subsequent operations (get, update, delete). It must be unique within your workspace. **Important**: The slug cannot collide with an existing project in your workspace. A duplicate slug returns a 409 conflict. **Required Permissions** Your root key must have the following permission: - `project.*.create_project` (to create projects in your workspace)
Open-world
unkey_v2_logs_get_api_request_metrics Count the requests that the Unkey API served for your workspace per time bucket, split by status class. The filters have the same shape as in `logs.listApiRequests`, without `requestId`. In one field, values under `is`, `contains`, `startsWith`, and `endsWith` are combined with OR. Values under `isNot` and `notContains`, and the range operators `gt`, `gte`, `lt`, and `lte`, are combined with AND. Different fields are combined with AND. Every text match is exact and case-sensitive. `filters.time` sets the window. A missing lower bound is the start of your log retention, and a missing upper bound is now. Unkey picks the bucket width from the window. It is the distance between the `time` of two points. The first bucket starts at or before the window start and counts its whole width. Windows reach back at most 100 days, and requests outside the log retention of your workspace are not counted. **Required Permissions** Your root key must have the following permission: - `unkey:v1:<workspace_id>:logs/apiRequests#read` ▾
Count the requests that the Unkey API served for your workspace per time bucket, split by status class. The filters have the same shape as in `logs.listApiRequests`, without `requestId`. In one field, values under `is`, `contains`, `startsWith`, and `endsWith` are combined with OR. Values under `isNot` and `notContains`, and the range operators `gt`, `gte`, `lt`, and `lte`, are combined with AND. Different fields are combined with AND. Every text match is exact and case-sensitive. `filters.time` sets the window. A missing lower bound is the start of your log retention, and a missing upper bound is now. Unkey picks the bucket width from the window. It is the distance between the `time` of two points. The first bucket starts at or before the window start and counts its whole width. Windows reach back at most 100 days, and requests outside the log retention of your workspace are not counted. **Required Permissions** Your root key must have the following permission: - `unkey:v1:<workspace_id>:logs/apiRequests#read`
Open-world
unkey_v2_github_install_app Start installing the Unkey GitHub App for your workspace. Returns a GitHub App install URL: open it in a browser to install the app and grant repository access. After installation GitHub returns to Unkey, which binds the installation to your workspace and lands you in the workspace settings. Installation is workspace-wide and takes no parameters. Once installed, link repositories to individual apps with the `git` field on `apps.createApp` and `apps.updateApp`. **Required Permissions** Your root key must have the following permission: - `workspace.*.install_github` ▾
Start installing the Unkey GitHub App for your workspace. Returns a GitHub App install URL: open it in a browser to install the app and grant repository access. After installation GitHub returns to Unkey, which binds the installation to your workspace and lands you in the workspace settings. Installation is workspace-wide and takes no parameters. Once installed, link repositories to individual apps with the `git` field on `apps.createApp` and `apps.updateApp`. **Required Permissions** Your root key must have the following permission: - `workspace.*.install_github`
Open-world
unkey_v2_gateway_update_policy Update a single policy in place without resending the environment's full policy list. The policy keeps its id and its position in the evaluation order, and all other policies are untouched. Omitted fields keep their stored values; at least one updatable field must be provided. Setting `match` to null removes all match expressions so the policy applies to every request. Providing one of `keyauth`, `ratelimit`, `firewall` or `openapi` replaces the policy's rule entirely, including switching its type; at most one may be set. Policy ids are regenerated whenever `gateway.setPolicies` replaces the list, so fetch current ids via `gateway.listPolicies` first. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.update_policy` (for any environment) - `environment.<environment_id>.update_policy` (for a specific environment) ▾
Update a single policy in place without resending the environment's full policy list. The policy keeps its id and its position in the evaluation order, and all other policies are untouched. Omitted fields keep their stored values; at least one updatable field must be provided. Setting `match` to null removes all match expressions so the policy applies to every request. Providing one of `keyauth`, `ratelimit`, `firewall` or `openapi` replaces the policy's rule entirely, including switching its type; at most one may be set. Policy ids are regenerated whenever `gateway.setPolicies` replaces the list, so fetch current ids via `gateway.listPolicies` first. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.update_policy` (for any environment) - `environment.<environment_id>.update_policy` (for a specific environment)
Open-world
unkey_v2_gateway_set_policies Replace an environment's gateway policies in a single atomic request. Policies run at the edge before requests reach your app: verify API keys, rate limit, block requests outright, or validate them against your OpenAPI spec. Policies are an ordered list: the gateway evaluates them top to bottom and the first rejection short-circuits the request. Each policy sets exactly one of `keyauth`, `ratelimit`, `firewall` or `openapi`, plus optional `match` expressions restricting which requests it applies to. Every call is a full replace: the environment's policies become exactly the request list in the given order, and the server generates a fresh id for each one. An empty list removes all policies. The operation is atomic: if any policy is invalid, nothing is written. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.set_policies` (for any environment) - `environment.<environment_id>.set_policies` (for a specific environment) ▾
Replace an environment's gateway policies in a single atomic request. Policies run at the edge before requests reach your app: verify API keys, rate limit, block requests outright, or validate them against your OpenAPI spec. Policies are an ordered list: the gateway evaluates them top to bottom and the first rejection short-circuits the request. Each policy sets exactly one of `keyauth`, `ratelimit`, `firewall` or `openapi`, plus optional `match` expressions restricting which requests it applies to. Every call is a full replace: the environment's policies become exactly the request list in the given order, and the server generates a fresh id for each one. An empty list removes all policies. The operation is atomic: if any policy is invalid, nothing is written. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.set_policies` (for any environment) - `environment.<environment_id>.set_policies` (for a specific environment)
Open-world
unkey_v2_gateway_list_policies Retrieve an environment's gateway policies in evaluation order: the gateway evaluates them top to bottom and the first rejection short-circuits the request. The full policy list is returned in a single response. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_policies` (for any environment) - `environment.<environment_id>.read_policies` (for a specific environment) ▾
Retrieve an environment's gateway policies in evaluation order: the gateway evaluates them top to bottom and the first rejection short-circuits the request. The full policy list is returned in a single response. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_policies` (for any environment) - `environment.<environment_id>.read_policies` (for a specific environment)
Open-world
unkey_v2_environments_update_settings Update the build, runtime, and regional settings for an environment. All settings fields are optional. Omit a field to leave it unchanged. For nullable fields (`dockerfile`, `healthcheck`, `openapiSpecPath`), send null to clear the value. When `regions` is present it replaces the full set of regions for the environment. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.update_environment` (to update any environment) - `environment.<environment_id>.update_environment` (to update a specific environment) ▾
Update the build, runtime, and regional settings for an environment. All settings fields are optional. Omit a field to leave it unchanged. For nullable fields (`dockerfile`, `healthcheck`, `openapiSpecPath`), send null to clear the value. When `regions` is present it replaces the full set of regions for the environment. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.update_environment` (to update any environment) - `environment.<environment_id>.update_environment` (to update a specific environment)
Open-world
unkey_v2_environments_set_environment_variables Create or update environment variables for an environment in a single atomic request. By default this is an upsert: each variable in the payload is created if new or fully overwritten if the key already exists, and any variable not in the payload is left untouched. This lets you change one variable without re-sending the others, which matters for write-only secrets you can no longer read back. Set `prune: true` to make it a full replace instead: after upserting, every variable not in the payload is deleted. Sending `prune: true` with an empty `variables` list resets the environment by deleting every variable. Each variable is written exactly as sent, never merged, so omitted optional fields fall back to their defaults rather than the previous value. Values are always encrypted at rest. Set `kind: recoverable` to allow a value to be read back; it defaults to `writeonly`, which can never be read back through the API. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.set_environment_variables` (for any environment) - `environment.<environment_id>.set_environment_variables` (for a specific environment) ▾
Create or update environment variables for an environment in a single atomic request. By default this is an upsert: each variable in the payload is created if new or fully overwritten if the key already exists, and any variable not in the payload is left untouched. This lets you change one variable without re-sending the others, which matters for write-only secrets you can no longer read back. Set `prune: true` to make it a full replace instead: after upserting, every variable not in the payload is deleted. Sending `prune: true` with an empty `variables` list resets the environment by deleting every variable. Each variable is written exactly as sent, never merged, so omitted optional fields fall back to their defaults rather than the previous value. Values are always encrypted at rest. Set `kind: recoverable` to allow a value to be read back; it defaults to `writeonly`, which can never be read back through the API. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.set_environment_variables` (for any environment) - `environment.<environment_id>.set_environment_variables` (for a specific environment)
Open-world
unkey_v2_environments_remove_environment_variables Remove environment variables from an environment in a single atomic request. This operation only deletes keys by name. Keys in the payload that exist are removed; keys that are not present are ignored, since their absence already matches the requested state. To replace or update values, use `setEnvironmentVariables` instead. The whole operation is atomic: if any part fails the environment is left unchanged. Duplicate keys in the payload collapse to a single removal. Values are never read or returned. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.remove_environment_variables` (for any environment) - `environment.<environment_id>.remove_environment_variables` (for a specific environment) ▾
Remove environment variables from an environment in a single atomic request. This operation only deletes keys by name. Keys in the payload that exist are removed; keys that are not present are ignored, since their absence already matches the requested state. To replace or update values, use `setEnvironmentVariables` instead. The whole operation is atomic: if any part fails the environment is left unchanged. Duplicate keys in the payload collapse to a single removal. Values are never read or returned. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.remove_environment_variables` (for any environment) - `environment.<environment_id>.remove_environment_variables` (for a specific environment)
Open-world
unkey_v2_environments_list_environments Retrieve the environments within an app. Use this to enumerate every environment in an app. Identify the app by its project slug and app slug. Results are ordered by environment id. An app has only a handful of environments, so all of them are returned in a single response. **Required Permissions** Your root key must have the following permission: - `environment.*.read_environment` (to read environments in any app) ▾
Retrieve the environments within an app. Use this to enumerate every environment in an app. Identify the app by its project slug and app slug. Results are ordered by environment id. An app has only a handful of environments, so all of them are returned in a single response. **Required Permissions** Your root key must have the following permission: - `environment.*.read_environment` (to read environments in any app)
Open-world
unkey_v2_environments_list_environment_variables Retrieve the environment variables for an environment. Identify the environment by its project, app, and environment identifiers. Results are ordered by variable id and paginated; when `hasMore` is true, pass the returned `cursor` to fetch the next page. `recoverable` variables are returned with their decrypted plaintext value. `writeonly` variables never expose a value: only the key, kind, and description are returned. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_environment_variables` (for any environment) - `environment.<environment_id>.read_environment_variables` (for a specific environment) ▾
Retrieve the environment variables for an environment. Identify the environment by its project, app, and environment identifiers. Results are ordered by variable id and paginated; when `hasMore` is true, pass the returned `cursor` to fetch the next page. `recoverable` variables are returned with their decrypted plaintext value. `writeonly` variables never expose a value: only the key, kind, and description are returned. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_environment_variables` (for any environment) - `environment.<environment_id>.read_environment_variables` (for a specific environment)
Open-world
unkey_v2_environments_get_environment Retrieve a single environment by its id. Use this to fetch environment details after creation or to verify an environment exists before performing operations. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_environment` (to read any environment) - `environment.<environment_id>.read_environment` (to read a specific environment) ▾
Retrieve a single environment by its id. Use this to fetch environment details after creation or to verify an environment exists before performing operations. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_environment` (to read any environment) - `environment.<environment_id>.read_environment` (to read a specific environment)
Open-world
unkey_v2_domains_verify_domain Restart verification for a custom domain. Address the domain by its ID or by its name. Names are unique per workspace, so `api.acme.com` is enough. Call this after you correct the DNS records of a domain that shows `failed`, or to give a `pending` domain a new 24-hour verification period. The domain goes back to `pending` and the 24-hour period starts again. The endpoint returns when Unkey accepts the retry. Poll `domains.getDomain` for the result. A domain that is already `verified` returns a 412. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.verify_domain` (to verify domains in any environment) - `environment.<environment_id>.verify_domain` (to verify domains in a specific environment) ▾
Restart verification for a custom domain. Address the domain by its ID or by its name. Names are unique per workspace, so `api.acme.com` is enough. Call this after you correct the DNS records of a domain that shows `failed`, or to give a `pending` domain a new 24-hour verification period. The domain goes back to `pending` and the 24-hour period starts again. The endpoint returns when Unkey accepts the retry. Poll `domains.getDomain` for the result. A domain that is already `verified` returns a 412. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.verify_domain` (to verify domains in any environment) - `environment.<environment_id>.verify_domain` (to verify domains in a specific environment)
Open-world
unkey_v2_domains_list_domains List your custom domains with their verification status and DNS records. Filter by project, app, or environment using IDs or slugs, or send `{}` to list domains across your workspace. Use any filter on its own or combine filters to narrow the results. Results match all supplied filters. Omitting `environment` includes all matching environments. Results include only domains you have permission to read, sorted by ID. When `hasMore` is true, send the returned `cursor` to get the next page. `status: verified` means the domain is verified. Unkey has configured routing and requested a certificate. Each domain includes its full `dnsRecords`. Each record has a `verified` flag. The flag shows which records Unkey has read back, so you can see which records are still missing without a second call. Some providers hide a record from DNS lookups, for example a proxied or flattened routing record. Such a record stays `false` while it serves traffic. **Required Permissions** Use a root key with the `environment.*.read_domain` permission. A successful request returns an empty list if no matching domains are readable by your key. ▾
List your custom domains with their verification status and DNS records. Filter by project, app, or environment using IDs or slugs, or send `{}` to list domains across your workspace. Use any filter on its own or combine filters to narrow the results. Results match all supplied filters. Omitting `environment` includes all matching environments. Results include only domains you have permission to read, sorted by ID. When `hasMore` is true, send the returned `cursor` to get the next page. `status: verified` means the domain is verified. Unkey has configured routing and requested a certificate. Each domain includes its full `dnsRecords`. Each record has a `verified` flag. The flag shows which records Unkey has read back, so you can see which records are still missing without a second call. Some providers hide a record from DNS lookups, for example a proxied or flattened routing record. Such a record stays `false` while it serves traffic. **Required Permissions** Use a root key with the `environment.*.read_domain` permission. A successful request returns an empty list if no matching domains are readable by your key.
Open-world
unkey_v2_domains_get_domain Retrieve a custom domain and its verification status. Address the domain by its id or by its name. Names are unique per workspace, so `api.acme.com` is sufficient. You do not need to supply a project, app, or environment. Use this endpoint to poll after `domains.createDomain`. Verification runs in the background and checks DNS approximately each minute. `status: verified` means the domain is verified. Unkey has configured routing and requested a certificate. Each entry in `dnsRecords` has a `verified` flag. The flag shows which records Unkey has read back, so you can see which records are still missing. Some providers hide a record from DNS lookups, for example a proxied or flattened routing record. Such a record stays `false` while it serves traffic. `verificationError` gives the reason for the last failed attempt. `dnsRecords` contains the same values that `domains.createDomain` returned. Use it to recover the values without creating the domain again. **Important**: verification stops 24 hours after the domain was created, and the status becomes `failed`. The window starts at `createdAt`, not at the last attempt. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_domain` (to read domains in any environment) - `environment.<environment_id>.read_domain` (to read domains in a specific environment) ▾
Retrieve a custom domain and its verification status. Address the domain by its id or by its name. Names are unique per workspace, so `api.acme.com` is sufficient. You do not need to supply a project, app, or environment. Use this endpoint to poll after `domains.createDomain`. Verification runs in the background and checks DNS approximately each minute. `status: verified` means the domain is verified. Unkey has configured routing and requested a certificate. Each entry in `dnsRecords` has a `verified` flag. The flag shows which records Unkey has read back, so you can see which records are still missing. Some providers hide a record from DNS lookups, for example a proxied or flattened routing record. Such a record stays `false` while it serves traffic. `verificationError` gives the reason for the last failed attempt. `dnsRecords` contains the same values that `domains.createDomain` returned. Use it to recover the values without creating the domain again. **Important**: verification stops 24 hours after the domain was created, and the status becomes `failed`. The window starts at `createdAt`, not at the last attempt. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.read_domain` (to read domains in any environment) - `environment.<environment_id>.read_domain` (to read domains in a specific environment)
Open-world
unkey_v2_domains_delete_domain Delete a custom domain from your workspace. Address the domain by its id or by its name. Names are unique per workspace, so `api.acme.com` is enough. Unkey stops serving the domain. Later requests fail with a certificate error. The DNS records at your provider stay in place. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.delete_domain` (to delete domains in any environment) - `environment.<environment_id>.delete_domain` (to delete domains in a specific environment) ▾
Delete a custom domain from your workspace. Address the domain by its id or by its name. Names are unique per workspace, so `api.acme.com` is enough. Unkey stops serving the domain. Later requests fail with a certificate error. The DNS records at your provider stay in place. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.delete_domain` (to delete domains in any environment) - `environment.<environment_id>.delete_domain` (to delete domains in a specific environment)
Open-world
unkey_v2_domains_create_domain Attach a custom domain to an environment and start verifying it. The domain is created in the `pending` state and does not serve traffic until verification succeeds. Verification runs in the background and polls DNS, so it is eventually consistent. The response returns `dnsRecords`: every record needed to finish setup, already resolved for whether this domain is an apex or a subdomain. Create every entry exactly as given. One record establishes routing and one proves ownership, and both are needed: whether ownership can be inferred from the routing record depends on how your provider publishes it, and a name another workspace has already verified can only be claimed through the ownership record. Neither is knowable before the records exist. When your DNS provider supports Domain Connect, the response also carries a `domainConnect` object; opening its `url` applies the same records at the provider in one step. The object is absent when the shortcut is unavailable. Domains are unique per workspace, so the same name cannot be attached to two environments. Attaching a domain that already exists in your workspace returns a 409 conflict. How many domains you may attach is set by your plan. Attaching one beyond that allowance returns a 403; upgrade the plan or remove a domain you no longer need. **Important**: verification stops after 24 hours without the required DNS records, and the domain moves to `failed`. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.create_domain` (to attach domains to any environment) - `environment.<environment_id>.create_domain` (to attach domains to a specific environment) ▾
Attach a custom domain to an environment and start verifying it. The domain is created in the `pending` state and does not serve traffic until verification succeeds. Verification runs in the background and polls DNS, so it is eventually consistent. The response returns `dnsRecords`: every record needed to finish setup, already resolved for whether this domain is an apex or a subdomain. Create every entry exactly as given. One record establishes routing and one proves ownership, and both are needed: whether ownership can be inferred from the routing record depends on how your provider publishes it, and a name another workspace has already verified can only be claimed through the ownership record. Neither is knowable before the records exist. When your DNS provider supports Domain Connect, the response also carries a `domainConnect` object; opening its `url` applies the same records at the provider in one step. The object is absent when the shortcut is unavailable. Domains are unique per workspace, so the same name cannot be attached to two environments. Attaching a domain that already exists in your workspace returns a 409 conflict. How many domains you may attach is set by your plan. Attaching one beyond that allowance returns a 403; upgrade the plan or remove a domain you no longer need. **Important**: verification stops after 24 hours without the required DNS records, and the domain moves to `failed`. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.create_domain` (to attach domains to any environment) - `environment.<environment_id>.create_domain` (to attach domains to a specific environment)
Open-world
unkey_v2_deployments_stop_deployment Stop a running preview deployment. Stopped deployments keep their configuration and can be resumed later with `startDeployment`. The deployment must be ready and running, and must belong to a non-production environment; production deployments cannot be stopped. A deployment that is already draining from a previous stop is rejected with a precondition error. Stopping is asynchronous: this endpoint only enqueues the stop and returns immediately. Poll `getDeployment` until the status reaches `stopped`. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.stop_deployment` (to stop deployments in any environment) - `environment.<environment_id>.stop_deployment` (to stop deployments in a specific environment) ▾
Stop a running preview deployment. Stopped deployments keep their configuration and can be resumed later with `startDeployment`. The deployment must be ready and running, and must belong to a non-production environment; production deployments cannot be stopped. A deployment that is already draining from a previous stop is rejected with a precondition error. Stopping is asynchronous: this endpoint only enqueues the stop and returns immediately. Poll `getDeployment` until the status reaches `stopped`. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.stop_deployment` (to stop deployments in any environment) - `environment.<environment_id>.stop_deployment` (to stop deployments in a specific environment)
Open-world
unkey_v2_deployments_start_deployment Start a deployment that was previously stopped with `stopDeployment`, so it serves traffic again. The deployment keeps the configuration it had when it was stopped; nothing is rebuilt or redeployed. The deployment must currently be stopped, and must belong to a non-production environment. Production deployments are never stopped, so they cannot be started. Starting is asynchronous: this endpoint only enqueues the start and returns immediately. Poll `getDeployment` until the status reaches `ready`. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.start_deployment` (to start deployments in any environment) - `environment.<environment_id>.start_deployment` (to start deployments in a specific environment) ▾
Start a deployment that was previously stopped with `stopDeployment`, so it serves traffic again. The deployment keeps the configuration it had when it was stopped; nothing is rebuilt or redeployed. The deployment must currently be stopped, and must belong to a non-production environment. Production deployments are never stopped, so they cannot be started. Starting is asynchronous: this endpoint only enqueues the start and returns immediately. Poll `getDeployment` until the status reaches `ready`. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.start_deployment` (to start deployments in any environment) - `environment.<environment_id>.start_deployment` (to start deployments in a specific environment)
Open-world
unkey_v2_deployments_rollback_deployment Roll live traffic back to a previous deployment. `deploymentId` is the deployment to roll back TO; the app's current deployment is used as the rollback source automatically. The target deployment must be ready, not already shutting down, belong to the production environment, and must not itself be the current deployment. After a rollback the app is marked as rolled back, which prevents new deployments from automatically taking over live traffic. Promote the rolled-back deployment (or a newer one) to clear this state. Rollback runs as a durable workflow: this endpoint returns once the rollback is accepted. Poll `getDeployment` or `listDeployments` to observe the result. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.rollback_deployment` (to roll back deployments in any environment) - `environment.<environment_id>.rollback_deployment` (to roll back deployments in a specific environment) ▾
Roll live traffic back to a previous deployment. `deploymentId` is the deployment to roll back TO; the app's current deployment is used as the rollback source automatically. The target deployment must be ready, not already shutting down, belong to the production environment, and must not itself be the current deployment. After a rollback the app is marked as rolled back, which prevents new deployments from automatically taking over live traffic. Promote the rolled-back deployment (or a newer one) to clear this state. Rollback runs as a durable workflow: this endpoint returns once the rollback is accepted. Poll `getDeployment` or `listDeployments` to observe the result. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.rollback_deployment` (to roll back deployments in any environment) - `environment.<environment_id>.rollback_deployment` (to roll back deployments in a specific environment)
Open-world
unkey_v2_deployments_promote_deployment Promote a deployment to become the current deployment for its environment. All sticky domains are reassigned from the current deployment to the promoted one, and the previous deployment is scheduled for standby. The deployment must be ready, not already shutting down, belong to the production environment, and its app must already have a current deployment. Promoting the deployment that is already current fails, unless the app is in a rolled-back state, in which case promoting the current deployment confirms the rollback and re-enables automatic promotion of future deployments. Promotion runs as a durable workflow: this endpoint returns once the promotion is accepted. Poll `getDeployment` or `listDeployments` to observe the result. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.promote_deployment` (to promote deployments in any environment) - `environment.<environment_id>.promote_deployment` (to promote deployments in a specific environment) ▾
Promote a deployment to become the current deployment for its environment. All sticky domains are reassigned from the current deployment to the promoted one, and the previous deployment is scheduled for standby. The deployment must be ready, not already shutting down, belong to the production environment, and its app must already have a current deployment. Promoting the deployment that is already current fails, unless the app is in a rolled-back state, in which case promoting the current deployment confirms the rollback and re-enables automatic promotion of future deployments. Promotion runs as a durable workflow: this endpoint returns once the promotion is accepted. Poll `getDeployment` or `listDeployments` to observe the result. **Required Permissions** Your root key must have one of the following permissions: - `environment.*.promote_deployment` (to promote deployments in any environment) - `environment.<environment_id>.promote_deployment` (to promote deployments in a specific environment)
Open-world
unkey_v2_deployments_list_deployments Retrieve a paginated list of deployments within a workspace, newest first. Filter by project, app, environment, lifecycle status, git branch, and creation time. All filters are optional; with none set, every deployment in the workspace is returned. Filters nest: `app` requires `project`, and `environment` and `branch` require both `project` and `app`. Results are paginated; when `hasMore` is true, pass the returned `cursor` to fetch the next page. **Required Permissions** Your root key must have this permission: - `unkey:v1:<workspace_id>:projects/<project_id>/apps/<app_id>/environments/<environment_id>/deployments/*#read` (use `*` for every level you do not filter by) The permission must cover every deployment the filters select: a grant on one environment is not sufficient for a request that spans more than that environment. ▾
Retrieve a paginated list of deployments within a workspace, newest first. Filter by project, app, environment, lifecycle status, git branch, and creation time. All filters are optional; with none set, every deployment in the workspace is returned. Filters nest: `app` requires `project`, and `environment` and `branch` require both `project` and `app`. Results are paginated; when `hasMore` is true, pass the returned `cursor` to fetch the next page. **Required Permissions** Your root key must have this permission: - `unkey:v1:<workspace_id>:projects/<project_id>/apps/<app_id>/environments/<environment_id>/deployments/*#read` (use `*` for every level you do not filter by) The permission must cover every deployment the filters select: a grant on one environment is not sufficient for a request that spans more than that environment.
Open-world
unkey_v2_deployments_list_build_logs Retrieve the build output of a deployment as a list of log entries, in the order the build printed them. A log entry is one chunk of build output, and can contain several lines or part of a line. Poll this endpoint to follow a running build: - Send the `pagination.cursor` of the last response as `cursor`. The response contains only the entries after it. - When `hasMore` is true, request again now. - When `hasMore` is false, you have all entries so far. Wait, then request again with the same cursor. - The cursor is absent only when the request had no cursor and the build has no entries yet. - A response can contain fewer than `limit` entries and still have `hasMore: true` when the entries are large. New entries become visible up to a few seconds after the build prints them. To know that a build is done, check the deployment status with `getDeployment`. After the status is no longer `building`, request until you get an empty response at least 5 seconds later. When a build attempt is retried, an entry from the earlier attempt can arrive after the cursor has moved past it, and a poll does not return it. A request without a cursor returns it. A deployment from a prebuilt image has no build and returns no entries. Build logs are kept for 3 months. **Required Permissions** Your root key must have the following permission: - `unkey:v1:<workspace_id>:projects/<project_id>/apps/<app_id>/environments/<environment_id>/deployments/<deployment_id>/buildLogs#read` ▾
Retrieve the build output of a deployment as a list of log entries, in the order the build printed them. A log entry is one chunk of build output, and can contain several lines or part of a line. Poll this endpoint to follow a running build: - Send the `pagination.cursor` of the last response as `cursor`. The response contains only the entries after it. - When `hasMore` is true, request again now. - When `hasMore` is false, you have all entries so far. Wait, then request again with the same cursor. - The cursor is absent only when the request had no cursor and the build has no entries yet. - A response can contain fewer than `limit` entries and still have `hasMore: true` when the entries are large. New entries become visible up to a few seconds after the build prints them. To know that a build is done, check the deployment status with `getDeployment`. After the status is no longer `building`, request until you get an empty response at least 5 seconds later. When a build attempt is retried, an entry from the earlier attempt can arrive after the cursor has moved past it, and a poll does not return it. A request without a cursor returns it. A deployment from a prebuilt image has no build and returns no entries. Build logs are kept for 3 months. **Required Permissions** Your root key must have the following permission: - `unkey:v1:<workspace_id>:projects/<project_id>/apps/<app_id>/environments/<environment_id>/deployments/<deployment_id>/buildLogs#read`
Open-world
unkey_v2_deployments_get_deployment Retrieve a single deployment by its id. Use this to check a deployment's status after creating it, or to inspect the runtime configuration of an existing deployment. **Required Permissions** Your root key must have this permission: - `unkey:v1:<workspace_id>:projects/<project_id>/apps/<app_id>/environments/<environment_id>/deployments/<deployment_id>#read` (use `*` for any level) ▾
Retrieve a single deployment by its id. Use this to check a deployment's status after creating it, or to inspect the runtime configuration of an existing deployment. **Required Permissions** Your root key must have this permission: - `unkey:v1:<workspace_id>:projects/<project_id>/apps/<app_id>/environments/<environment_id>/deployments/<deployment_id>#read` (use `*` for any level)
Open-world
unkey_v2_apps_update_app Update an existing app, identified by its id. The app name, slug, default branch, and delete protection setting can be changed. Omitted fields are left unchanged. Changing the slug affects the deployment domains generated for this app. **Important**: The slug cannot collide with an existing app in the same project. A duplicate slug returns a 409 conflict. **Required Permissions** Your root key must have one of the following permissions: - `app.*.update_app` (to update any app) - `app.<app_id>.update_app` (to update a specific app) ▾
Update an existing app, identified by its id. The app name, slug, default branch, and delete protection setting can be changed. Omitted fields are left unchanged. Changing the slug affects the deployment domains generated for this app. **Important**: The slug cannot collide with an existing app in the same project. A duplicate slug returns a 409 conflict. **Required Permissions** Your root key must have one of the following permissions: - `app.*.update_app` (to update any app) - `app.<app_id>.update_app` (to update a specific app)
Open-world
unkey_v2_apps_list_apps Retrieve a paginated list of apps within a project. Use this to enumerate every app in a project. Results are ordered by app id and paginated; when `hasMore` is true, pass the returned `cursor` to fetch the next page. **Required Permissions** Your root key must have the following permission: - `app.*.read_app` (to read apps in any project) ▾
Retrieve a paginated list of apps within a project. Use this to enumerate every app in a project. Results are ordered by app id and paginated; when `hasMore` is true, pass the returned `cursor` to fetch the next page. **Required Permissions** Your root key must have the following permission: - `app.*.read_app` (to read apps in any project)
Open-world
unkey_v2_apps_get_app Retrieve a single app by its id or slug within a project. Use this to fetch app details after creation or to verify an app exists before performing operations. **Required Permissions** Your root key must have one of the following permissions: - `app.*.read_app` (to read any app) - `app.<app_id>.read_app` (to read a specific app) ▾
Retrieve a single app by its id or slug within a project. Use this to fetch app details after creation or to verify an app exists before performing operations. **Required Permissions** Your root key must have one of the following permissions: - `app.*.read_app` (to read any app) - `app.<app_id>.read_app` (to read a specific app)
Open-world
unkey_v2_apps_delete_app Delete an existing app, identified by its id. Deletion is asynchronous and eventually consistent. The app and all of its associated resources (environments, deployments, custom domains) are torn down by a background workflow. A successful response indicates the deletion was enqueued, not that every resource has already been removed. Apps with delete protection enabled cannot be deleted until protection is disabled. **Required Permissions** Your root key must have one of the following permissions: - `app.*.delete_app` (to delete any app) - `app.<app_id>.delete_app` (to delete a specific app) ▾
Delete an existing app, identified by its id. Deletion is asynchronous and eventually consistent. The app and all of its associated resources (environments, deployments, custom domains) are torn down by a background workflow. A successful response indicates the deletion was enqueued, not that every resource has already been removed. Apps with delete protection enabled cannot be deleted until protection is disabled. **Required Permissions** Your root key must have one of the following permissions: - `app.*.delete_app` (to delete any app) - `app.<app_id>.delete_app` (to delete a specific app)
Open-world
unkey_v2_apps_create_app Create an app within a project. The app is created with default `production` and `preview` environments. Set exactly one source. Use `git` to create a GitHub-sourced app and connect its repository. Use `oci` to create an app from a prebuilt OCI image. The slug you provide is the stable, caller-defined handle used to reference this app. It must be unique within the project. **Important**: The slug cannot collide with an existing app in the same project. A duplicate slug returns a 409 conflict. **Required Permissions** Your root key must have one of the following permissions: - `project.*.create_app` (to create apps in any project) - `project.<project_id>.create_app` (to create apps in a specific project) ▾
Create an app within a project. The app is created with default `production` and `preview` environments. Set exactly one source. Use `git` to create a GitHub-sourced app and connect its repository. Use `oci` to create an app from a prebuilt OCI image. The slug you provide is the stable, caller-defined handle used to reference this app. It must be unique within the project. **Important**: The slug cannot collide with an existing app in the same project. A duplicate slug returns a 409 conflict. **Required Permissions** Your root key must have one of the following permissions: - `project.*.create_app` (to create apps in any project) - `project.<project_id>.create_app` (to create apps in a specific project)
Open-world
unkey_v2_analytics_get_runtime_logs A query can use only the public alias `runtime_logs_v1`. CTEs, subqueries, UNION, and EXCEPT are permitted. The root key must have the `project.*.read_runtime_logs` permission. Unkey limits each query to the workspace of the root key. To get the logs of one project, app, environment, or deployment, add a filter on `project_id`, `app_id`, `environment_id`, or `deployment_id`. The workspace retention period and the workspace query limits apply. For the table, the columns, and more query examples, see [Query runtime logs](/platform/analytics/get-runtime-logs). ▾
A query can use only the public alias `runtime_logs_v1`. CTEs, subqueries, UNION, and EXCEPT are permitted. The root key must have the `project.*.read_runtime_logs` permission. Unkey limits each query to the workspace of the root key. To get the logs of one project, app, environment, or deployment, add a filter on `project_id`, `app_id`, `environment_id`, or `deployment_id`. The workspace retention period and the workspace query limits apply. For the table, the columns, and more query examples, see [Query runtime logs](/platform/analytics/get-runtime-logs).
Open-world
unkey_v2_analytics_get_gateway_requests A query can use only the public alias `gateway_requests_v1`. CTEs, subqueries, UNION, and EXCEPT are permitted. The root key must have the `project.*.read_gateway_requests` permission. Unkey limits each query to the workspace of the root key. To get the data for one project, app, or environment, add a filter on `project_id`, `app_id`, or `environment_id`. The workspace retention period and the workspace query limits apply. For the columns and more query examples, see the gateway request analytics documentation. ▾
A query can use only the public alias `gateway_requests_v1`. CTEs, subqueries, UNION, and EXCEPT are permitted. The root key must have the `project.*.read_gateway_requests` permission. Unkey limits each query to the workspace of the root key. To get the data for one project, app, or environment, add a filter on `project_id`, `app_id`, or `environment_id`. The workspace retention period and the workspace query limits apply. For the columns and more query examples, see the gateway request analytics documentation.
Open-world
No tools match your search.
Server Instructions
These instructions are provided to LLMs when they connect to help them understand how to use the server effectively.
# Unkey Deploy

Manage projects, apps, environments, deployments, domains, and edge gateway policies.

## Resource hierarchy

`workspace → project → app → environment → deployment`

Most calls need the parent identifiers. Projects and apps are addressable by id or slug; slugs are caller-defined and must be unique within their parent. Creating an app provisions `production` and `preview` environments automatically.

## Typical setup flow

1. `projects.createProject` → `apps.createApp` (set exactly one source: `git` or `oci`).
2. For `git` apps: `github.installApp` first, open the returned URL in a browser, then connect the repo via the app's `git` field.
3. `environments.setEnvironmentVariables`, `environments.updateSettings` (build/runtime/regions).
4. `deployments.createDeployment` → poll `deployments.getDeployment`.
5. Optional: `domains.createDomain`, `gateway.setPolicies`.

## Asynchronous operations

Create, promote, rollback, start, stop, verify, and delete all return on acceptance, not completion. Always poll:

- deployments → `deployments.getDeployment` (status) and `deployments.listBuildLogs` (output, cursor-based; empty response ≠ build finished — check status first)
- domains → `domains.getDomain`
- deletions of projects/apps → eventually consistent; resources tear down in the background

## Traffic control

- Production only: `promoteDeployment`, `rollbackDeployment`. Target must be `ready`.
- Non-production only: `stopDeployment` / `startDeployment` (config preserved, nothing rebuilt).
- After a rollback the app is flagged rolled-back and new deployments stop auto-promoting. Promote any ready deployment (including the current one) to clear it.

## Replace vs. merge semantics

- `gateway.setPolicies`: full atomic replace, order = evaluation order, ids regenerated. Use `gateway.listPolicies` to get fresh ids before `gateway.updatePolicy`.
- `environments.setEnvironmentVariables`: upsert by default; `prune: true` makes it a full replace. Each variable is written whole — omitted optional fields reset to defaults.
- `environments.updateSettings`: per-field merge, but `regions` replaces the whole set; send `null` to clear nullable fields.

## Constraints

- Delete protection must be disabled before deleting a project or app.
- Duplicate slugs and duplicate domain names → 409.
- `writeonly` env vars can never be read back; use `kind: recoverable` if you need reads.
- Domain verification expires 24h after `createdAt`; re-arm with `domains.verifyDomain`. Create every returned DNS record.
- Check `workspace.getLimits` before adding domains, drains, or reserving CPU/memory/disk. `workspace.getUsage` lags up to 15 min and can change for 7 days.
- Log/metrics windows are capped (≤100 days) and bounded by workspace retention; build logs kept 3 months.
- Analytics tools accept SQL against only `runtime_logs_v1` / `gateway_requests_v1`, scoped to your workspace — filter by `project_id`/`app_id`/`environment_id`/`deployment_id` to narrow.
Server URL
https://mcp.unkey.com/mcp/compute
Raw Configuration
If you have a client that's not listed above, access the raw MCP configuration below. Check out the troubleshooting documentation for more help.
{ "command": "npx", "args": [ "mcp-remote@0.1.25", "https://mcp.unkey.com/mcp/compute", "--header", "Mcp-Unkey-V2-Bearer:${UNKEY_ROOT_KEY}" ], "env": { "UNKEY_ROOT_KEY": "<your-value-here>" } }