> ## Documentation Index
> Fetch the complete documentation index at: https://unkey.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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)




## OpenAPI

````yaml https://spec.speakeasy.com/unkey/unkey/openapi-json-with-code-samples post /v2/domains.createDomain
openapi: 3.1.0
info:
  description: >-
    Unkey's API provides programmatic access for all resources within our
    platform.



    ### Authentication

    #

    This API accepts HTTP Bearer credentials. Public integrations use root keys.
    Dashboard-originated requests use a short-lived dashboard proxy JWT minted
    by the dashboard server. Most endpoints require permissions associated with
    the authenticated principal. When making public API requests, include your
    root key in the `Authorization` header:

    ```

    Authorization: Bearer unkey_xxxxxxxxxxx

    ```


    All responses follow a consistent envelope structure that separates
    operational metadata from actual data. This design provides several
    benefits:

    - Debugging: Every response includes a unique requestId for tracing issues

    - Consistency: Predictable response format across all endpoints

    - Extensibility: Easy to add new metadata without breaking existing
    integrations

    - Error Handling: Unified error format with actionable information


    ### Success Response Format:

    ```json

    {
      "meta": {
        "requestId": "req_123456"
      },
      "data": {
        // Actual response data here
      }
    }

    ```


    The meta object contains operational information:

    - `requestId`: Unique identifier for this request (essential for support)


    The data object contains the actual response data specific to each endpoint.


    ### Paginated Response Format:

    ```json

    {
      "meta": {
        "requestId": "req_123456"
      },
      "data": [
        // Array of results
      ],
      "pagination": {
        "cursor": "next_page_token",
        "hasMore": true
      }
    }

    ```


    The pagination object appears on list endpoints and contains:

    - `cursor`: Token for requesting the next page

    - `hasMore`: Whether more results are available


    ### Error Response Format:

    ```json

    {
      "meta": {
        "requestId": "req_2c9a0jf23l4k567"
      },
      "error": {
        "detail": "The resource you are attempting to modify is protected and cannot be changed",
        "status": 403,
        "title": "Forbidden",
        "type": "https://unkey.com/docs/errors/unkey/application/protected_resource"
      }
    }

    ```


    Error responses include comprehensive diagnostic information:

    - `title`: Human-readable error summary

    - `detail`: Specific description of what went wrong

    - `status`: HTTP status code

    - `type`: Link to error documentation

    - `errors`: Array of validation errors (for 400 responses)


    This structure ensures you always have the context needed to debug issues
    and take corrective action.
  title: Unkey API
  version: 2.0.0
servers:
  - url: https://api.unkey.com
security:
  - bearer: []
tags:
  - description: Analytics query operations
    name: analytics
  - description: API management operations
    name: apis
  - description: App management operations
    name: apps
  - description: Deployment operations
    name: deploy
  - description: Deployment operations
    name: deployments
  - description: Custom domain operations
    name: domains
  - description: Environment management operations
    name: environments
  - description: Identity management operations
    name: identities
  - description: API key management operations
    name: keys
  - description: Health check operations
    name: liveness
  - description: Permission and role management operations
    name: permissions
  - description: Gateway policy operations
    name: gateway
  - description: Customer Portal session management
    name: portal
  - description: Rate limiting operations
    name: ratelimit
  - description: GitHub App installation operations
    name: github
