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

# Add custom domain

> <Info>This API is in beta. Endpoints, fields, and behavior may still change, so avoid depending on it in production.</Info>

Attaches a domain you own to the app. Nothing serves on it until you link it with [Link custom domain](/api-reference/link-custom-domain).

Adding a domain and linking it are separate steps. DNS propagation happens outside Base44, so a linked domain can sit unverified for as long as its nameservers take. The domain's DNS has to point at Base44 before verification can pass, and the Base44 editor's domain settings show the records to set.

If a domain was released by another workspace, the call is rejected with a TXT record to publish. Publish it at the domain's DNS provider and send the same request again to prove you control the domain. A domain your own workspace released is re-added straight away.

Don't retry a request that timed out without checking first. If the domain was added, a second request is rejected as already attached, so look for it in [List custom domains](/api-reference/list-custom-domains) before you send the request again.

Adding domains is limited to 30 requests an hour per caller. Some workspaces have a different limit.

<Warning>The response includes fields beyond the ones documented here. Don't rely on undocumented response fields, as they can change at any time.</Warning>



## OpenAPI

````yaml /developers/references/app-management/app-management-openapi.json post /api/apps/{app_id}/custom-domains
openapi: 3.1.0
info:
  title: Base44 App Management API
  version: 1.0.0
servers:
  - url: https://app.base44.com
security:
  - PersonalAccessTokenAuth: []
paths:
  /api/apps/{app_id}/custom-domains:
    post:
      summary: Add custom domain
      description: >-
        <Info>This API is in beta. Endpoints, fields, and behavior may still
        change, so avoid depending on it in production.</Info>


        Attaches a domain you own to the app. Nothing serves on it until you
        link it with [Link custom domain](/api-reference/link-custom-domain).


        Adding a domain and linking it are separate steps. DNS propagation
        happens outside Base44, so a linked domain can sit unverified for as
        long as its nameservers take. The domain's DNS has to point at Base44
        before verification can pass, and the Base44 editor's domain settings
        show the records to set.


        If a domain was released by another workspace, the call is rejected with
        a TXT record to publish. Publish it at the domain's DNS provider and
        send the same request again to prove you control the domain. A domain
        your own workspace released is re-added straight away.


        Don't retry a request that timed out without checking first. If the
        domain was added, a second request is rejected as already attached, so
        look for it in [List custom domains](/api-reference/list-custom-domains)
        before you send the request again.


        Adding domains is limited to 30 requests an hour per caller. Some
        workspaces have a different limit.


        <Warning>The response includes fields beyond the ones documented here.
        Don't rely on undocumented response fields, as they can change at any
        time.</Warning>
      operationId: create_domain_api_apps__app_id__custom_domains_post
      parameters:
        - description: ID of the app the domain belongs to.
          example: 6820f3a4e7b91d003c45a1f2
          in: path
          name: app_id
          required: true
          schema:
            description: ID of the app the domain belongs to.
            title: App Id
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateDomainBody'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomDomainResource'
          description: The domain, attached to the app but not yet linked.
        '400':
          description: >-
            The domain is already attached to an app, contains a social media
            platform's name, or you have reached the limit of 350 custom
            domains.
        '401':
          description: Missing or invalid credentials.
        '402':
          description: This workspace's plan doesn't include custom domains.
        '403':
          description: >-
            You don't have access to this app, or you used a workspace API key.
            These endpoints take a personal API key.
        '404':
          description: App not found.
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainClaimChallenge'
          description: >-
            Another workspace released this domain. Publish the TXT record in
            `detail.verification` and retry.
        '422':
          description: '`domain` is missing or empty.'
        '429':
          description: >-
            Rate limit reached, either yours or Base44's hosting provider's.
            Retry later.
