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

# Create a project

> Atomically records the project and a durable operation for asynchronous processing.



## OpenAPI

````yaml /openapi.json post /v1/projects
openapi: 3.1.2
info:
  title: ohmyho.st API
  version: 0.0.0
  description: >-
    Public REST API for ohmyho.st hosting, projects, domains, email, credits and
    exports.
servers:
  - url: https://app.ohmyho.st
    description: Production control API
  - url: https://dev.app.ohmyho.st
    description: Development control API
security:
  - BearerAuth: []
paths:
  /v1/projects:
    post:
      summary: Create a project
      description: >-
        Atomically records the project and a durable operation for asynchronous
        processing.
      operationId: createProject
      parameters:
        - $ref: '#/components/parameters/RequestId'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateProjectRequest'
      responses:
        '202':
          $ref: '#/components/responses/AcceptedOperation'
        '400':
          $ref: '#/components/responses/Problem'
        '401':
          $ref: '#/components/responses/Problem'
        '403':
          $ref: '#/components/responses/Problem'
        '409':
          $ref: '#/components/responses/IdempotencyConflict'
        '413':
          $ref: '#/components/responses/Problem'
        '429':
          $ref: '#/components/responses/Problem'
        '503':
          $ref: '#/components/responses/Problem'
components:
  parameters:
    RequestId:
      name: X-Request-Id
      in: header
      description: Optional caller-provided correlation identifier.
      required: false
      schema:
        type: string
        minLength: 1
        maxLength: 128
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      description: Identifies one mutation and its canonical request payload.
      required: true
      schema:
        type: string
        minLength: 1
        maxLength: 128
  schemas:
    CreateProjectRequest:
      type: object
      description: >-
        Phase 1 project creation request. The server assigns resource
        identifiers.
      additionalProperties: false
      required:
        - organization_id
        - name
      properties:
        organization_id:
          $ref: '#/components/schemas/Ulid'
        data_mode:
          $ref: '#/components/schemas/ProjectDataMode'
        name:
          type: string
          minLength: 1
          maxLength: 128
          pattern: ^\S(?:.*\S)?$
    Ulid:
      type: string
      pattern: ^[0-9A-HJKMNP-TV-Z]{26}$
    ProjectDataMode:
      type: string
      enum:
        - shared
        - isolated
      default: shared
      description: >-
        Chosen when the project is created. shared uses one database and a
        shared file namespace across Dev/Prod; isolated keeps their
        database/Auth records and files separate. Skills recommend isolated
        development, but the customer chooses the additional measured database
        consumption. Promotion applies pending schema migrations to an isolated
        Prod database without copying Dev data. Changing an established mode
        requires an explicit data migration.
    Operation:
      type: object
      description: >-
        Durable record returned for an accepted asynchronous mutation. Optional
        reconciliation is a current observation for queued/running work,
        separate from immutable terminal state. A completed reconciliation
        attempt alone does not mean the operation succeeded.
      additionalProperties: false
      required:
        - id
        - state
        - created_at
        - updated_at
      properties:
        id:
          $ref: '#/components/schemas/Ulid'
        state:
          type: string
          enum:
            - queued
            - running
            - succeeded
            - failed
            - cancelled
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        result:
          type: object
          additionalProperties: true
        error:
          $ref: '#/components/schemas/OperationFailure'
        progress:
          $ref: '#/components/schemas/OperationDeploymentProgress'
        reconciliation:
          $ref: '#/components/schemas/OperationReconciliation'
    ProblemDetails:
      type: object
      description: RFC 9457 Problem Details extended with stable ohmyhost recovery fields.
      additionalProperties: false
      required:
        - type
        - title
        - status
        - code
        - request_id
        - retryable
        - suggested_action
      properties:
        type:
          type: string
          format: uri-reference
        title:
          type: string
          minLength: 1
        status:
          type: integer
          minimum: 400
          maximum: 599
        detail:
          type: string
        instance:
          type: string
          format: uri-reference
        code:
          type: string
          enum:
            - invalid_request
            - unauthenticated
            - forbidden
            - resource_not_found
            - idempotency_key_reused
            - project_handle_unavailable
            - project_identity_unavailable
            - deployment_plan_expired
            - deployment_plan_incompatible
            - confirmation_expired
            - confirmation_invalid
            - etag_mismatch
            - promotion_source_stale
            - promotion_target_stale
            - promotion_invalid_target
            - mail_domain_conflict
            - mail_domain_required
            - framework_conversion_required
            - migration_filename_noncanonical
            - environment_secret_mutation_blocked
            - container_runtime_required
            - payload_too_large
            - rate_limited
            - insufficient_organization_credits
            - paid_plan_required
            - project_budget_exceeded
            - compute_performance_paid_required
            - compute_performance_unavailable
            - compute_change_pending
            - compute_change_conflict
            - billing_purchase_conflict
            - cloudflare_authorization_closed
            - project_notes_conflict
            - project_export_not_ready
            - interactive_login_required
            - api_key_creation_uncertain
            - api_key_permissions_unavailable
            - reconciliation_exhausted
            - service_unavailable
        request_id:
          type: string
          minLength: 1
          maxLength: 128
        retryable:
          type: boolean
        retry_after_seconds:
          type: integer
          minimum: 1
          maximum: 86400
          description: >-
            Optional machine-readable retry delay for a rate limit, matching
            Retry-After.
        suggested_action:
          type: string
          minLength: 1
    IdempotencyConflictProblem:
      allOf:
        - $ref: '#/components/schemas/ProblemDetails'
        - type: object
          properties:
            code:
              const: idempotency_key_reused
    OperationFailure:
      type: object
      additionalProperties: false
      required:
        - code
        - message
        - retryable
        - suggested_action
      properties:
        code:
          type: string
          enum:
            - operation_failed
            - recovery_dispatch_failed
            - recovery_job_failed
            - recovery_input_expired
            - recovery_database_unavailable
            - recovery_checksum_mismatch
            - recovery_scope_unavailable
            - recovery_archive_too_large
            - build_not_started
            - build_failed
            - database_compute_failed
            - database_compute_plan_changed
            - database_compute_rejected
            - database_migration_failed
            - insufficient_organization_credits
            - paid_plan_required
            - runtime_candidate_failed
            - container_runtime_secrets_unsupported
            - provider_state_absent
        message:
          type: string
          minLength: 1
          maxLength: 512
        retryable:
          type: boolean
          const: false
          description: >-
            A terminal operation cannot be retried in place; follow
            suggested_action.
        suggested_action:
          type: string
          minLength: 1
          maxLength: 500
    OperationDeploymentProgress:
      type: object
      additionalProperties: false
      description: >-
        Current deployment dependency observation, separate from immutable
        operation history. Poll the same operation; mail readiness does not mean
        application activation.
      required:
        - phase
        - project_id
        - deployment_id
        - observed_at
        - next_poll_after_seconds
        - suggested_action
      properties:
        build_completed_at:
          type: string
          format: date-time
          description: >-
            Actual successful CodeBuild completion time when this operation ran
            a build; omitted for reused artifacts without a current build.
        phase:
          type: string
          enum:
            - queued
            - building
            - publishing
            - waiting_for_mail
            - mail_status_unavailable
        project_id:
          $ref: '#/components/schemas/Ulid'
        deployment_id:
          $ref: '#/components/schemas/Ulid'
        observed_at:
          type: string
          format: date-time
        next_poll_after_seconds:
          type: integer
          const: 60
        suggested_action:
          type: string
          minLength: 1
          maxLength: 500
    OperationReconciliation:
      type: object
      additionalProperties: false
      required:
        - state
        - attempt_id
        - observed_at
        - suggested_action
      properties:
        state:
          type: string
          enum:
            - required
            - pending
        attempt_id:
          oneOf:
            - $ref: '#/components/schemas/Ulid'
            - type: 'null'
          description: >-
            Active attempt for pending reconciliation; null when a new confirmed
            reconciliation is required.
        observed_at:
          type: string
          format: date-time
        suggested_action:
          type: string
          minLength: 1
          maxLength: 500
  responses:
    AcceptedOperation:
      description: The mutation was accepted for asynchronous processing.
      headers:
        Location:
          description: Relative URL of the durable operation resource.
          required: true
          schema:
            type: string
            pattern: ^/v1/operations/[0-9A-HJKMNP-TV-Z]{26}$
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Operation'
    Problem:
      description: The request failed.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    IdempotencyConflict:
      description: The idempotency key was already used with a different canonical request.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/IdempotencyConflictProblem'
          examples:
            reusedKey:
              value:
                type: https://docs.ohmyho.st/errors/idempotency-key-reused
                title: Idempotency key reused
                status: 409
                code: idempotency_key_reused
                request_id: req_01J00000000000000000000000
                retryable: false
                suggested_action: Retry with a new idempotency key.
  headers:
    XRequestId:
      description: Correlates the request with operations, events, logs, and audit records.
      required: true
      schema:
        type: string
        minLength: 1
        maxLength: 128
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        WorkOS access JWT or a user-owned WorkOS API key. User keys are bound to
        one organization and restricted to their enabled product permissions.
        Session-only onboarding and session revocation require an interactive
        access JWT. No cookie session is assumed.

````