paths:
  /v2/domains.createDomain:
    post:
      tags:
        - domains
      summary: Create domain
      description: >
        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)
      operationId: domains.createDomain
      requestBody:
        content:
          application/json:
            examples:
              apex:
                description: >-
                  An apex domain receives an apex-compatible alias, which the
                  provider resolves to the A or AAAA records that carry traffic,
                  plus a TXT record proving ownership.
                summary: Attach an apex domain
                value:
                  app: payments-api
                  domain: acme.com
                  environment: production
                  project: payments
              byId:
                description: Uses the ids returned by the corresponding list endpoints.
                summary: Attach a domain, locating the environment by ID
                value:
                  app: app_1234abcd
                  domain: api.acme.com
                  environment: env_1234abcd
                  project: proj_1234abcd
              bySlug:
                description: Uses the project, app, and environment slugs.
                summary: Attach a domain, locating the environment by slug
                value:
                  app: payments-api
                  domain: api.acme.com
                  environment: production
                  project: payments
            schema:
              $ref: '#/components/schemas/V2DomainsCreateDomainRequestBody'
        required: true
      responses:
        '200':
          content:
            application/json:
              examples:
                apex:
                  description: >-
                    An apex domain cannot hold a CNAME, so it needs an
                    apex-compatible alias and the TXT record.
                  summary: Apex domain attached
                  value:
                    data:
                      dnsRecords:
                        - name: acme.com
                          note: >-
                            Apex domains cannot hold a CNAME. Use ALIAS, ANAME,
                            or a flattened CNAME depending on your provider.
                          type: ALIAS
                          value: a1b2c3d4e5f6g7h8.cname.unkey.com
                          verified: false
                        - name: _unkey.acme.com
                          note: >-
                            Proves ownership. An apex domain cannot be verified
                            through its routing record, so this is the only
                            proof available.
                          type: TXT
                          value: unkey-domain-verify=3ZQ8xK1mP7vT5nR2wY6bJ4hL
                          verified: false
                      domainId: dom_1234abcd
                    meta:
                      requestId: req_1234abcd
                domainConnect:
                  description: The same records can be applied through the returned URL.
                  summary: Domain attached at a Domain Connect provider
                  value:
                    data:
                      dnsRecords:
                        - name: api.acme.com
                          note: >-
                            Create as DNS-only if your provider offers the
                            choice.
                          type: CNAME
                          value: a1b2c3d4e5f6g7h8.cname.unkey.com
                          verified: false
                        - name: _unkey.api.acme.com
                          note: >-
                            Proves ownership. Create it alongside the routing
                            record.
                          type: TXT
                          value: unkey-domain-verify=3ZQ8xK1mP7vT5nR2wY6bJ4hL
                          verified: false
                      domainConnect:
                        provider: Cloudflare
                        url: >-
                          https://dash.cloudflare.com/domainconnect/v2/domaintemplates/apply?domain=acme.com&host=api
                      domainId: dom_1234abcd
                    meta:
                      requestId: req_1234abcd
                subdomain:
                  description: >-
                    A subdomain can hold a CNAME, so it gets the CNAME record
                    for routing and the TXT record for ownership.
                  summary: Subdomain attached
                  value:
                    data:
                      dnsRecords:
                        - name: api.acme.com
                          note: >-
                            Create as DNS-only if your provider offers the
                            choice.
                          type: CNAME
                          value: a1b2c3d4e5f6g7h8.cname.unkey.com
                          verified: false
                        - name: _unkey.api.acme.com
                          note: >-
                            Proves ownership. Create it alongside the routing
                            record.
                          type: TXT
                          value: unkey-domain-verify=3ZQ8xK1mP7vT5nR2wY6bJ4hL
                          verified: false
                      domainId: dom_1234abcd
                    meta:
                      requestId: req_1234abcd
              schema:
                $ref: '#/components/schemas/V2DomainsCreateDomainResponseBody'
          description: >
            Domain created and verification started. The domain is `pending`
            until the DNS records resolve.
        '400':
          content:
            application/json:
              examples:
                invalidDomain:
                  summary: Invalid domain format
                  value:
                    error:
                      detail: >-
                        The domain 'https://api.acme.com' is not a valid fully
                        qualified domain name. Pass a name such as
                        'api.acme.com', without a scheme, port, or path.
                      status: 400
                      title: Bad Request
                      type: >-
                        https://unkey.com/docs/errors/unkey/application/invalid_input
                    meta:
                      requestId: req_1234abcd
                publicSuffix:
                  summary: Public suffix rejected
                  value:
                    error:
                      detail: >-
                        The domain 'co.uk' is a public suffix that nobody can
                        own. Pass a domain registered to you, such as
                        'api.acme.com'.
                      status: 400
                      title: Bad Request
                      type: >-
                        https://unkey.com/docs/errors/unkey/application/invalid_input
                    meta:
                      requestId: req_1234abcd
              schema:
                $ref: '#/components/schemas/BadRequestErrorResponse'
          description: Bad request
        '401':
          content:
            application/json:
              examples:
                invalidRootKey:
                  summary: Root key not found
                  value:
                    error:
                      detail: The provided root key is invalid.
                      status: 401
                      title: Unauthorized
                      type: unauthorized
                    meta:
                      requestId: req_1234abcd
              schema:
                $ref: '#/components/schemas/UnauthorizedErrorResponse'
          description: Unauthorized
        '403':
          content:
            application/json:
              examples:
                allowanceExceeded:
                  description: >-
                    The workspace already holds every custom domain its plan
                    permits.
                  summary: Plan allowance reached
                  value:
                    error:
                      detail: >-
                        Your plan does not allow another custom domain. Upgrade
                        your plan, or remove a domain you no longer need, then
                        retry.
                      status: 403
                      title: Forbidden
                      type: >-
                        https://unkey.com/docs/errors/unkey/limits/custom_domain_limit_exceeded
                    meta:
                      requestId: req_1234abcd
                keyDisabled:
                  summary: Root key disabled
                  value:
                    error:
                      detail: The provided root key is disabled.
                      status: 403
                      title: Forbidden
                      type: forbidden
                    meta:
                      requestId: req_1234abcd
              schema:
                $ref: '#/components/schemas/ForbiddenErrorResponse'
          description: >
            Forbidden - The root key or its workspace is disabled, or the
            workspace has already attached as

            many custom domains as its plan allows. A root key that simply lacks

            `environment.*.create_domain` receives a 404 instead, so permissions
            cannot be used to discover

            which environments exist.
        '404':
          content:
            application/json:
              examples:
                environmentNotFound:
                  summary: Environment not found
                  value:
                    error:
                      detail: The requested environment does not exist.
                      status: 404
                      title: Not Found
                      type: not-found
                    meta:
                      requestId: req_1234abcd
              schema:
                $ref: '#/components/schemas/NotFoundErrorResponse'
          description: >
            Not Found - The environment does not exist in your workspace, or
            your root key may not read it.
        '409':
          content:
            application/json:
              examples:
                domainExists:
                  summary: Domain already attached
                  value:
                    error:
                      detail: >-
                        The domain 'api.acme.com' is already attached to this
                        workspace.
                      status: 409
                      title: Conflict
                      type: conflict
                    meta:
                      requestId: req_1234abcd
              schema:
                $ref: '#/components/schemas/ConflictErrorResponse'
          description: >-
            Conflict - The domain is already attached to an environment in this
            workspace.
        '429':
          content:
            application/json:
              examples:
                rateLimited:
                  summary: Workspace rate limit exceeded
                  value:
                    error:
                      detail: >-
                        You have exceeded the rate limit for this operation.
                        Retry after the window resets.
                      status: 429
                      title: Too Many Requests
                      type: rate-limited
                    meta:
                      requestId: req_1234abcd
              schema:
                $ref: '#/components/schemas/TooManyRequestsErrorResponse'
          description: Too Many Requests
        '500':
          content:
            application/json:
              examples:
                internalError:
                  summary: Unexpected server error
                  value:
                    error:
                      detail: >-
                        An unexpected error occurred. Contact support@unkey.com
                        with the requestId.
                      status: 500
                      title: Internal Server Error
                      type: internal-server-error
                    meta:
                      requestId: req_1234abcd
              schema:
                $ref: '#/components/schemas/InternalServerErrorResponse'
          description: Internal server error
      security:
        - bearer: []
      x-codeSamples:
        - lang: typescript
          label: Typescript (SDK)
          source: |-
            import { Unkey } from "@unkey/api";

            const unkey = new Unkey({
              rootKey: process.env["UNKEY_ROOT_KEY"] ?? "",
            });

            async function run() {
              const result = await unkey.domains.createDomain({
                project: "payments",
                app: "payments-api",
                environment: "production",
                domain: "acme.com",
              });

              console.log(result);
            }

            run();