components:
  schemas:
    CreateDomainBody:
      properties:
        domain:
          description: >-
            The domain to add. A scheme, a trailing slash, and a leading `www.`
            are removed, and it's stored in lower case.
          example: example.com
          title: Domain
          type: string
      required:
        - domain
      title: CreateDomainBody
      type: object
    CustomDomainResource:
      description: A custom domain attached to an app.
      properties:
        app_id:
          description: ID of the app the domain serves.
          example: 6820f3a4e7b91d003c45a1f2
          title: App Id
          type: string
        disabled:
          description: >-
            Whether Base44 has stopped serving the domain. A disabled domain
            stays attached to the app and keeps its DNS, and serves a
            placeholder page instead of the app.
          example: false
          title: Disabled
          type: boolean
        domain:
          description: >-
            The domain name, normalized to lower case with any scheme, trailing
            slash and leading `www.` removed.
          example: example.com
          title: Domain
          type: string
        id:
          description: >-
            ID of the domain. Pass it as `domain_id` to the other domain
            endpoints.
          example: 68b1c0d4e7b91d003c45a1f7
          title: Id
          type: string
        last_status_check:
          anyOf:
            - format: date-time
              type: string
            - type: 'null'
          description: >-
            When [Get custom domain
            status](/api-reference/get-custom-domain-status) last ran for this
            domain, as a UTC timestamp in ISO 8601 format, or `null` if it never
            has.
          example: '2026-08-15T09:10:00'
          title: Last Status Check
        last_status_payload:
          anyOf:
            - $ref: '#/components/schemas/CustomDomainStatusPayload'
            - type: 'null'
          description: >-
            The provider's last report on the domain, or `null` until a status
            check has run.
        provider_id:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            Names the registrar when the domain was bought through Base44's Wix
            flow. The value is `null` otherwise, which covers both a domain you
            own elsewhere and one bought through the Entri flow, so this isn't a
            purchased-versus-external signal.
          example: wix
          title: Provider Id
        redirect_target_domain:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            The domain that visitors to this one are sent to with a 301
            redirect. The value is `null` when this domain serves the app
            itself.
          example: www.example.com
          title: Redirect Target Domain
      required:
        - id
        - domain
        - app_id
        - disabled
      title: CustomDomainResource
      type: object
    DomainClaimChallenge:
      description: >-
        Another workspace released this domain, so you have to prove you control
        it.
      properties:
        detail:
          $ref: '#/components/schemas/DomainClaimChallengeDetail'
          description: What to publish before adding the domain again.
      required:
        - detail
      title: DomainClaimChallenge
      type: object
    CustomDomainStatusPayload:
      description: What the hosting provider last reported about the domain.
      properties:
        verificationStatus:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            Whether the provider has verified the domain's DNS. Only `verified`
            means the domain serves the app, and anything else means it doesn't
            yet. Absent until [Get custom domain
            status](/api-reference/get-custom-domain-status) has run once.
          example: verified
          title: Verificationstatus
      title: CustomDomainStatusPayload
      type: object
    DomainClaimChallengeDetail:
      properties:
        message:
          description: Why the domain can't be added yet.
          example: >-
            This domain is registered to another workspace. Add the TXT record
            below to prove you control it, then try again.
          title: Message
          type: string
        verification:
          $ref: '#/components/schemas/DomainClaimVerification'
          description: The record to publish at the domain's DNS provider before you retry.
      required:
        - message
        - verification
      title: DomainClaimChallengeDetail
      type: object
    DomainClaimVerification:
      description: The DNS record that proves you control the domain.
      properties:
        name:
          description: Host name to publish the record on.
          example: _b44-verify.example.com
          title: Name
          type: string
        type:
          description: Record type. Always `TXT`.
          example: TXT
          title: Type
          type: string
        value:
          description: >-
            Value to publish. It's issued to your workspace, so another
            workspace can't use it to claim the domain.
          example: base44-domain-claim=3kQ9vL2mP7xR8tN4wZ1yB6cF5hJ0dS2aE9gU7iO3rT
          title: Value
          type: string
      required:
        - type
        - name
        - value
      title: DomainClaimVerification
      type: object
  securitySchemes:
    PersonalAccessTokenAuth:
      description: 'Personal access token, sent as `Authorization: Bearer <token>`.'
      scheme: bearer
      type: http

````