components:
  schemas:
    V2DomainsCreateDomainRequestBody:
      type: object
      required:
        - project
        - app
        - environment
        - domain
      properties:
        project:
          $ref: '#/components/schemas/ResourceIdentifier'
        app:
          $ref: '#/components/schemas/ResourceIdentifier'
        environment:
          $ref: '#/components/schemas/ResourceIdentifier'
        domain:
          type: string
          minLength: 4
          maxLength: 253
          description: >
            Fully qualified domain name to attach to the environment, without a
            scheme, port, or path.

            Must be unique across your entire workspace: the same name cannot be
            attached to two environments.


            The name must sit under a registrable domain: 'api.acme.co.uk' is
            accepted, the public suffix

            'co.uk' itself is not. Internationalized names may be sent in
            Unicode or Punycode form; either

            way the domain is stored and returned in its canonical form,
            lowercase ASCII with Unicode labels

            Punycode encoded, and the DNS records in the response use that form.
          example: api.acme.com
      additionalProperties: false
    V2DomainsCreateDomainResponseBody:
      type: object
      required:
        - meta
        - data
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        data:
          $ref: '#/components/schemas/V2DomainsCreateDomainResponseData'
      additionalProperties: false
    BadRequestErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BadRequestErrorDetails'
      description: >-
        Error response for invalid requests that cannot be processed due to
        client-side errors. This typically occurs when request parameters are
        missing, malformed, or fail validation rules. The response includes
        detailed information about the specific errors in the request, including
        the location of each error and suggestions for fixing it. When receiving
        this error, check the 'errors' array in the response for specific
        validation issues that need to be addressed before retrying.
    UnauthorizedErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when authentication has failed or credentials are
        missing. This occurs when:

        - No authentication token is provided in the request

        - The provided token is invalid, expired, or malformed

        - The token format doesn't match expected patterns


        To resolve this error, ensure you're including a valid root key in the
        Authorization header.
    ForbiddenErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when the provided credentials are valid but lack
        sufficient permissions for the requested operation. This occurs when:

        - The root key doesn't have the required permissions for this endpoint

        - The operation requires elevated privileges that the current key lacks

        - Access to the requested resource is restricted based on workspace
        settings


        To resolve this error, ensure your root key has the necessary
        permissions or contact your workspace administrator.
    NotFoundErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when the requested resource cannot be found. This occurs
        when:

        - The specified resource ID doesn't exist in your workspace

        - The resource has been deleted or moved

        - The resource exists but is not accessible with current permissions


        To resolve this error, verify the resource ID is correct and that you
        have access to it.
    ConflictErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when the request conflicts with the current state of the
        resource. This occurs when:

        - Attempting to create a resource that already exists

        - Modifying a resource that has been changed by another operation

        - Violating unique constraints or business rules


        To resolve this error, check the current state of the resource and
        adjust your request accordingly.
    TooManyRequestsErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when the client has sent too many requests in a given
        time period. This occurs when you've exceeded a rate limit or quota for
        the resource you're accessing.


        The rate limit resets automatically after the time window expires. To
        avoid this error:

        - Implement exponential backoff when retrying requests

        - Cache results where appropriate to reduce request frequency

        - Check the error detail message for specific quota information

        - Contact support if you need a higher quota for your use case
    InternalServerErrorResponse:
      type: object
      required:
        - meta
        - error
      properties:
        meta:
          $ref: '#/components/schemas/Meta'
        error:
          $ref: '#/components/schemas/BaseError'
      description: >-
        Error response when an unexpected error occurs on the server. This
        indicates a problem with Unkey's systems rather than your request.


        When you encounter this error:

        - The request ID in the response can help Unkey support investigate the
        issue

        - The error is likely temporary and retrying may succeed

        - If the error persists, contact Unkey support with the request ID
    ResourceIdentifier:
      type: string
      minLength: 3
      maxLength: 255
      pattern: ^[a-zA-Z0-9_-]+$
      description: |
        Identifies a resource by either its unique ID or its slug.
        Accepts a prefixed ID (such as 'proj_' or 'app_') or a slug.
      example: proj_1234abcd
    Meta:
      type: object
      required:
        - requestId
      properties:
        requestId:
          description: >-
            A unique id for this request. Always include this ID when contacting
            support about a specific API request. This identifier allows Unkey's
            support team to trace the exact request through logs and diagnostic
            systems to provide faster assistance.
          example: req_123
          type: string
      additionalProperties: false
      description: >-
        Metadata object included in every API response. This provides context
        about the request and is essential for debugging, audit trails, and
        support inquiries. The `requestId` is particularly important when
        troubleshooting issues with the Unkey support team.
    V2DomainsCreateDomainResponseData:
      type: object
      required:
        - domainId
        - dnsRecords
      properties:
        domainId:
          $ref: '#/components/schemas/ResourceIdentifier'
        dnsRecords:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/DnsRecord'
          description: >
            Every DNS record needed to finish setting up this domain, ready to
            create at your provider.

            The list already accounts for whether the domain is an apex or a
            subdomain, so no further

            branching is needed: create each entry as given.


            One record establishes routing and one proves ownership. Create all
            of them: 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.
        domainConnect:
          $ref: '#/components/schemas/DomainConnect'
      additionalProperties: false
    BadRequestErrorDetails:
      allOf:
        - $ref: '#/components/schemas/BaseError'
        - type: object
          properties:
            errors:
              description: >-
                List of individual validation errors that occurred in the
                request. Each error provides specific details about what failed
                validation, where the error occurred in the request, and
                suggestions for fixing it. This granular information helps
                developers quickly identify and resolve multiple issues in a
                single request without having to make repeated API calls.
              items:
                $ref: '#/components/schemas/ValidationError'
              type: array
          required:
            - errors
      description: >-
        Extended error details specifically for bad request (400) errors. This
        builds on the BaseError structure by adding an array of individual
        validation errors, making it easy to identify and fix multiple issues at
        once.
    BaseError:
      properties:
        detail:
          description: >-
            A human-readable explanation specific to this occurrence of the
            problem. This provides detailed information about what went wrong
            and potential remediation steps. The message is intended to be
            helpful for developers troubleshooting the issue.
          example: Property foo is required but is missing.
          type: string
        status:
          description: >-
            HTTP status code that corresponds to this error. This will match the
            status code in the HTTP response. Common codes include `400` (Bad
            Request), `401` (Unauthorized), `403` (Forbidden), `404` (Not
            Found), `409` (Conflict), and `500` (Internal Server Error).
          example: 404
          format: int
          type: integer
        title:
          description: >-
            A short, human-readable summary of the problem type. This remains
            constant from occurrence to occurrence of the same problem and
            should be used for programmatic handling.
          example: Not Found
          type: string
        type:
          description: >-
            A URI reference that identifies the problem type. This provides a
            stable identifier for the error that can be used for documentation
            lookups and programmatic error handling. When followed, this URI
            should provide human-readable documentation for the problem type.
          example: https://unkey.com/docs/errors/unkey/resource/not_found
          type: string
      required:
        - title
        - detail
        - status
        - type
      type: object
      additionalProperties: false
      description: >-
        Base error structure following Problem Details for HTTP APIs (RFC 7807).
        This provides a standardized way to carry machine-readable details of
        errors in HTTP response content.
    DnsRecord:
      type: object
      required:
        - type
        - name
        - value
        - ttl
        - verified
      properties:
        type:
          type: string
          enum:
            - CNAME
            - ALIAS
            - TXT
          description: >
            Record type to create. `ALIAS` is not a real DNS record type: it
            means an apex-compatible

            alias, which providers expose as ALIAS, ANAME, or a flattened CNAME.
            Apex domains cannot

            hold a plain CNAME, so they receive `ALIAS` where a subdomain
            receives `CNAME`.
          example: CNAME
        name:
          type: string
          minLength: 1
          maxLength: 253
          description: >
            Fully qualified name of the record, ready to use as-is.


            Some providers want a name relative to the zone instead. Drop the
            zone and its trailing dot:

            in zone `acme.com`, `api.acme.com` becomes `api` and
            `_unkey.api.acme.com` becomes

            `_unkey.api`. A name equal to the zone itself is usually entered as
            `@`.
          example: api.acme.com
        value:
          type: string
          minLength: 1
          maxLength: 512
          description: >
            The value to set on the record, exactly as given, including any
            prefix.

            Do not trim or reformat it: verification compares the published
            record against this string.


            Use the lowest TTL your provider allows until the domain is
            verified. Verification polls DNS,

            so a long TTL keeps a stale value cached and can burn the
            verification window on a value you

            have already corrected. Raise it afterwards if you want.
          example: a1b2c3d4e5f6g7h8.cname.unkey.com
        ttl:
          type: integer
          minimum: 1
          description: >
            Seconds a resolver may cache this record. Set it in your provider
            alongside the record's

            name and value.
          example: 60
        verified:
          type: boolean
          description: >
            Whether Unkey has read this record back with the expected value. Use
            it to see which

            records are still outstanding.


            False does not always mean the record is missing. A provider that
            does not expose the

            published value to a DNS lookup, such as a proxied or flattened
            routing record, leaves

            this false for as long as it serves traffic; such a domain verifies
            through its TXT

            record instead. Always false on a domain no check has run against
            yet.
          example: false
        note:
          type: string
          maxLength: 512
          description: >
            What this record is for and any provider-specific caveat that
            applies to it.

            Worth surfacing to whoever edits the DNS zone. Treat it as optional:
            it carries

            no data the record itself needs, so a future record type may omit
            it.
          example: Create as DNS-only if your provider offers the choice.
      additionalProperties: false
    DomainConnect:
      type: object
      description: >
        One-click setup at the domain's DNS provider. Omitted entirely when the
        provider does not support

        Domain Connect or discovery failed, so the object's presence is the
        signal that the shortcut is

        available and both of its fields are filled.
      required:
        - provider
        - url
      properties:
        provider:
          type: string
          maxLength: 256
          description: >
            Display name of the DNS provider the domain is delegated to, such as
            'Cloudflare'. Discovered

            from the domain's nameservers, so it reflects where DNS is actually
            hosted rather than where the

            domain was registered.
          example: Cloudflare
        url:
          type: string
          maxLength: 2048
          description: >
            Signed Domain Connect URL that pre-fills the records in `dnsRecords`
            at the provider. Open it in a

            browser and the domain owner approves them in one step instead of
            entering them by hand. The URL is

            signed with an Unkey key, so it cannot be constructed or altered by
            the caller.


            Intended for a browser, not a script: after approval the provider
            sends the browser to this

            workspace's app settings page in the Unkey dashboard, so it suits a
            caller who administers this

            workspace. Anyone who does not have access to it approves the
            records successfully but lands on a

            page they cannot open. Approving is what writes the records;
            verification then proceeds on its own,

            so nothing depends on completing that return trip.
          example: >-
            https://dash.cloudflare.com/domainconnect/v2/domaintemplates/apply?domain=acme.com&host=api
      additionalProperties: false
    ValidationError:
      additionalProperties: false
      properties:
        location:
          description: >-
            JSON path indicating exactly where in the request the error
            occurred. This helps pinpoint the problematic field or parameter.
            Examples include:

            - 'body.name' (field in request body)

            - 'body.items[3].tags' (nested array element)

            - 'path.apiId' (path parameter)

            - 'query.limit' (query parameter)

            Use this location to identify exactly which part of your request
            needs correction.
          type: string
          example: body.permissions[0].name
        message:
          description: >-
            Detailed error message explaining what validation rule was violated.
            This provides specific information about why the field or parameter
            was rejected, such as format errors, invalid values, or constraint
            violations.
          type: string
          example: Must be at least 3 characters long
        fix:
          description: >-
            A human-readable suggestion describing how to fix the error. This
            provides practical guidance on what changes would satisfy the
            validation requirements. Not all validation errors include fix
            suggestions, but when present, they offer specific remediation
            advice.
          type: string
          example: >-
            Ensure the name uses only alphanumeric characters, underscores, and
            hyphens
      required:
        - location
        - message
      type: object
      description: >-
        Individual validation error details. Each validation error provides
        precise information about what failed, where it failed, and how to fix
        it, enabling efficient error resolution.
  securitySchemes:
    bearer:
      bearerFormat: bearer token
      description: >-
        Unkey uses bearer tokens for authentication. Public integrations use
        root keys, while the dashboard proxy uses short-lived JWTs.

        To authenticate, include the token in the Authorization header of each
        request:

        ```

        Authorization: Bearer unkey_123

        ```

        Root keys have specific permissions attached to them, controlling what
        operations they can perform. Legacy permissions use tuple strings like
        `api.*.create_key`; resource permissions use Unkey Resource Names plus
        actions, like `unkey:v1:ws_123:keyspaces/*#create_key`.

        Security best practices:

        - Keep root keys secure and never expose them in client-side code

        - Use different root keys for different environments

        - Rotate keys periodically, especially after team member departures

        - Create keys with minimal necessary permissions following least
        privilege principle

        - Monitor key usage with audit logs.
      scheme: bearer
      type: http
      x-speakeasy-name-override: rootKey

````