openapi: 3.1.0
info:
  title: Dashio API
  version: 2026.8.0
  description: API documentation for Dashio services
servers:
  - url: https://www.dashio.local:3000
    description: Local Development Server
    variables: {}
paths:
  "":
    get:
      tags:
        - App Routes
      parameters: []
      responses:
        "200":
          description: OK
  /api/_openapi-globals:
    get:
      tags:
        - API Routes
      parameters: []
      responses:
        "200":
          description: OK
  /api/health:
    get:
      tags:
        - Support
      parameters: []
      responses:
        "200":
          description: Runtime health diagnostics.
          content:
            application/json:
              schema:
                type: object
                properties:
                  version:
                    type: string
                  health:
                    type: object
                  time:
                    type: object
                  memory:
                    type: object
                  cpu:
                    type: object
                  system:
                    type: object
                  response_time:
                    type: string
      operationId: getHealth
      summary: Health check for the API
      description: Returns runtime-safe API health diagnostics for Node, Bun and
        Cloudflare Workers.
  /api/telemetry/config:
    get:
      tags:
        - Telemetry
      parameters: []
      responses:
        "200":
          description: Current public telemetry configuration.
      operationId: getBrowserTelemetryConfig
      summary: Read public browser telemetry settings
      description: Returns runtime settings for browser instrumentation, including
        prerendered pages. Contains no credentials.
  /api/telemetry/v1/{signal}:
    post:
      tags:
        - Telemetry
      parameters:
        - name: signal
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Telemetry accepted by the upstream collector.
        "400":
          description: Malformed or unexpected OTLP envelope.
        "403":
          description: Cross-origin request rejected.
        "413":
          description: Payload exceeds the relay limit.
        "415":
          description: Only OTLP/HTTP JSON is accepted.
        "502":
          description: The upstream collector rejected telemetry.
      operationId: relayBrowserOtlp
      summary: Relay bounded same-origin browser OTLP
      description: Forwards validated OTLP/HTTP JSON logs, traces or metrics with a
        server-held collector credential.
  /api/v1/auth/mfa/verify:
    post:
      tags:
        - Auth
      parameters: []
      responses:
        "200":
          description: MFA verification successful.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                required:
                  - success
        "401":
          description: Authentication failed (not authenticated or invalid MFA code).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 401
                  statusMessage:
                    type: string
                    example: Verification failed
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                        example: Invalid or expired code. Please try again.
                    required:
                      - message
                required:
                  - statusCode
                  - statusMessage
        "422":
          description: Validation failed (missing/invalid factor ID or code).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 422
                  statusMessage:
                    type: string
                    example: Authentication code is required.
                required:
                  - statusCode
                  - statusMessage
        "429":
          description: Too many requests (rate limit exceeded).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 429
                  statusMessage:
                    type: string
                    example: Too Many Requests
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                        example: Too many verification attempts. Please try again in X seconds.
                    required:
                      - message
                required:
                  - statusCode
                  - statusMessage
        "500":
          description: Internal server error during processing.
      operationId: postAuthMfaVerify
      summary: Verify MFA code
      description: Verifies a TOTP MFA code for the authenticated user. Requires user
        to be authenticated with password first (AAL1). Returns success state
        upon successful verification.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - factorId
                - code
              properties:
                factorId:
                  type: string
                  format: uuid
                  description: MFA factor ID
                code:
                  type: string
                  description: 6-digit TOTP code
              additionalProperties: false
            examples:
              example:
                summary: Valid MFA verification request
                value:
                  factorId: 123e4567-e89b-12d3-a456-426614174000
                  code: "123456"
  /api/v1/auth/passkeys/{passkeyId}:
    delete:
      tags:
        - Auth
      parameters:
        - name: passkeyId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Passkey deleted.
        "401":
          description: Authentication required.
        "403":
          description: MFA re-authentication required.
        "422":
          description: Invalid passkey ID.
      operationId: deleteAuthPasskey
      summary: Delete passkey
      security:
        - bearerAuth: []
    patch:
      tags:
        - Auth
      parameters:
        - name: passkeyId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Passkey renamed.
        "401":
          description: Authentication required.
        "403":
          description: MFA re-authentication required.
        "422":
          description: Invalid passkey ID or friendly name.
      operationId: patchAuthPasskey
      summary: Rename passkey
      security:
        - bearerAuth: []
  /api/v1/auth/passkeys:
    get:
      tags:
        - Auth
      parameters: []
      responses:
        "200":
          description: Current user passkeys.
        "401":
          description: Authentication required.
      operationId: getAuthPasskeys
      summary: List passkeys
      security:
        - bearerAuth: []
  /api/v1/auth/password-reset/request:
    post:
      tags:
        - Auth
      parameters: []
      responses:
        "200":
          description: Password reset email sent (or would be sent if account exists).
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: If an account exists with this email, you will receive a password reset
                      link shortly.
                required:
                  - success
                  - message
        "422":
          description: Validation failed (missing/invalid email or Turnstile token).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 422
                  statusMessage:
                    type: string
                    example: Invalid email address.
                required:
                  - statusCode
                  - statusMessage
        "429":
          description: Too many password reset attempts (rate limit exceeded).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 429
                  statusMessage:
                    type: string
                    example: Too Many Requests
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                        example: Too many password reset attempts. Please try again in 15 minutes.
                    required:
                      - message
                required:
                  - statusCode
                  - statusMessage
        "500":
          description: Internal server error during processing.
      operationId: postAuthPasswordResetRequest
      summary: Request password reset
      description: Initiates a password reset flow by sending an email with a reset
        link. Requires a valid Cloudflare Turnstile token for bot protection.
        Rate limited to 3 requests per 15 minutes per email.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - captchaToken
              properties:
                email:
                  type: string
                  format: email
                  description: User email address
                captchaToken:
                  type: string
                  description: Cloudflare Turnstile token
              additionalProperties: false
            examples:
              example:
                summary: Valid password reset request
                value:
                  email: user@example.com
                  captchaToken: turnstile-token
  /api/v1/auth/password-reset/update:
    post:
      tags:
        - Auth
      parameters: []
      responses:
        "200":
          description: Password updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Your password has been updated successfully.
                required:
                  - success
                  - message
        "400":
          description: Password update failed (e.g., password same as current).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 400
                  statusMessage:
                    type: string
                    example: Password update failed
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                        example: New password must be different from your current password.
                    required:
                      - message
                required:
                  - statusCode
                  - statusMessage
        "401":
          description: User not authenticated (must access via password reset link).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 401
                  statusMessage:
                    type: string
                    example: Authentication required
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                        example: You must be authenticated via the password reset link to update your
                          password.
                    required:
                      - message
                required:
                  - statusCode
                  - statusMessage
        "422":
          description: Validation failed (password missing or does not meet policy).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 422
                  statusMessage:
                    type: string
                    example: Invalid password
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                        example: Password must be at least 12 characters...
                required:
                  - statusCode
                  - statusMessage
        "500":
          description: Internal server error during processing.
      operationId: postAuthPasswordResetUpdate
      summary: Update password
      description: Updates the authenticated user's password. User must be
        authenticated via the password reset email link (recovery flow).
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - password
              properties:
                password:
                  type: string
                  description: New password (min 12 chars, must include uppercase, lowercase,
                    numeric, and special characters)
              additionalProperties: false
            examples:
              example:
                summary: Valid password update request
                value:
                  password: SecureP@ssw0rd123!
  /api/v1/auth/sign-in:
    post:
      tags:
        - Auth
      parameters: []
      responses:
        "200":
          description: Sign-in successful.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  requiresMfa:
                    type: boolean
                    example: false
                    description: Whether MFA verification is required
                required:
                  - success
                  - requiresMfa
        "401":
          description: Authentication failed (invalid credentials).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 401
                  statusMessage:
                    type: string
                    example: Login failed
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                        example: Invalid login credentials
                    required:
                      - message
                required:
                  - statusCode
                  - statusMessage
                  - data
        "422":
          description: Validation failed (missing/invalid email, password, or Turnstile
            token).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 422
                  statusMessage:
                    type: string
                    example: Turnstile token missing.
                required:
                  - statusCode
                  - statusMessage
        "429":
          description: Too many sign-in attempts (rate limit exceeded).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 429
                  statusMessage:
                    type: string
                    example: Too Many Requests
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                        example: Too many sign-in attempts. Please try again in 60 seconds.
                    required:
                      - message
                required:
                  - statusCode
                  - statusMessage
        "500":
          description: Internal server error during processing.
      operationId: postAuthSignIn
      summary: Sign in with email and password
      description: Authenticates a user with email and password credentials. Requires
        a valid Cloudflare Turnstile token for bot protection. Returns success
        state and whether MFA verification is required.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - password
                - captchaToken
              properties:
                email:
                  type: string
                  format: email
                  description: User email address
                password:
                  type: string
                  description: User password
                captchaToken:
                  type: string
                  description: Cloudflare Turnstile token
              additionalProperties: false
            examples:
              example:
                summary: Valid sign-in request
                value:
                  email: user@example.com
                  password: securePassword123
                  captchaToken: turnstile-token
  /api/v1/auth/sign-in/passkey:
    post:
      tags:
        - Auth
      parameters: []
      responses:
        "200":
          description: Passkey sign-in finalized.
        "401":
          description: Authentication required.
        "500":
          description: Internal server error during processing.
      operationId: postAuthSignInPasskeyFinalize
      summary: Finalize passkey sign-in
      description: Completes a browser-side passkey sign-in and writes the sign-in
        audit log.
      security:
        - bearerAuth: []
  /api/v1/billing/checkout/certificates:
    post:
      tags:
        - Checkouts
      parameters: []
      responses:
        "200":
          description: Stripe Checkout session created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  sessionId:
                    type: string
                  checkoutUrl:
                    type: string
                    format: uri
                  productFamily:
                    type: string
                    enum:
                      - certificates
                required:
                  - productFamily
        "400":
          description: Invalid certificate identifier, period, or contact information.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden. User is not owner or admin of the space.
        "404":
          description: Certificate not found.
        "500":
          description: Failed to create Stripe checkout session.
      operationId: createCertificateCheckoutSession
      summary: Create Stripe Checkout session for SSL certificate purchase
      description: Validates SSL certificate availability, calculates pricing, and
        creates a one-time Stripe Checkout session for the selected product.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - productId
                - period
                - contact
                - successUrl
                - cancelUrl
              properties:
                productId:
                  type: integer
                  minimum: 1
                period:
                  type: integer
                  minimum: 1
                  description: Certificate validity period in years.
                contact:
                  type: object
                  required:
                    - accountType
                    - email
                    - firstName
                    - lastName
                    - phone
                    - street
                    - zip
                    - city
                    - country
                  properties:
                    accountType:
                      type: string
                      enum:
                        - private
                        - business
                    company:
                      type: string
                    email:
                      type: string
                      format: email
                    firstName:
                      type: string
                    lastName:
                      type: string
                    phone:
                      type: object
                      required:
                        - countryCode
                        - areaCode
                        - subscriberNumber
                        - e164
                      properties:
                        countryCode:
                          type: string
                          description: Country calling code including leading + (e.g., +49).
                        areaCode:
                          type: string
                          description: Area or city code without leading zero.
                        subscriberNumber:
                          type: string
                          description: Subscriber number part of the phone.
                        e164:
                          type: string
                          description: Fully concatenated E.164 formatted phone number.
                    street:
                      type: string
                    zip:
                      type: string
                    city:
                      type: string
                    country:
                      type: string
                successUrl:
                  type: string
                  format: uri
                cancelUrl:
                  type: string
                  format: uri
      security:
        - bearerAuth: []
  /api/v1/billing/checkout/domains/{transaction}:
    get:
      tags:
        - Billing / Checkout
      parameters:
        - name: transaction
          in: path
          required: true
          schema:
            type: string
          description: Transaction ID (UUID) or Stripe checkout session ID (cs_test_* or
            cs_live_*).
          example: cs_test_a1B2c3D4e5F6g7H8i9J0
      responses:
        "200":
          description: Transaction status retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                required:
                  - status
                  - orderNumber
                  - error
                properties:
                  status:
                    type: string
                    enum:
                      - pending
                      - succeeded
                      - failed
                    description: Current transaction status.
                  orderNumber:
                    type: string
                    description: Short order reference number.
                  error:
                    type:
                      - string
                      - "null"
                    description: User-facing error message when checkout failed.
        "400":
          description: Invalid or missing transaction ID.
        "401":
          description: Unauthorized - authentication required.
        "404":
          description: Transaction not found.
        "500":
          description: Internal server error.
      operationId: getDomainCheckoutTransactionStatus
      summary: Get domain checkout transaction status
      description: Retrieves the current status of a domain checkout transaction. Used
        to poll for order completion after payment. Requires authentication.
      security:
        - bearerAuth: []
  /api/v1/billing/checkout/domains:
    post:
      tags:
        - Checkouts
      parameters: []
      responses:
        "200":
          description: Stripe Checkout session created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  sessionId:
                    type: string
                  checkoutUrl:
                    type: string
                    format: uri
                  productFamily:
                    type: string
                    enum:
                      - domains
                required:
                  - productFamily
        "400":
          description: Invalid domain, contact details, or redirect URLs.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden. User is not owner or admin of the space.
        "409":
          description: Domain is no longer available.
        "500":
          description: Failed to create Stripe checkout session.
      operationId: createDomainCheckoutSession
      summary: Create Stripe Checkout session for domain purchase
      description: Validates domain availability, calculates pricing, and creates a
        Stripe Checkout session for the requested domain and add-ons.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - domain
                - billingInterval
                - addons
                - contact
                - successUrl
                - cancelUrl
              properties:
                domain:
                  type: string
                  description: Fully qualified domain to purchase.
                billingInterval:
                  type: string
                  enum:
                    - monthly
                    - yearly
                addons:
                  type: object
                  additionalProperties:
                    type: boolean
                contact:
                  type: object
                  required:
                    - accountType
                    - email
                    - firstName
                    - lastName
                    - phone
                    - street
                    - zip
                    - city
                    - country
                  properties:
                    accountType:
                      type: string
                      enum:
                        - private
                        - business
                    company:
                      type: string
                    email:
                      type: string
                      format: email
                    firstName:
                      type: string
                    lastName:
                      type: string
                    phone:
                      type: object
                      required:
                        - countryCode
                        - areaCode
                        - subscriberNumber
                        - e164
                      properties:
                        countryCode:
                          type: string
                          description: Country calling code including leading + (e.g., +49).
                        areaCode:
                          type: string
                          description: Area or city code without leading zero.
                        subscriberNumber:
                          type: string
                          description: Subscriber number part of the phone.
                        e164:
                          type: string
                          description: Fully concatenated E.164 formatted phone number.
                    street:
                      type: string
                    zip:
                      type: string
                    city:
                      type: string
                    country:
                      type: string
                successUrl:
                  type: string
                  format: uri
                cancelUrl:
                  type: string
                  format: uri
      security:
        - bearerAuth: []
  /api/v1/billing/checkout/domains/transfers:
    post:
      tags:
        - Solutions / Domains
      parameters: []
      responses:
        "200":
          description: Stripe Checkout session created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  sessionId:
                    type: string
                  checkoutUrl:
                    type: string
                    format: uri
                  productFamily:
                    type: string
                    enum:
                      - domain-transfer
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthorized.
        "403":
          description: Forbidden. User is not owner or admin of the space.
        "422":
          description: Contact information required or pricing unavailable.
        "500":
          description: Failed to create checkout session.
      operationId: createDomainTransferCheckout
      summary: Create Stripe Checkout session for domain transfer
      description: Creates a one-time payment Stripe Checkout session for transferring
        domains. The transfer will be initiated after successful payment.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - transfers
                - spaceId
                - successUrl
                - cancelUrl
              properties:
                transfers:
                  type: array
                  items:
                    type: object
                    required:
                      - domain
                      - authCode
                    properties:
                      domain:
                        type: string
                        description: Fully qualified domain name to transfer.
                      authCode:
                        type: string
                        description: Authorization code from current registrar.
                  minItems: 1
                  maxItems: 10
                spaceId:
                  type: string
                  format: uuid
                  description: Space ID to associate the domain with.
                contact:
                  type: object
                  description: Contact details for domain registration. Required if no contact
                    exists for the space.
                successUrl:
                  type: string
                  format: uri
                  description: URL to redirect to after successful payment.
                cancelUrl:
                  type: string
                  format: uri
                  description: URL to redirect to if payment is cancelled.
      security:
        - bearerAuth: []
  /api/v1/billing/checkout/domains/transfers/pricing:
    post:
      tags:
        - Solutions / Domains
      parameters: []
      responses:
        "200":
          description: Transfer pricing information.
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        domain:
                          type: string
                        price:
                          type: number
                        currency:
                          type: string
                      required:
                        - domain
                        - price
                        - currency
                  totalPrice:
                    type: number
                  currency:
                    type: string
                required:
                  - items
                  - totalPrice
                  - currency
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthorized.
      operationId: getTransferPricing
      summary: Get domain transfer pricing
      description: Retrieves domain transfer pricing using the highest create,
        renewal, or transfer price.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - domains
              properties:
                domains:
                  type: array
                  items:
                    type: string
                  minItems: 1
                  maxItems: 10
                  description: List of domain names to get pricing for.
  /api/v1/billing/checkout/domains/transfers/status:
    get:
      tags:
        - Solutions / Domains
      parameters:
        - name: sessionId
          in: query
          required: true
          schema:
            type: string
          description: Stripe checkout session ID.
      responses:
        "200":
          description: Transfer status information.
          content:
            application/json:
              schema:
                type: object
                properties:
                  sessionId:
                    type: string
                  status:
                    type: string
                    enum:
                      - pending
                      - processing
                      - completed
                      - failed
                      - partial
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        domain:
                          type: string
                        success:
                          type: boolean
                        error:
                          type: string
                  refunded:
                    type: boolean
                  refundReason:
                    type: string
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthorized.
        "404":
          description: Session not found.
      operationId: getTransferStatus
      summary: Get domain transfer checkout status
      description: Retrieves the status of a domain transfer checkout session.
  /api/v1/billing/checkout/saas:
    post:
      tags:
        - Checkouts
      parameters: []
      responses:
        "200":
          description: Stripe Checkout session created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  sessionId:
                    type: string
                  checkoutUrl:
                    type: string
                    format: uri
                  productFamily:
                    type: string
                    enum:
                      - saas
                required:
                  - productFamily
        "400":
          description: Invalid plan selection, seat count, or contact information.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden. User is not owner or admin of the space.
        "500":
          description: Failed to create Stripe checkout session.
      operationId: createSaasCheckoutSession
      summary: Create Stripe Checkout session for SaaS plan subscription
      description: Creates a recurring Stripe subscription checkout session for the
        selected SaaS plan and seat count.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - planId
                - seats
                - contact
                - successUrl
                - cancelUrl
              properties:
                planId:
                  type: string
                  enum:
                    - startup
                    - business
                    - enterprise
                seats:
                  type: integer
                  minimum: 1
                contact:
                  type: object
                  required:
                    - accountType
                    - email
                    - firstName
                    - lastName
                    - phone
                    - street
                    - zip
                    - city
                    - country
                  properties:
                    accountType:
                      type: string
                      enum:
                        - private
                        - business
                    company:
                      type: string
                    email:
                      type: string
                      format: email
                    firstName:
                      type: string
                    lastName:
                      type: string
                    phone:
                      type: object
                      required:
                        - countryCode
                        - areaCode
                        - subscriberNumber
                        - e164
                      properties:
                        countryCode:
                          type: string
                          description: Country calling code including leading + (e.g., +49).
                        areaCode:
                          type: string
                          description: Area or city code without leading zero.
                        subscriberNumber:
                          type: string
                          description: Subscriber number part of the phone.
                        e164:
                          type: string
                          description: Fully concatenated E.164 formatted phone number.
                    street:
                      type: string
                    zip:
                      type: string
                    city:
                      type: string
                    country:
                      type: string
                successUrl:
                  type: string
                  format: uri
                cancelUrl:
                  type: string
                  format: uri
      security:
        - bearerAuth: []
  /api/v1/billing/contacts:
    delete:
      tags:
        - Billing Contacts
      parameters:
        - name: spaceId
          in: query
          required: true
          schema:
            type: string
            format: uuid
          description: The ID of the Space containing the billing contact.
        - name: contactId
          in: query
          required: true
          schema:
            type: string
            format: uuid
          description: The ID of the billing contact to delete.
      responses:
        "200":
          description: "Billing contact removed. Returns { success: true }."
        "400":
          description: Invalid request parameters. spaceId/contactId missing or not valid
            UUIDs.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden. User is not owner or admin of the space.
        "404":
          description: Contact not found.
        "500":
          description: Membership lookup failed OR failed to remove contact.
      operationId: deleteBillingContact
      summary: Remove a billing contact from a Space
      description: "Deletes a billing contact from a Space. Only Space owners or
        admins may perform this action. Query params: spaceId and contactId
        (UUID). Returns { success: true } on success."
      security:
        - bearerAuth: []
    get:
      tags:
        - Billing Contacts
      parameters:
        - name: spaceId
          in: query
          required: true
          schema:
            type: string
            format: uuid
          description: UUID of the Space.
      responses:
        "200":
          description: "Billing contacts retrieved. Returns an object with `contacts`, an
            array of `{ id: uuid, email: string }`."
        "400":
          description: Invalid request parameters. spaceId missing or not a valid UUID.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden. User is not owner or admin of the space.
        "500":
          description: Membership lookup failed OR failed to fetch contacts.
      operationId: getBillingContacts
      summary: List billing contacts for a Space
      description: "Retrieves billing contacts for the given spaceId. Only Space
        owners or admins may access this endpoint. Query: spaceId (UUID)."
      security:
        - bearerAuth: []
    post:
      tags:
        - Billing Contacts
      parameters: []
      responses:
        "200":
          description: "Billing contact added. Returns an object with `contact: { id:
            uuid, email: string }`."
        "400":
          description: Invalid request parameters. spaceId/email missing or invalid
            (spaceId must be UUID, email must be valid).
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden. User is not owner or admin of the space.
        "409":
          description: Conflict. Contact limit reached (max 5) OR contact already exists
            (duplicate email).
        "500":
          description: Membership lookup failed OR billing contacts lookup failed OR
            failed to add contact.
      operationId: addBillingContact
      summary: Add a billing contact to a Space
      description: Adds a new billing contact email to a Space. Only Space owners or
        admins may add contacts. Email is normalized to lowercase and must be
        valid. A maximum of 5 contacts is allowed per space, and duplicate
        emails are rejected.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
  /api/v1/billing/customers/portal/redirect:
    get:
      tags:
        - Stripe Actions
      parameters:
        - name: spaceId
          in: query
          required: true
          schema:
            type: string
            format: uuid
          description: Space ID the billing customer belongs to.
      responses:
        "302":
          description: Redirect to the Stripe portal or the trusted billing page after an
            authorization denial.
        "400":
          description: Invalid Space ID.
        "401":
          description: Unauthenticated.
        "404":
          description: Billing customer not found.
        "500":
          description: Billing lookup failed.
        "503":
          description: Portal policy could not be verified.
      operationId: redirectToBillingPortal
      summary: Redirect to Stripe Billing Portal
      description: Checks current Space owner/admin permissions and creates a no-store
        session using the code-owned shared billing policy. Submitted return
        URLs and configuration IDs are ignored.
      security:
        - bearerAuth: []
  /api/v1/billing/profiles:
    get:
      tags:
        - Billing Profiles
      parameters:
        - name: spaceId
          in: query
          required: true
          schema:
            type: string
            format: uuid
          description: Space UUID to load the billing profile for.
      responses:
        "200":
          description: "Billing profile retrieved. Returns BillingProfileResponse: address
            (BillingAddress), taxId (string|null), phone
            (PhoneNumberParts|null)."
        "400":
          description: Missing spaceId.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden.
        "404":
          description: Billing profile not found.
        "500":
          description: Failed to verify permissions or unexpected internal error.
      operationId: getBillingProfile
      summary: Retrieve billing profile for a space
      description: Retrieves the billing profile for the given spaceId. The response
        is primarily sourced from Supabase and may be enriched with Stripe
        address and tax ID when available. Requires an authenticated user with
        role owner or admin in the space.
      security:
        - bearerAuth: []
    post:
      tags:
        - Billing Profiles
      parameters: []
      responses:
        "200":
          description: "Billing profile created. Returns BillingProfileResponse: address
            (BillingAddress), taxId (string|null), phone
            (PhoneNumberParts|null)."
        "400":
          description: Bad Request. Payload validation failed OR spaceId missing in
            payload OR other validation errors thrown by
            validatePayload/createCustomer.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden. User is not owner or admin of the space.
        "404":
          description: Space not found.
        "409":
          description: Billing profile already exists.
        "500":
          description: Failed to verify permissions, failed to create customer, or
            unexpected internal error.
      operationId: createBillingProfile
      summary: Create billing profile for a space
      description: Creates a billing profile for the given space. Requires an
        authenticated user with role owner or admin in the space. Validates the
        request payload and creates a Stripe customer plus a billing.customers
        row.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
    put:
      tags:
        - Billing Profiles
      parameters: []
      responses:
        "200":
          description: "Billing profile updated. Returns BillingProfileResponse: address
            (BillingAddress), taxId (string|null), phone
            (PhoneNumberParts|null)."
        "400":
          description: Bad Request. Invalid payload OR missing spaceId for billing profile
            update.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden. User does not have access to the space.
        "404":
          description: Not Found. Billing profile not found OR space not found for billing
            profile update.
        "500":
          description: Failed to update billing profile or unexpected internal error.
        "502":
          description: Failed to update Stripe customer.
      operationId: updateBillingProfile
      summary: Update billing profile for a space
      description: Updates the billing profile for the given space. Requires an
        authenticated user with space access. Validates the request payload,
        updates the Stripe customer, then updates the billing.customers row.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
  /api/v1/billing/saas/{productKey}/checkout:
    post:
      tags:
        - SaaS Billing
      parameters:
        - in: path
          name: productKey
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Stripe-hosted checkout URL.
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                    format: uri
        "400":
          description: Invalid request.
        "401":
          description: Authentication required.
        "403":
          description: Space owner/admin required.
        "404":
          description: Unknown or disabled product.
        "409":
          description: Existing subscription or conflicting reservation.
        "415":
          description: JSON request required.
        "503":
          description: Checkout or tax configuration unavailable.
      operationId: createSaasCheckout
      summary: Subscribe to a registered SaaS product
      description: Owner/admin only. Prices come from the verified server catalog.
        Durable reservations preserve the original price and idempotency key.
        Only verified webhooks activate access.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - planId
              properties:
                spaceId:
                  type: string
                  format: uuid
                planId:
                  type: string
  /api/v1/billing/saas/{productKey}/plan-change:
    get:
      tags:
        - SaaS Billing
      parameters:
        - in: path
          name: productKey
          required: true
          schema:
            type: string
            enum:
              - marketing-signatures
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Current plan change state.
          content:
            application/json:
              schema:
                type: object
                properties:
                  currentPlanId:
                    type: string
                    nullable: true
                  canChangePlan:
                    type: boolean
                  blockedReason:
                    type: string
                    nullable: true
                  paymentUrl:
                    type: string
                    nullable: true
                  scheduledChange:
                    type: object
                    nullable: true
                    properties:
                      planId:
                        type: string
                      planName:
                        type: string
                      effectiveAt:
                        type: string
                        format: date-time
                      revision:
                        type: string
        "400":
          description: Invalid Space.
        "401":
          description: Authentication required.
        "403":
          description: Owner/admin required.
        "404":
          description: Product does not support plan changes.
        "409":
          description: Subscription ownership or product requires review.
        "503":
          description: Billing unavailable.
      operationId: getSignaturePlanChange
      summary: Get Signature plan change availability
      description: Owner/admin only. Returns the current Signature plan, a scheduled
        downgrade and an invoice payment link when an upgrade needs payment.
      security:
        - bearerAuth: []
    post:
      tags:
        - SaaS Billing
      parameters:
        - in: path
          name: productKey
          required: true
          schema:
            type: string
            enum:
              - marketing-signatures
      responses:
        "200":
          description: Plan change result.
          content:
            application/json:
              schema:
                type: object
                properties:
                  outcome:
                    type: string
                    enum:
                      - applied
                      - payment_required
                      - scheduled
                  paymentUrl:
                    type: string
                    nullable: true
        "400":
          description: Invalid request.
        "401":
          description: Authentication required.
        "403":
          description: Owner/admin required.
        "404":
          description: Product disabled.
        "409":
          description: Review expired, state changed or plan unavailable.
        "415":
          description: JSON required.
        "503":
          description: Billing unavailable.
      operationId: confirmSignaturePlanChange
      summary: Confirm a Signature plan change
      description: Revalidates permissions, signed review and current Stripe state.
        Upgrades apply only after successful prorated payment. Downgrades start
        at renewal. Changes only the persisted Signature subscription.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - token
              properties:
                spaceId:
                  type: string
                  format: uuid
                token:
                  type: string
                  description: Signed token from the preview endpoint, up to 4096 characters.
  /api/v1/billing/saas/{productKey}/plan-change/cancel:
    post:
      tags:
        - SaaS Billing
      parameters:
        - in: path
          name: productKey
          required: true
          schema:
            type: string
            enum:
              - marketing-signatures
      responses:
        "200":
          description: Scheduled downgrade canceled.
          content:
            application/json:
              schema:
                type: object
                properties:
                  canceled:
                    type: boolean
        "400":
          description: Invalid request.
        "401":
          description: Authentication required.
        "403":
          description: Owner/admin required.
        "404":
          description: Product does not support plan changes.
        "409":
          description: Schedule changed or already took effect.
        "415":
          description: JSON required.
        "503":
          description: Billing unavailable.
      operationId: cancelSignaturePlanChange
      summary: Cancel a scheduled Signature downgrade
      description: Owner/admin only. Releases only a future schedule owned by the
        Signature panel and matching the current revision. The current
        subscription continues.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - revision
              properties:
                spaceId:
                  type: string
                  format: uuid
                revision:
                  type: string
  /api/v1/billing/saas/{productKey}/plan-change/preview:
    post:
      tags:
        - SaaS Billing
      parameters:
        - in: path
          name: productKey
          required: true
          schema:
            type: string
            enum:
              - marketing-signatures
      responses:
        "200":
          description: Signed plan review.
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string
                  plan:
                    type: object
                  direction:
                    type: string
                    enum:
                      - upgrade
                      - downgrade
                  effectiveAt:
                    type: string
                    format: date-time
                  expiresAt:
                    type: string
                    format: date-time
                  amountDue:
                    type: integer
                  currency:
                    type: string
        "400":
          description: Invalid plan or Space.
        "401":
          description: Authentication required.
        "403":
          description: Owner/admin required.
        "404":
          description: Product disabled.
        "409":
          description: Plan cannot currently be changed.
        "415":
          description: JSON required.
        "503":
          description: Pricing unavailable.
      operationId: previewSignaturePlanChange
      summary: Review a Signature upgrade or downgrade
      description: Owner/admin only. Returns a signed ten-minute review, the prorated
        amount for immediate upgrades, or the renewal date for downgrades. Does
        not modify the subscription.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - planId
              properties:
                spaceId:
                  type: string
                  format: uuid
                planId:
                  type: string
  /api/v1/billing/saas/{productKey}/plans:
    get:
      tags:
        - SaaS Billing
      parameters:
        - in: path
          name: productKey
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Public prices in minor currency units.
          content:
            application/json:
              schema:
                type: object
                properties:
                  available:
                    type: boolean
                  plans:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        amount:
                          type: integer
                        currency:
                          type: string
                        interval:
                          type: string
                          enum:
                            - month
                            - year
                        intervalCount:
                          type: integer
                        entitlements:
                          type: object
                        available:
                          type: boolean
        "404":
          description: Unknown or disabled product.
        "503":
          description: Catalog temporarily unavailable.
      operationId: getSaasBillingPlans
      summary: Get a SaaS product catalog
      description: Reads recurring prices and entitlements from the registered product
        catalog. Unknown or disabled products are unavailable.
      security: []
  /api/v1/billing/saas/{productKey}/portal:
    post:
      tags:
        - SaaS Billing
      parameters:
        - in: path
          name: productKey
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Stripe-hosted Customer Portal URL.
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                    format: uri
        "400":
          description: Invalid request.
        "401":
          description: Authentication required.
        "403":
          description: Space owner/admin required.
        "404":
          description: Unknown product or no billing customer.
        "409":
          description: Customer ownership needs review.
        "415":
          description: JSON request required.
        "503":
          description: Billing portal temporarily unavailable.
      operationId: createSaasBillingPortal
      summary: Manage a SaaS subscription
      description: Creates a portal for a Space owner/admin. Signatures uses the
        code-owned Space invoice/payment policy; Signature plan and renewal
        changes happen in Dashio. Other products retain their product
        configuration. Customer ownership and return URLs are server-controlled.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
              properties:
                spaceId:
                  type: string
                  format: uuid
  /api/v1/billing/saas/{productKey}/renewal:
    get:
      tags:
        - SaaS Billing
      parameters:
        - in: path
          name: productKey
          required: true
          schema:
            type: string
            enum:
              - marketing-signatures
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Current renewal state, billing period, allowed action and signed
            token, or a blocking reason.
        "400":
          description: Invalid Space ID.
        "401":
          description: Authentication required.
        "403":
          description: Space owner/admin required.
        "404":
          description: Signature subscription not found.
        "409":
          description: Subscription ownership requires review.
        "503":
          description: Billing unavailable.
      operationId: getSignatureRenewalReview
      summary: Review Signature subscription renewal
      description: Requires current Space owner/admin authorization. Reads live state
        and returns a short-lived signed review without mutating Stripe or local
        entitlements.
      security:
        - bearerAuth: []
    post:
      tags:
        - SaaS Billing
      parameters:
        - in: path
          name: productKey
          required: true
          schema:
            type: string
            enum:
              - marketing-signatures
      responses:
        "200":
          description: Confirmed cancelAtPeriodEnd state; webhook processing remains
            authoritative for entitlements.
        "400":
          description: Invalid confirmation.
        "401":
          description: Authentication required.
        "403":
          description: Space owner/admin required.
        "404":
          description: Signature subscription not found.
        "409":
          description: Expired, invalid or stale review, or a conflicting subscription
            state.
        "415":
          description: JSON required.
        "503":
          description: Billing unavailable.
      operationId: confirmSignatureRenewal
      summary: Confirm Signature renewal changes
      description: Confirms a signed, tenant-bound period-end cancellation or renewal
        restoration. Never accepts a submitted Stripe subscription ID or
        arbitrary cancellation settings.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - token
              properties:
                spaceId:
                  type: string
                  format: uuid
                token:
                  type: string
                  description: Signed renewal review, validated server-side with a 4096-character
                    limit.
  /api/v1/billing/saas/{productKey}/status:
    get:
      tags:
        - SaaS Billing
      parameters:
        - in: path
          name: productKey
          required: true
          schema:
            type: string
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Safe subscription status projection.
          content:
            application/json:
              schema:
                type: object
                properties:
                  canManageBilling:
                    type: boolean
                  canCheckout:
                    type: boolean
                  subscription:
                    type: object
                    nullable: true
                    properties:
                      planId:
                        type: string
                        nullable: true
                      status:
                        type: string
                      entitlements:
                        type: object
                      currentPeriodEnd:
                        type: string
                        nullable: true
                        format: date-time
                      cancelAtPeriodEnd:
                        type: boolean
        "400":
          description: Invalid Space.
        "401":
          description: Authentication required.
        "403":
          description: Space owner/admin required.
        "404":
          description: Unknown product.
        "503":
          description: Billing temporarily unavailable.
      operationId: getSaasBillingStatus
      summary: Get a SaaS subscription status
      description: Returns verified subscription state and repurchase availability for
        an authorized Space. Checkout return URLs never grant access. Existing
        billing remains manageable when the product is disabled.
      security:
        - bearerAuth: []
  /api/v1/billing/webhooks/stripe:
    post:
      tags:
        - Stripe Actions
      parameters:
        - name: stripe-signature
          in: header
          required: true
          description: Stripe-Signature header used to verify webhook authenticity.
          schema:
            type: string
      responses:
        "200":
          description: Webhook event verified and queued, or already queued.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: false
                required:
                  - received
                  - queued
                properties:
                  received:
                    type: boolean
                  queued:
                    type: boolean
              examples:
                default:
                  value:
                    received: true
                    queued: true
        "400":
          description: Missing signature/body or signature verification failed.
        "500":
          description: Internal error while processing the webhook event.
      operationId: postStripeWebhook
      summary: Handle Stripe webhooks
      description: Receives Stripe webhook events, verifies the Stripe signature, and
        queues the event for background processing. The request body must be the
        raw, unmodified payload as sent by Stripe (required for signature
        verification).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: string
              description: Raw request body (unmodified).
          text/plain:
            schema:
              type: string
              description: Raw request body (unmodified).
  /api/v1/careers/jobs/{job_title_slug}:
    get:
      tags:
        - Jobs
      parameters:
        - in: path
          name: job_title_slug
          required: true
          schema:
            type: string
            example: senior-frontend-engineer
          description: URL-safe slug (lowercase letters, digits, hyphens).
      responses:
        "200":
          description: Job listing found.
          content:
            application/json:
              schema:
                type: object
                description: Job listing record from `careers.job_listings`.
                additionalProperties: false
                properties:
                  id:
                    type: string
                    format: uuid
                  title:
                    type: string
                  title_slug:
                    type: string
                  description:
                    type: string
                  status:
                    type: string
                    example: Open
                  internal:
                    type: boolean
                    example: false
                required:
                  - id
                  - title
                  - title_slug
                  - status
                  - internal
              examples:
                default:
                  value:
                    id: 6b7f3e52-0b1a-4f3a-8a4d-3ac0f8a6d6d1
                    title: Senior Frontend Engineer
                    title_slug: senior-frontend-engineer
                    description: ...
                    status: Open
                    internal: false
        "400":
          description: Route parameter missing or invalid.
        "404":
          description: Job listing not found (or not public/open).
        "500":
          description: Internal server error.
      operationId: getJobBySlug
      summary: Get public job listing by slug
      description: Returns a single public job listing identified by the
        `job_title_slug` path parameter. Only listings with `status = Open` and
        `internal = false` are returned. Closed or internal listings are
        returned as 404.
  /api/v1/careers/jobs/apply:
    post:
      tags:
        - Jobs
      parameters: []
      responses:
        "201":
          description: Application submitted successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Application submitted successfully
        "400":
          description: "Validation error: missing or invalid fields."
        "500":
          description: Failed to store application or send emails.
      operationId: postJobApplication
      summary: Submit job application
      description: Validates fields, stores the application in the database, and sends
        confirmation and notification emails.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - job_id
                - first_name
                - last_name
                - email
                - phone_number
                - address
                - desired_salary
                - potential_start_date
                - job_title
              properties:
                job_id:
                  type: string
                  format: uuid
                first_name:
                  type: string
                last_name:
                  type: string
                email:
                  type: string
                  format: email
                phone_number:
                  type: string
                address:
                  type: string
                desired_salary:
                  type: string
                potential_start_date:
                  type: string
                job_title:
                  type: string
                document:
                  type: string
                  nullable: true
                  description: Document URL or identifier
                user_id:
                  type: string
                  nullable: true
                social_data:
                  type:
                    - object
                    - array
                  nullable: true
                  description: Optional social profile handles. Accepts either an object keyed by
                    platform (preferred) or an array of "key:value" strings
                    (legacy).
                  oneOf:
                    - type: object
                      additionalProperties: false
                      properties:
                        linkedin:
                          type: string
                          nullable: true
                          description: LinkedIn handle or full profile URL.
                          example: john-doe
                        x:
                          type: string
                          nullable: true
                          description: X (formerly Twitter) handle or profile URL.
                          example: "@john_doe"
                        github:
                          type: string
                          nullable: true
                          description: GitHub username or repository URL.
                          example: johndoe
                        portfolio:
                          type: string
                          nullable: true
                          description: Personal portfolio URL.
                          example: https://johndoe.dev
                      example:
                        linkedin: john-doe
                        github: https://github.com/johndoe
                        portfolio: https://johndoe.dev
                    - type: array
                      description: Legacy representation of social links as "key:value" strings.
                      items:
                        type: string
                        example: linkedin:john-doe
                document_base64:
                  type: string
                  nullable: true
                  description: Base64-encoded application PDF (optional)
            examples:
              default:
                summary: Complete application payload
                value:
                  job_id: 7f0b8f68-46e2-4d6e-8e3c-1234567890ab
                  first_name: Jane
                  last_name: Doe
                  email: jane.doe@example.com
                  phone_number: +49 176 12345678
                  address: Main Street 123, 10115 Berlin, Germany
                  desired_salary: 75,000€ / year
                  potential_start_date: 2024-11-01
                  job_title: Senior Frontend Engineer
                  document: web_uploads/2024-11-01-123456-application.pdf
                  user_id: 8c2b7a83-91d2-4a53-84f0-3216549870ba
                  social_data:
                    linkedin: jane-doe
                    github: janedoe
                    portfolio: https://janedoe.dev
                  document_base64: <base64-pdf-content>
  /api/v1/careers/jobs:
    get:
      tags:
        - Jobs
      parameters:
        - in: query
          name: page
          required: false
          schema:
            type: integer
            minimum: 1
            default: 1
          description: Page number (1-based).
          example: 1
        - in: query
          name: limit
          required: false
          schema:
            type: integer
            minimum: 1
            default: 5
          description: Items per page.
          example: 5
        - in: query
          name: search
          required: false
          schema:
            type: string
          description: Case-insensitive partial match against the job title.
        - in: query
          name: department
          required: false
          schema:
            type: string
        - in: query
          name: job_type
          required: false
          schema:
            type: string
        - in: query
          name: level
          required: false
          schema:
            type: string
        - in: query
          name: location
          required: false
          schema:
            type: string
        - in: query
          name: sort_by
          required: false
          schema:
            type: string
            default: created_at
            enum:
              - created_at
              - publication_date
              - application_deadline
              - title
              - department
              - job_type
              - level
          description: Column to sort by.
        - in: query
          name: sort_order
          required: false
          schema:
            type: string
            enum:
              - asc
              - desc
            default: desc
          description: Sort direction.
      responses:
        "200":
          description: Paginated list of job listings.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: false
                required:
                  - data
                  - total
                  - page
                  - totalPages
                properties:
                  data:
                    type: array
                    description: Job listings.
                    items:
                      type: object
                      additionalProperties: false
                      properties:
                        job_id:
                          type: string
                          format: uuid
                        created_at:
                          type: string
                          format: date-time
                        job_type:
                          type: string
                        title:
                          type: string
                        department:
                          type: string
                        locations:
                          type: array
                          items:
                            type: string
                        publication_date:
                          type: string
                          nullable: true
                        application_deadline:
                          type: string
                          nullable: true
                        requirements:
                          type: string
                          nullable: true
                        working_hours_model:
                          type: string
                          nullable: true
                        salary_range:
                          type: string
                          nullable: true
                        status:
                          type: string
                          example: Open
                        benefits:
                          type: string
                          nullable: true
                        internal:
                          type: boolean
                          example: false
                        job_description:
                          type: string
                          nullable: true
                        tasks:
                          type: string
                          nullable: true
                        applicant_profile:
                          type: string
                          nullable: true
                        level:
                          type: string
                          nullable: true
                        language_requirements:
                          type: string
                          nullable: true
                      required:
                        - job_id
                        - created_at
                        - title
                        - status
                        - internal
                  total:
                    type: integer
                    description: Total number of matching records.
                  page:
                    type: integer
                  totalPages:
                    type: integer
        "500":
          description: Internal server error.
      operationId: getJobs
      summary: List public job listings
      description: Returns paginated public job listings. Only listings with `status =
        Open` and `internal = false` are included. Supports optional search and
        filters, plus sorting.
  /api/v1/careers/jobs/options:
    get:
      tags:
        - Jobs
      parameters: []
      responses:
        "200":
          description: Option lists fetched successfully.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: false
                required:
                  - departments
                  - job_types
                  - levels
                  - locations
                properties:
                  departments:
                    type: array
                    items:
                      type: string
                  job_types:
                    type: array
                    items:
                      type: string
                  levels:
                    type: array
                    items:
                      type: string
                  locations:
                    type: array
                    items:
                      type: string
              examples:
                default:
                  value:
                    departments:
                      - Engineering
                      - Marketing
                    job_types:
                      - Full-time
                      - Part-time
                    levels:
                      - Junior
                      - Senior
                    locations:
                      - Berlin
                      - Remote
        "500":
          description: Internal server error.
      operationId: getJobOptions
      summary: Get job filter options
      description: "Returns unique filter option lists derived from public job
        listings (`status = Open`, `internal = false`): departments, job types,
        levels, and locations."
  /api/v1/community/newsletter/subscribe:
    post:
      tags:
        - Newsletter
      parameters: []
      responses:
        "201":
          description: Contact created or updated successfully in the audience.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                required:
                  - success
                  - message
        "400":
          description: Invalid request (e.g., missing or invalid email, invalid name).
        "500":
          description: Failed to create contact (upstream error or internal failure).
      operationId: postNewsletterSubscribe
      summary: Subscribe to the newsletter
      description: Creates a contact in the newsletter audience after validating the
        email and optional name fields.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
              properties:
                email:
                  type: string
                  format: email
                  description: Subscriber email address.
                firstName:
                  type: string
                  description: Optional first name.
                lastName:
                  type: string
                  description: Optional last name.
              additionalProperties: false
            examples:
              minimal:
                summary: Email only
                value:
                  email: sam@example.com
              full:
                summary: Email with names
                value:
                  email: sam@example.com
                  firstName: Sam
                  lastName: Rivera
  /api/v1/community/partners/apply:
    post:
      tags:
        - Partner
      parameters: []
      responses:
        "200":
          description: Partner application accepted and stored.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Partner application form submitted successfully
        "400":
          description: Validation error in one or more fields.
        "404":
          description: User not found for provided user_id.
        "409":
          description: Duplicate submission for this user_id.
        "422":
          description: Missing or invalid Turnstile token.
        "500":
          description: Internal server error while storing or sending emails.
      operationId: postPartnerApplication
      summary: Submit partner application
      description: Validates partner application data, verifies a Turnstile token for
        spam prevention, stores the submission, and sends
        confirmation/notification emails.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - token
                - full_name
                - street
                - city
                - state
                - zip
                - country
                - promotion_plan
                - join_reason
                - user_id
              properties:
                token:
                  type: string
                  description: Cloudflare Turnstile token
                company:
                  type: string
                  nullable: true
                  description: Optional company name
                full_name:
                  type: string
                street:
                  type: string
                city:
                  type: string
                state:
                  type: string
                zip:
                  type: string
                country:
                  type: string
                promotion_plan:
                  type: string
                  description: Planned promotional activities as free text
                join_reason:
                  type: string
                  description: Reason for joining the partner program
                user_id:
                  type: string
                  format: uuid
                  description: Existing authenticated user id
              additionalProperties: false
            examples:
              example:
                summary: Valid application payload
                value:
                  token: 1x0000000000000000000000000000000AA
                  company: Acme GmbH
                  full_name: Jane Doe
                  street: Example Straße 12
                  city: Berlin
                  state: Berlin
                  zip: "10115"
                  country: Germany
                  promotion_plan: Publish integration guide and host webinars
                  join_reason: Existing customer base looking for managed solutions
                  user_id: 13jc72b5-8561-48cd-9652-2e88a23aa999
  /api/v1/community/roadmap:
    get:
      tags:
        - Roadmap
      parameters: []
      responses:
        "200":
          description: The public roadmap and its release-controlled starting quarter.
          content:
            application/json:
              schema:
                type: object
                required:
                  - focusQuarterId
                  - quarters
                properties:
                  focusQuarterId:
                    type: string
                    example: q4-2026
                  quarters:
                    type: array
                    items:
                      type: object
                      required:
                        - id
                        - title
                        - date
                        - description
                        - features
                      properties:
                        id:
                          type: string
                          example: q4-2026
                        title:
                          type: string
                          example: Q4 2026
                        date:
                          type: string
                          example: October – December 2026
                        description:
                          type: string
                        tone:
                          type: string
                          enum:
                            - primary
                            - neutral
                        features:
                          type: array
                          items:
                            type: object
                            required:
                              - id
                              - title
                              - highlights
                              - category
                              - status
                            properties:
                              id:
                                type: string
                              title:
                                type: string
                              highlights:
                                type: array
                                description: Three concise feature highlights, including applicable
                                  prerequisites and rollout timing.
                                items:
                                  type: string
                              category:
                                type: string
                                enum:
                                  - Marketing
                                  - Platform
                                  - Domains
                                  - Developers
                                  - Certificates
                                  - Community
                              status:
                                type: string
                                enum:
                                  - planned
                                  - in-progress
                                  - shipped
      operationId: getPublicRoadmap
      summary: Get the public product roadmap
      description: Returns shipped releases and planned features in chronological
        order, with an explicit starting quarter. Statuses are editorial, not
        feature flags.
      security: []
  /api/v1/community/waitlist/subscribe:
    post:
      tags:
        - Waitlist
      parameters: []
      responses:
        "201":
          description: Successfully joined the waitlist.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                required:
                  - success
                  - message
        "400":
          description: Invalid request (e.g., malformed email).
        "500":
          description: Internal server error.
      operationId: postWaitlistSubscribe
      summary: Join the maintenance waitlist
      description: Adds an email address to the maintenance waitlist and forwards it
        to the newsletter audience.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
              properties:
                email:
                  type: string
                  format: email
                  description: Email to subscribe to the waitlist (and newsletter).
              additionalProperties: false
            examples:
              basic:
                summary: Minimal payload
                value:
                  email: alex@example.com
  /api/v1/marketing/generators/{id}:
    delete:
      tags:
        - Marketing
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: revision
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Generator deleted.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
        "400":
          description: Invalid identifier or revision.
        "401":
          description: Unauthenticated.
        "403":
          description: Owner or admin membership required.
        "409":
          description: Stale revision; reload the generator.
        "500":
          description: Database operation failed.
      operationId: deleteMarketingGenerator
      summary: Delete a signature generator
      description: Deletes the draft and published snapshot for one tenant-owned
        generator. Requires owner/admin membership and the current revision.
      security:
        - bearerAuth: []
    get:
      tags:
        - Marketing
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
            format: uuid
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Generator administration data.
          content:
            application/json:
              schema:
                type: object
                properties:
                  generator:
                    type: object
        "400":
          description: Invalid identifier.
        "401":
          description: Unauthenticated.
        "403":
          description: Owner or admin membership required.
        "404":
          description: Generator not found in this Space.
        "500":
          description: Database operation failed.
      operationId: getMarketingGenerator
      summary: Read a signature generator
      description: Returns the current draft, published snapshot and revision to a
        Space owner or admin.
      security:
        - bearerAuth: []
    put:
      tags:
        - Marketing
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Saved draft with incremented revision.
          content:
            application/json:
              schema:
                type: object
                properties:
                  generator:
                    type: object
        "400":
          description: Invalid configuration or revision.
        "401":
          description: Unauthenticated.
        "403":
          description: Owner or admin membership required.
        "409":
          description: Stale revision or slug unavailable.
        "415":
          description: JSON request required.
        "500":
          description: Database operation failed.
      operationId: updateMarketingGenerator
      summary: Save a signature generator draft
      description: Replaces the draft without publishing it. The current revision is
        mandatory to prevent lost updates. Changing the slug also changes the
        employee link immediately.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - name
                - slug
                - config
                - revision
              properties:
                spaceId:
                  type: string
                  format: uuid
                name:
                  type: string
                slug:
                  type: string
                config:
                  type: object
                revision:
                  type: integer
  /api/v1/marketing/generators/{id}/publish:
    post:
      tags:
        - Marketing
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Published generator and incremented revision.
          content:
            application/json:
              schema:
                type: object
                properties:
                  generator:
                    type: object
        "400":
          description: Invalid identifier or revision.
        "401":
          description: Unauthenticated.
        "402":
          description: Active paid subscription required.
        "403":
          description: Insufficient membership or plan limit reached.
        "404":
          description: Generator not found in this Space.
        "409":
          description: Stale revision; reload the generator.
        "415":
          description: JSON request required.
        "500":
          description: Database operation failed.
      operationId: publishMarketingGenerator
      summary: Publish a signature generator
      description: Copies the saved draft to the employee-facing snapshot. The
        database atomically checks the current revision, active paid
        subscription and plan limit.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - revision
              properties:
                spaceId:
                  type: string
                  format: uuid
                revision:
                  type: integer
  /api/v1/marketing/generators/{id}/unpublish:
    post:
      tags:
        - Marketing
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Unpublished generator and incremented revision.
          content:
            application/json:
              schema:
                type: object
                properties:
                  generator:
                    type: object
        "400":
          description: Invalid identifier or revision.
        "401":
          description: Unauthenticated.
        "403":
          description: Owner or admin membership required.
        "409":
          description: Stale revision; reload the generator.
        "415":
          description: JSON request required.
        "500":
          description: Database operation failed.
      operationId: unpublishMarketingGenerator
      summary: Unpublish a signature generator
      description: Removes access from the public generator link immediately,
        preserving the saved draft. Available to owners/admins even after the
        subscription ends.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - revision
              properties:
                spaceId:
                  type: string
                  format: uuid
                revision:
                  type: integer
  /api/v1/marketing/generators:
    get:
      tags:
        - Marketing
      parameters:
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Generators for the requested Space.
          content:
            application/json:
              schema:
                type: object
                properties:
                  generators:
                    type: array
                    items:
                      type: object
        "400":
          description: Invalid Space identifier.
        "401":
          description: Unauthenticated.
        "403":
          description: Owner or admin membership required.
        "500":
          description: Database operation failed.
      operationId: listMarketingGenerators
      summary: List signature generators
      description: Lists drafts and published snapshots belonging to one Space.
        Requires owner or admin membership.
      security:
        - bearerAuth: []
    post:
      tags:
        - Marketing
      parameters: []
      responses:
        "201":
          description: Created draft.
          content:
            application/json:
              schema:
                type: object
                properties:
                  generator:
                    type: object
        "400":
          description: Invalid metadata or configuration.
        "401":
          description: Unauthenticated.
        "403":
          description: Insufficient membership or plan limit reached.
        "409":
          description: Generator address already in use.
        "415":
          description: JSON request required.
        "500":
          description: Database operation failed.
      operationId: createMarketingGenerator
      summary: Create a signature generator draft
      description: Creates a draft. One draft is available before subscribing; paid
        plan limits are enforced atomically by the database. Names contain 1–120
        characters and slugs 3–64 lowercase letters, numbers or internal
        hyphens.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - name
                - slug
                - config
              properties:
                spaceId:
                  type: string
                  format: uuid
                name:
                  type: string
                slug:
                  type: string
                config:
                  type: object
                  description: Version 1 structured signature configuration; employee data is
                    never accepted.
  /api/v1/marketing/public/{slug}:
    get:
      tags:
        - Marketing
      parameters:
        - in: path
          name: slug
          required: true
          schema:
            type: string
          description: Public generator address, 3–64 lowercase letters, numbers or
            internal hyphens.
      responses:
        "200":
          description: Public company configuration and canonical space slug.
          content:
            application/json:
              schema:
                type: object
                required:
                  - name
                  - spaceSlug
                  - slug
                  - config
                properties:
                  name:
                    type: string
                  spaceSlug:
                    type: string
                  slug:
                    type: string
                  config:
                    type: object
        "404":
          description: Unknown, unpublished, inactive or unavailable generator.
        "500":
          description: Database operation failed.
      operationId: getPublicMarketingGenerator
      summary: Read a published employee signature generator
      description: Legacy lookup resolves a canonical space slug only when the
        generator slug belongs to exactly one space. Ambiguous links return 404.
        Publication, subscription and quota checks apply. Responses are no-store
        and noindex.
      security: []
  /api/v1/marketing/public/{spaceSlug}/{slug}:
    get:
      tags:
        - Marketing
      parameters:
        - in: path
          name: spaceSlug
          required: true
          schema:
            type: string
          description: The company space slug.
        - in: path
          name: slug
          required: true
          schema:
            type: string
          description: The generator slug within that space.
      responses:
        "200":
          description: Public company configuration.
          content:
            application/json:
              schema:
                type: object
                required:
                  - name
                  - spaceSlug
                  - slug
                  - config
                properties:
                  name:
                    type: string
                  spaceSlug:
                    type: string
                  slug:
                    type: string
                  config:
                    type: object
        "404":
          description: Unknown, unpublished, inactive or unavailable generator.
        "500":
          description: Database operation failed.
      operationId: getSpacePublicMarketingGenerator
      summary: Read a published signature generator within a space
      description: Resolves the space and generator slugs together. Active
        subscription, publication and plan-limit checks apply. Only public
        company configuration is returned; responses are no-store and noindex.
      security: []
  /api/v1/products/certificates:
    get:
      tags:
        - Certificate Products
      parameters: []
      responses:
        "200":
          description: Successfully retrieved the SSL certificate product list.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  products:
                    type: object
                    properties:
                      results:
                        type: array
                        description: List of SSL products with margin pricing applied.
                      total:
                        type: integer
                        description: Total number of products returned.
                    required:
                      - results
                      - total
                required:
                  - success
                  - products
        "500":
          description: Failed to load SSL certificate products.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                required:
                  - success
                  - error
      operationId: getCertificates
      summary: List SSL certificate products
      description: Fetches SSL certificate products from Openprovider and returns them
        with calculated sale prices. Intended for the public solutions page.
  /api/v1/products/domains/alternatives:
    post:
      tags:
        - Domain Products
      parameters: []
      responses:
        "200":
          description: NDJSON stream of candidate, result, unavailable, error, and done
            messages.
        "400":
          description: Invalid request parameters.
      operationId: streamDomainAlternatives
      summary: Stream domain alternatives
      description: Streams alternative domain candidates and priced available results
        as NDJSON.
  /api/v1/products/domains/check:
    post:
      tags:
        - Domain Products
      parameters:
        - in: query
          name: alternatives
          required: false
          description: If true, also checks a curated pool of alternative TLDs and returns
            up to five available alternatives in addition to the primary domain.
          schema:
            type: boolean
          examples:
            disabled:
              value: false
            enabled:
              value: true
      responses:
        "200":
          description: Search completed. Returns the primary domain result and, when
            requested, up to five available alternatives.
          content:
            application/json:
              schema:
                type: object
                properties:
                  domains:
                    type: array
                    description: Ordered results. The first element is always the primary domain.
                      When `alternatives=true`, additional available
                      alternatives may follow.
                    items:
                      type: object
                      properties:
                        domain:
                          type: string
                          description: Fully-qualified domain in lowercase (e.g., "example.com").
                        available:
                          type: boolean
                          description: True if the domain is currently available for registration.
                        price:
                          type: string
                          description: Net price (string, two decimals) with margin applied, derived from
                            create/renew prices.
                          example: "11.90"
                        currency:
                          type: string
                          description: ISO currency code from Openprovider (usually "EUR").
                          example: EUR
                      required:
                        - domain
                        - available
                        - price
                        - currency
                required:
                  - domains
              examples:
                primaryOnly:
                  summary: Primary domain unavailable, no alternatives requested
                  value:
                    domains:
                      - domain: acme.com
                        available: false
                        price: "0.00"
                        currency: EUR
                withAlternatives:
                  summary: Primary + available alternatives
                  value:
                    domains:
                      - domain: acme.com
                        available: false
                        price: "0.00"
                        currency: EUR
                      - domain: acme.io
                        available: true
                        price: "34.90"
                        currency: EUR
                      - domain: acme.dev
                        available: true
                        price: "12.90"
                        currency: EUR
        "400":
          description: Invalid request. Returned when the input array is missing/empty or
            domain format validation fails after sanitization.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  status:
                    type: integer
                required:
                  - error
                  - status
              examples:
                emptyArray:
                  value:
                    error: Invalid request parameters. Expecting an array of domains.
                    status: 400
                invalidDomain:
                  value:
                    error: Invalid domain format.
                    status: 400
        "500":
          description: Server-side or upstream error (e.g., Openprovider error or renewal
            price fetch failure).
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  status:
                    type: integer
                  details:
                    type: string
                required:
                  - error
                  - status
              examples:
                upstream:
                  value:
                    error: Failed to fetch domain info
                    status: 500
                generic:
                  value:
                    error: Internal Server Error
                    status: 500
                    details: Upstream timeout
      operationId: checkDomains
      summary: Check domain availability
      description: Checks domain availability via Openprovider and returns the highest
        create or renewal price with margin applied. Optionally checks
        alternative TLDs and returns up to five available alternatives alongside
        the primary query. Input is sanitized (lowercased, diacritics removed,
        common German umlauts transliterated, invalid characters stripped).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                domains:
                  type: array
                  description: List of domain queries to check. The first item is treated as the
                    primary domain; its alternatives may be explored when
                    `alternatives=true`.
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                        description: Second-level label (e.g., "example"). Will be sanitized
                          (lowercased, invalid chars removed).
                      extension:
                        type: string
                        description: TLD without leading dot (e.g., "com", "de"). Will be sanitized
                          (lowercased).
                    required:
                      - name
                      - extension
                  minItems: 1
              required:
                - domains
            examples:
              single:
                summary: Single domain
                value:
                  domains:
                    - name: dashio
                      extension: net
              multi:
                summary: Multiple domains (first is primary)
                value:
                  domains:
                    - name: acme
                      extension: com
                    - name: acme
                      extension: io
  /api/v1/products/domains/prices:
    get:
      tags:
        - Domain Products
      parameters: []
      responses:
        "200":
          description: Successfully retrieved TLD prices.
          content:
            application/json:
              schema:
                type: object
                properties:
                  prices:
                    type: array
                    description: List of TLDs with their current registration and renewal prices.
                    items:
                      type: object
                      properties:
                        tld:
                          type: string
                          description: Top-level domain (e.g. .com, .de).
                        registerPrice:
                          type: number
                          description: Highest registration or renewal price in EUR (with margin applied).
                        renewPrice:
                          type: number
                          description: Highest registration or renewal price in EUR (with margin applied).
                      required:
                        - tld
                        - registerPrice
                        - renewPrice
                  cached:
                    type: boolean
                    description: Indicates whether the data was served from cache.
                required:
                  - prices
        "500":
          description: Failed to fetch TLD prices due to an internal error or upstream
            issue.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  status:
                    type: integer
                  details:
                    type: string
                required:
                  - error
                  - status
      operationId: getDomainPrices
      summary: Retrieve domain TLD prices
      description: Retrieves a list of popular TLD prices from Openprovider. Results
        are cached for 12 hours to reduce external API calls. Returns the
        highest current registration or renewal price for selected extensions.
  /api/v1/products/domains/restrictions:
    get:
      tags:
        - Domain Products
      parameters:
        - in: query
          name: extensions
          required: true
          description: Comma-separated list of TLD extensions without leading dots (e.g.,
            "us,de,eu,io")
          schema:
            type: string
          examples:
            single:
              value: us
            multiple:
              value: us,de,eu
      responses:
        "200":
          description: TLD restrictions retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  restrictions:
                    type: array
                    items:
                      type: object
                      properties:
                        extension:
                          type: string
                          description: TLD extension (e.g., "us")
                        restrictions:
                          type: array
                          items:
                            type: string
                          description: Array of restriction messages
                        isPrivateWhoisAllowed:
                          type: boolean
                          description: Whether WHOIS privacy is available
                        dnssecAllowed:
                          type: boolean
                          description: Whether DNSSEC is available
                        minPeriod:
                          type: integer
                          description: Minimum registration period in years
                        maxPeriod:
                          type: integer
                          description: Maximum registration period in years
                        transferAvailable:
                          type: boolean
                          description: Whether transfers are available
                        renewAvailable:
                          type: boolean
                          description: Whether renewals are available
                        status:
                          type: string
                          description: TLD status (e.g., "ACT")
                      required:
                        - extension
                        - restrictions
                        - isPrivateWhoisAllowed
                        - dnssecAllowed
                        - minPeriod
                        - maxPeriod
                        - transferAvailable
                        - renewAvailable
                        - status
                  cached:
                    type: boolean
                    description: Whether the response was served from cache
                  cachedAt:
                    type: string
                    nullable: true
                    description: ISO timestamp of when the data was cached
                required:
                  - restrictions
                  - cached
              examples:
                singleTld:
                  summary: Single TLD with restrictions
                  value:
                    restrictions:
                      - extension: us
                        restrictions:
                          - Local address of the domain owner is required.
                          - The listed nameservers for a .us domain have to be
                            located within the United States.
                        isPrivateWhoisAllowed: false
                        dnssecAllowed: true
                        minPeriod: 1
                        maxPeriod: 10
                        transferAvailable: true
                        renewAvailable: true
                        status: ACT
                    cached: true
                    cachedAt: 2026-05-11T10:30:00.000Z
                multipleTlds:
                  summary: Multiple TLDs
                  value:
                    restrictions:
                      - extension: eu
                        restrictions:
                          - It is required that the office/residence of the
                            registrant is within the EU.
                        isPrivateWhoisAllowed: false
                        dnssecAllowed: true
                        minPeriod: 1
                        maxPeriod: 10
                        transferAvailable: true
                        renewAvailable: true
                        status: ACT
                      - extension: io
                        restrictions: []
                        isPrivateWhoisAllowed: true
                        dnssecAllowed: true
                        minPeriod: 1
                        maxPeriod: 10
                        transferAvailable: true
                        renewAvailable: true
                        status: ACT
                    cached: false
                    cachedAt: 2026-05-11T10:35:00.000Z
        "400":
          description: Invalid request parameters
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  status:
                    type: integer
              examples:
                missingParam:
                  value:
                    error: "Missing required query parameter: extensions"
                    status: 400
                tooMany:
                  value:
                    error: Maximum 50 extensions allowed per request
                    status: 400
        "500":
          description: Server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  status:
                    type: integer
      operationId: getTldRestrictions
      summary: Get TLD restrictions
      description: Fetches registration restrictions for specified TLDs from
        OpenProvider. Results are cached server-side for 24 hours to ensure fast
        response times. Restrictions include eligibility requirements and WHOIS
        privacy availability.
  /api/v1/spaces/assets/certificates:
    get:
      tags:
        - Space Assets
      parameters: []
      responses:
        "200":
          description: Certificates were returned successfully.
          content:
            application/json:
              schema:
                type: object
                required:
                  - certificates
                properties:
                  certificates:
                    type: array
                    items:
                      type: object
                      required:
                        - id
                        - name
                        - type
                        - status
                        - issued_at
                        - expires_at
                      properties:
                        id:
                          type: string
                          description: Unique certificate identifier (e.g., "cert-1").
                          example: cert-1
                        name:
                          type: string
                          description: Certificate common name or label (e.g., domain, product name,
                            mailbox, or VMC handle).
                          example: dashio.net
                        type:
                          type: string
                          description: "Certificate category. Examples: TLS, Code Signing, Document
                            Signing, S/MIME, VMC."
                          example: TLS
                        status:
                          type: string
                          description: "Lifecycle status of the certificate. Examples: Active, Pending,
                            Revoked, Expired."
                          example: Active
                        issued_at:
                          type: string
                          format: date-time
                          description: Issue timestamp (ISO 8601).
                          example: 2025-01-01T00:00:00.000Z
                        expires_at:
                          type: string
                          format: date-time
                          description: Expiry timestamp (ISO 8601).
                          example: 2026-01-01T00:00:00.000Z
              examples:
                success:
                  value:
                    certificates:
                      - id: cert-1
                        name: dashio.net
                        type: TLS
                        status: Active
                        issued_at: 2025-01-01T00:00:00.000Z
                        expires_at: 2026-01-01T00:00:00.000Z
        "500":
          description: Internal Server Error
      operationId: listSpaceCertificates
      summary: List Space Certificates
      description: Returns certificate items for a Space. Currently backed by mock
        data; will be replaced with database results. Each item includes id,
        name, type, status, issued_at, and expires_at. All timestamps are ISO
        8601 strings.
  /api/v1/spaces/assets/domains/{domain}/addons/{addonId}:
    patch:
      tags:
        - Domain Addons
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
        - in: path
          name: addonId
          required: true
          schema:
            type: string
          description: Identifier of the addon
      responses:
        "200":
          description: Addon updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  addon:
                    type: object
                    properties:
                      id:
                        type: string
                      name:
                        type: string
                      description:
                        type: string
                      price:
                        type: number
                      enabled:
                        type: boolean
                      features:
                        type: array
                        items:
                          type: string
                      icon:
                        type: string
                      configurable:
                        type: boolean
                        nullable: true
                    required:
                      - id
                      - name
                      - description
                      - price
                      - enabled
                      - features
                      - icon
                    additionalProperties: false
                required:
                  - addon
        "400":
          description: Invalid request.
        "404":
          description: Domain or addon not found.
        "500":
          description: Failed to update addon.
      operationId: updateDomainAddon
      summary: Update addon state
      description: Enables or disables a specific addon on the domain.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
                space_id:
                  type: string
                  description: Space ID
                force_remove:
                  type: boolean
                  description: Force remove the addon immediately, bypassing
                    cancellation_requested state
  /api/v1/spaces/assets/domains/{domain}/addons/checkout:
    post:
      tags:
        - Domain Addons
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Checkout session created or addon activated.
          content:
            application/json:
              schema:
                type: object
                properties:
                  requires_payment:
                    type: boolean
                  checkout_url:
                    type: string
                    nullable: true
                  session_id:
                    type: string
                    nullable: true
                  addon_activated:
                    type: boolean
                    nullable: true
        "400":
          description: Invalid request.
        "401":
          description: Unauthenticated.
        "404":
          description: Domain or addon not found.
        "500":
          description: Failed to create checkout.
      operationId: createDomainAddonCheckout
      summary: Create addon checkout session
      description: Creates a Stripe Checkout session for purchasing a paid addon or
        activates a free addon directly.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                addon_id:
                  type: string
                  description: ID of the addon to purchase
                space_id:
                  type: string
                  description: Space ID
                success_url:
                  type: string
                  description: URL to redirect after successful payment
                cancel_url:
                  type: string
                  description: URL to redirect if payment is cancelled
              required:
                - addon_id
                - space_id
                - success_url
                - cancel_url
  /api/v1/spaces/assets/domains/{domain}/addons:
    get:
      tags:
        - Domain Addons
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Addons retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  addons:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        description:
                          type: string
                        price:
                          type: number
                        enabled:
                          type: boolean
                        features:
                          type: array
                          items:
                            type: string
                        icon:
                          type: string
                        configurable:
                          type: boolean
                          nullable: true
                      required:
                        - id
                        - name
                        - description
                        - price
                        - enabled
                        - features
                        - icon
                      additionalProperties: false
                required:
                  - addons
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found.
        "500":
          description: Failed to load addons.
      operationId: listDomainAddons
      summary: List domain addons
      description: Returns available addons for a specific domain.
      security:
        - bearerAuth: []
  /api/v1/spaces/assets/domains/{domain}/contacts/{contactId}:
    delete:
      tags:
        - Domain Contacts
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
        - in: path
          name: contactId
          required: true
          schema:
            type: integer
          description: Identifier of the contact
      responses:
        "200":
          description: Contact removed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                required:
                  - success
        "400":
          description: Invalid domain.
        "404":
          description: Domain or contact not found.
        "500":
          description: Failed to delete contact.
      operationId: deleteDomainContact
      summary: Delete domain contact
      description: Removes a contact from the specified domain.
      security:
        - bearerAuth: []
    patch:
      tags:
        - Domain Contacts
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
        - in: path
          name: contactId
          required: true
          schema:
            type: integer
          description: Identifier of the contact
      responses:
        "200":
          description: Contact updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  contact:
                    type: object
                    properties:
                      id:
                        type: number
                      type:
                        type: string
                        enum:
                          - PERSON
                          - ORG
                      role:
                        type: string
                        enum:
                          - owner
                          - admin
                          - tech
                          - billing
                      firstName:
                        type: string
                      lastName:
                        type: string
                      gender:
                        type: string
                        enum:
                          - M
                          - F
                          - U
                      email:
                        type: string
                        format: email
                      phone:
                        type: object
                        properties:
                          countryCode:
                            type: string
                          areaCode:
                            type: string
                          subscriberNumber:
                            type: string
                        required:
                          - countryCode
                          - areaCode
                          - subscriberNumber
                        additionalProperties: false
                      address:
                        type: object
                        properties:
                          street:
                            type: array
                            items:
                              type: string
                          city:
                            type: string
                          state:
                            type: string
                            nullable: true
                          zip:
                            type: string
                          country:
                            type: string
                        required:
                          - street
                          - city
                          - zip
                          - country
                        additionalProperties: false
                    required:
                      - id
                      - type
                      - role
                      - firstName
                      - lastName
                      - gender
                      - email
                      - phone
                      - address
                    additionalProperties: false
                required:
                  - contact
        "400":
          description: Invalid request.
        "404":
          description: Domain or contact not found.
        "500":
          description: Failed to update contact.
      operationId: updateDomainContact
      summary: Update domain contact
      description: Modifies details of an existing domain contact.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                contact:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                        - PERSON
                        - ORG
                    role:
                      type: string
                      enum:
                        - owner
                        - admin
                        - tech
                        - billing
                    firstName:
                      type: string
                    lastName:
                      type: string
                    gender:
                      type: string
                      enum:
                        - M
                        - F
                        - U
                    email:
                      type: string
                      format: email
                    phone:
                      type: object
                      properties:
                        countryCode:
                          type: string
                        areaCode:
                          type: string
                        subscriberNumber:
                          type: string
                      required:
                        - countryCode
                        - areaCode
                        - subscriberNumber
                      additionalProperties: false
                    address:
                      type: object
                      properties:
                        street:
                          type: array
                          items:
                            type: string
                        city:
                          type: string
                        state:
                          type: string
                          nullable: true
                        zip:
                          type: string
                        country:
                          type: string
                      required:
                        - street
                        - city
                        - zip
                        - country
                      additionalProperties: false
                  required:
                    - type
                    - role
                    - firstName
                    - lastName
                    - gender
                    - email
                    - phone
                    - address
                  additionalProperties: false
              required:
                - contact
  /api/v1/spaces/assets/domains/{domain}/contacts:
    get:
      tags:
        - Domain Contacts
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Contacts retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  contacts:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: number
                          nullable: true
                        type:
                          type: string
                          enum:
                            - PERSON
                            - ORG
                        role:
                          type: string
                          enum:
                            - owner
                            - admin
                            - tech
                            - billing
                        firstName:
                          type: string
                        lastName:
                          type: string
                        email:
                          type: string
                          format: email
                        phone:
                          type: object
                          properties:
                            countryCode:
                              type: string
                            areaCode:
                              type: string
                            subscriberNumber:
                              type: string
                          required:
                            - countryCode
                            - areaCode
                            - subscriberNumber
                          additionalProperties: false
                        address:
                          type: object
                          properties:
                            street:
                              type: array
                              items:
                                type: string
                            city:
                              type: string
                            state:
                              type: string
                              nullable: true
                            zip:
                              type: string
                            country:
                              type: string
                          required:
                            - street
                            - city
                            - zip
                            - country
                          additionalProperties: false
                      required:
                        - type
                        - role
                        - firstName
                        - lastName
                        - email
                        - phone
                        - address
                      additionalProperties: false
                required:
                  - contacts
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found.
        "500":
          description: Failed to load contacts.
      operationId: listDomainContacts
      summary: List domain contacts
      description: Returns all contacts associated with the specified domain.
      security:
        - bearerAuth: []
    post:
      tags:
        - Domain Contacts
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Contact created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  contact:
                    type: object
                    properties:
                      id:
                        type: number
                      type:
                        type: string
                        enum:
                          - PERSON
                          - ORG
                      role:
                        type: string
                        enum:
                          - owner
                          - admin
                          - tech
                          - billing
                      firstName:
                        type: string
                      lastName:
                        type: string
                      gender:
                        type: string
                        enum:
                          - M
                          - F
                          - U
                      email:
                        type: string
                        format: email
                      phone:
                        type: object
                        properties:
                          countryCode:
                            type: string
                          areaCode:
                            type: string
                          subscriberNumber:
                            type: string
                        required:
                          - countryCode
                          - areaCode
                          - subscriberNumber
                        additionalProperties: false
                      address:
                        type: object
                        properties:
                          street:
                            type: array
                            items:
                              type: string
                          city:
                            type: string
                          state:
                            type: string
                            nullable: true
                          zip:
                            type: string
                          country:
                            type: string
                        required:
                          - street
                          - city
                          - zip
                          - country
                        additionalProperties: false
                    required:
                      - id
                      - type
                      - role
                      - firstName
                      - lastName
                      - gender
                      - email
                      - phone
                      - address
                    additionalProperties: false
                required:
                  - contact
        "400":
          description: Invalid request.
        "404":
          description: Domain not found.
        "500":
          description: Failed to create contact.
      operationId: createDomainContact
      summary: Create domain contact
      description: Adds a new contact to the specified domain.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                spaceId:
                  type: string
                  format: uuid
                  nullable: true
                contact:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                        - PERSON
                        - ORG
                    role:
                      type: string
                      enum:
                        - owner
                        - admin
                        - tech
                        - billing
                    firstName:
                      type: string
                    lastName:
                      type: string
                    gender:
                      type: string
                      enum:
                        - M
                        - F
                        - U
                    email:
                      type: string
                      format: email
                    phone:
                      type: object
                      properties:
                        countryCode:
                          type: string
                        areaCode:
                          type: string
                        subscriberNumber:
                          type: string
                      required:
                        - countryCode
                        - areaCode
                        - subscriberNumber
                      additionalProperties: false
                    address:
                      type: object
                      properties:
                        street:
                          type: array
                          items:
                            type: string
                        city:
                          type: string
                        state:
                          type: string
                          nullable: true
                        zip:
                          type: string
                        country:
                          type: string
                      required:
                        - street
                        - city
                        - zip
                        - country
                      additionalProperties: false
                  required:
                    - type
                    - role
                    - firstName
                    - lastName
                    - gender
                    - email
                    - phone
                    - address
                  additionalProperties: false
              required:
                - contact
    put:
      tags:
        - Domain Contacts
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
          description: Space ID associated with the domain
        - in: query
          name: contactId
          required: true
          schema:
            type: string
          description: Openprovider contact ID to update
        - in: query
          name: role
          required: true
          schema:
            type: string
            enum:
              - owner
              - admin
              - tech
              - billing
          description: New contact role
      responses:
        "200":
          description: Contact role updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                required:
                  - message
        "400":
          description: Invalid request.
        "401":
          description: Unauthenticated.
        "404":
          description: Domain not found.
        "500":
          description: Failed to update contact role.
      operationId: updateDomainContactRole
      summary: Update domain contact role
      description: Updates the role for a contact associated with the specified domain.
      security:
        - bearerAuth: []
  /api/v1/spaces/assets/domains/{domain}/contacts/verify:
    post:
      tags:
        - API Routes
      parameters:
        - name: domain
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: OK
  /api/v1/spaces/assets/domains/{domain}/dnssec:
    get:
      tags:
        - Domain DNSSEC
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: DNSSEC configuration returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  config:
                    type: object
                    properties:
                      isDnssecEnabled:
                        type: boolean
                      autoRenew:
                        type: boolean
                      dnssecKeys:
                        type: array
                        items:
                          type: object
                          properties:
                            flags:
                              type: integer
                              enum:
                                - 256
                                - 257
                            protocol:
                              type: integer
                              enum:
                                - 3
                            alg:
                              type: integer
                              enum:
                                - 3
                                - 5
                                - 6
                                - 7
                                - 8
                                - 10
                                - 13
                            pubKey:
                              type: string
                          required:
                            - flags
                            - protocol
                            - alg
                            - pubKey
                    required:
                      - isDnssecEnabled
                      - autoRenew
                      - dnssecKeys
                required:
                  - config
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found.
        "500":
          description: Failed to load DNSSEC configuration.
      operationId: getDomainDnssecConfig
      summary: Get DNSSEC configuration
      description: Returns DNSSEC configuration and keys for the specified domain.
      security:
        - bearerAuth: []
    put:
      tags:
        - Domain DNSSEC
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: DNSSEC configuration updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  config:
                    type: object
                    properties:
                      isDnssecEnabled:
                        type: boolean
                      autoRenew:
                        type: boolean
                      dnssecKeys:
                        type: array
                        items:
                          type: object
                          properties:
                            flags:
                              type: integer
                            protocol:
                              type: integer
                            alg:
                              type: integer
                            pubKey:
                              type: string
                    required:
                      - isDnssecEnabled
                      - autoRenew
                      - dnssecKeys
                required:
                  - config
        "400":
          description: Invalid request body or domain.
        "404":
          description: Domain not found.
        "422":
          description: DNSSEC not enabled or domain has no provider backend.
        "500":
          description: Failed to update DNSSEC configuration.
        "502":
          description: Failed to update at provider.
      operationId: updateDomainDnssecConfig
      summary: Update DNSSEC configuration
      description: Updates DNSSEC keys and settings at Openprovider and in the local
        database.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                keys:
                  type: array
                  items:
                    type: object
                    properties:
                      flags:
                        type: integer
                        enum:
                          - 256
                          - 257
                        description: 256 for ZSK, 257 for KSK
                      protocol:
                        type: integer
                        enum:
                          - 3
                        description: Always 3
                      alg:
                        type: integer
                        enum:
                          - 3
                          - 5
                          - 6
                          - 7
                          - 8
                          - 10
                          - 13
                        description: DNSSEC algorithm
                      pubKey:
                        type: string
                        description: Base64-encoded public key
                    required:
                      - flags
                      - protocol
                      - alg
                      - pubKey
                autoRenew:
                  type: boolean
                  description: Enable automatic key renewal
  /api/v1/spaces/assets/domains/{domain}/dnssec/sync:
    post:
      tags:
        - Domain DNSSEC
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: DNSSEC keys synced successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  config:
                    type: object
                    properties:
                      isDnssecEnabled:
                        type: boolean
                      autoRenew:
                        type: boolean
                      dnssecKeys:
                        type: array
                        items:
                          type: object
                          properties:
                            flags:
                              type: integer
                            protocol:
                              type: integer
                            alg:
                              type: integer
                            pubKey:
                              type: string
                    required:
                      - isDnssecEnabled
                      - autoRenew
                      - dnssecKeys
                required:
                  - config
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found.
        "422":
          description: Domain has no provider backend.
        "500":
          description: Failed to sync DNSSEC keys.
        "502":
          description: Failed to fetch from provider.
      operationId: syncDomainDnssecKeys
      summary: Sync DNSSEC keys from provider
      description: Fetches the current DNSSEC keys from Openprovider and updates the
        local database.
      security:
        - bearerAuth: []
  /api/v1/spaces/assets/domains/{domain}/easydmarc:
    get:
      tags:
        - API Routes
      parameters:
        - name: domain
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: OK
  /api/v1/spaces/assets/domains/{domain}/easydmarc/sso:
    post:
      tags:
        - API Routes
      parameters:
        - name: domain
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: OK
  /api/v1/spaces/assets/domains/{domain}/forwarding:
    delete:
      tags:
        - Domain Forwarding
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "204":
          description: Forwarding configuration deleted successfully
        "400":
          description: Invalid domain
        "401":
          description: Unauthenticated
        "404":
          description: Domain not found
      operationId: deleteDomainForwarding
      summary: Delete domain forwarding configuration
      description: Removes the URL forwarding configuration for a domain.
      security:
        - bearerAuth: []
    get:
      tags:
        - Domain Forwarding
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Forwarding configuration retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  forwarding:
                    type: object
                    nullable: true
                    properties:
                      id:
                        type: string
                        format: uuid
                      target_url:
                        type: string
                        format: uri
                      redirect_type:
                        type: integer
                        enum:
                          - 301
                          - 302
                      path_pattern:
                        type: string
                      preserve_path:
                        type: boolean
                      preserve_query_string:
                        type: boolean
                      is_active:
                        type: boolean
        "400":
          description: Invalid domain
        "401":
          description: Unauthenticated
        "404":
          description: Domain not found
      operationId: getDomainForwarding
      summary: Get domain forwarding configuration
      description: Retrieves the URL forwarding configuration for a domain.
      security:
        - bearerAuth: []
    put:
      tags:
        - Domain Forwarding
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Forwarding configuration updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  forwarding:
                    type: object
                    properties:
                      id:
                        type: string
                        format: uuid
                      target_url:
                        type: string
                        format: uri
                      redirect_type:
                        type: integer
                        enum:
                          - 301
                          - 302
                      path_pattern:
                        type: string
                      preserve_path:
                        type: boolean
                      preserve_query_string:
                        type: boolean
                      is_active:
                        type: boolean
        "400":
          description: Invalid request body
        "401":
          description: Unauthenticated
        "404":
          description: Domain not found
      operationId: updateDomainForwarding
      summary: Update domain forwarding configuration
      description: Creates or updates the URL forwarding configuration for a domain.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - target_url
                - redirect_type
              properties:
                target_url:
                  type: string
                  format: uri
                  description: The destination URL to redirect to
                redirect_type:
                  type: integer
                  enum:
                    - 301
                    - 302
                  description: HTTP redirect status code
                preserve_path:
                  type: boolean
                  default: true
                  description: Whether to append the original path to the target URL
                preserve_query_string:
                  type: boolean
                  default: true
                  description: Whether to preserve query parameters in the redirect
  /api/v1/spaces/assets/domains/{domain}:
    delete:
      tags:
        - Domains
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Domain terminated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  domain:
                    type: object
                    properties:
                      id:
                        type: string
                      domain_name:
                        type: string
                      extension:
                        type: string
                      status:
                        type: string
                      created_at:
                        type: string
                        format: date-time
                      expires_at:
                        type: string
                        format: date-time
                        nullable: true
                      auto_renew:
                        type: string
                        enum:
                          - on
                          - off
                          - default
                    required:
                      - id
                      - domain_name
                      - extension
                      - status
                      - created_at
                      - expires_at
                      - auto_renew
                    additionalProperties: false
                required:
                  - domain
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found.
        "500":
          description: Failed to terminate domain.
      operationId: terminateSpaceDomain
      summary: Terminate domain
      description: Removes a domain from the Space and marks it as terminated.
      security:
        - bearerAuth: []
    get:
      tags:
        - Domains
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Domain information returned.
          content:
            application/json:
              schema:
                type: object
                properties:
                  domain:
                    type: object
                    properties:
                      registryStatus:
                        type: string
                      registrationDate:
                        type: string
                        format: date-time
                      renewalDate:
                        type: string
                        format: date-time
                      cancelled:
                        type: boolean
                      autoRenew:
                        type: string
                        enum:
                          - on
                          - off
                          - default
                      isLocked:
                        type: boolean
                      isLockable:
                        type: boolean
                      emailVerified:
                        type: boolean
                      paymentPastDue:
                        type: boolean
                      isIncomingTransfer:
                        type: boolean
                      requestedAt:
                        type: string
                        format: date-time
                      spaceId:
                        type: string
                    required:
                      - registryStatus
                      - registrationDate
                      - renewalDate
                      - cancelled
                      - autoRenew
                      - isLocked
                      - isLockable
                    additionalProperties: false
                  targetSpace:
                    type: string
                    nullable: true
                    description: Space to select when the domain belongs to another accessible
                      Space.
                required:
                  - domain
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found.
        "500":
          description: Failed to load domain info.
      operationId: getSpaceDomain
      summary: Get domain details
      description: Fetches registry and lifecycle information for a specific domain.
      security:
        - bearerAuth: []
    put:
      tags:
        - Domains
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Registry synchronization requested successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  synchronized:
                    type: boolean
                required:
                  - synchronized
                additionalProperties: false
        "400":
          description: Invalid domain or request body.
        "401":
          description: Unauthenticated.
        "403":
          description: Domain is not accessible from this Space.
        "404":
          description: Domain not found.
        "422":
          description: Domain is not linked to the registry.
        "500":
          description: Failed to synchronize domain with registry.
      operationId: synchronizeSpaceDomainWithRegistry
      summary: Synchronize domain with registry
      description: Forces Openprovider to update the domain using the latest registry data.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                force_registry_update:
                  type: boolean
                  enum:
                    - true
              required:
                - force_registry_update
              additionalProperties: false
  /api/v1/spaces/assets/domains/{domain}/nameservers:
    get:
      tags:
        - Domain Nameservers
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Nameservers fetched successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  nameservers:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        ipv4:
                          type: string
                          nullable: true
                        ipv6:
                          type: string
                          nullable: true
                        seq_nr:
                          type: number
                      required:
                        - name
                        - seq_nr
                      additionalProperties: false
                required:
                  - nameservers
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found.
        "500":
          description: Failed to load nameservers.
      operationId: getDomainNameservers
      summary: Get domain nameservers
      description: Returns the current nameserver set for the domain.
      security:
        - bearerAuth: []
    post:
      tags:
        - Domain Nameservers
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Nameservers updated.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                required:
                  - success
        "400":
          description: Invalid request.
        "404":
          description: Domain not found.
        "422":
          description: DNSSEC must be disabled before switching to external nameservers,
            or the registrar rejected the nameserver set.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: boolean
                    enum:
                      - true
                  url:
                    type: string
                  statusCode:
                    type: integer
                    enum:
                      - 422
                  statusMessage:
                    type: string
                  message:
                    type: string
                required:
                  - error
                  - statusCode
                  - statusMessage
                  - message
              example:
                error: true
                statusCode: 422
                statusMessage: Disable DNSSEC and wait for the old DS records to expire before
                  switching to external nameservers.
                message: Disable DNSSEC and wait for the old DS records to expire before
                  switching to external nameservers.
        "500":
          description: Failed to update nameservers.
      operationId: updateDomainNameservers
      summary: Update domain nameservers
      description: Replaces the nameserver set for the domain with the provided list.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                nameservers:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                      ipv4:
                        type: string
                        nullable: true
                      ipv6:
                        type: string
                        nullable: true
                      seq_nr:
                        type: number
                        nullable: true
                    required:
                      - name
                    additionalProperties: false
              required:
                - nameservers
  /api/v1/spaces/assets/domains/{domain}/records/{recordId}:
    delete:
      tags:
        - Domain Records
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
        - in: path
          name: recordId
          required: true
          schema:
            type: string
          description: Identifier of the DNS record
      responses:
        "200":
          description: DNS record removed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                required:
                  - success
        "400":
          description: Invalid domain.
        "404":
          description: Domain or record not found.
        "500":
          description: Failed to delete record.
      operationId: deleteDomainRecord
      summary: Delete DNS record
      description: Removes a DNS resource record from the domain.
      security:
        - bearerAuth: []
    patch:
      tags:
        - Domain Records
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
        - in: path
          name: recordId
          required: true
          schema:
            type: string
          description: Identifier of the DNS record
      responses:
        "200":
          description: DNS record updated.
          content:
            application/json:
              schema:
                type: object
                properties:
                  record:
                    type: object
                    properties:
                      id:
                        type: string
                      type:
                        type: string
                      name:
                        type: string
                      value:
                        type: string
                      ttl:
                        type: number
                      priority:
                        type: number
                        nullable: true
                      comment:
                        type: string
                        nullable: true
                    required:
                      - id
                      - type
                      - name
                      - value
                      - ttl
                    additionalProperties: false
                required:
                  - record
        "400":
          description: Invalid request.
        "404":
          description: Domain or record not found.
        "500":
          description: Failed to update record.
      operationId: updateDomainRecord
      summary: Update DNS record
      description: Updates a specific DNS resource record on the domain.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                record:
                  type: object
                  properties:
                    type:
                      type: string
                    name:
                      type: string
                    value:
                      type: string
                    ttl:
                      type: number
                    priority:
                      type: number
                      nullable: true
                    comment:
                      type: string
                      nullable: true
                  required:
                    - type
                    - name
                    - value
                    - ttl
                  additionalProperties: false
              required:
                - record
  /api/v1/spaces/assets/domains/{domain}/records/default:
    get:
      tags:
        - Domain Records
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Records retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  records:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        type:
                          type: string
                        name:
                          type: string
                        value:
                          type: string
                        ttl:
                          type: number
                        priority:
                          type: number
                          nullable: true
                        comment:
                          type: string
                          nullable: true
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found.
        "500":
          description: Failed to load records.
      operationId: listDefaultZoneRecords
      summary: List default zone DNS records
      description: Returns all DNS resource records from the default (openprovider)
        zone for the specified domain. Used for previewing records before
        transferring to Sectigo zone.
      security:
        - bearerAuth: []
  /api/v1/spaces/assets/domains/{domain}/records:
    get:
      tags:
        - Domain Records
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: DNS records returned successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  records:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        type:
                          type: string
                        name:
                          type: string
                        value:
                          type: string
                        ttl:
                          type: number
                        priority:
                          type: number
                          nullable: true
                        comment:
                          type: string
                          nullable: true
                      required:
                        - id
                        - type
                        - name
                        - value
                        - ttl
                      additionalProperties: false
                required:
                  - records
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found.
        "500":
          description: Failed to load records.
      operationId: listDomainRecords
      summary: List DNS records
      description: Returns all DNS resource records for the specified domain.
      security:
        - bearerAuth: []
    post:
      tags:
        - Domain Records
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: DNS record created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  record:
                    type: object
                    properties:
                      id:
                        type: string
                      type:
                        type: string
                      name:
                        type: string
                      value:
                        type: string
                      ttl:
                        type: number
                      priority:
                        type: number
                        nullable: true
                      comment:
                        type: string
                        nullable: true
                    required:
                      - id
                      - type
                      - name
                      - value
                      - ttl
                    additionalProperties: false
                required:
                  - record
        "400":
          description: Invalid request.
        "404":
          description: Domain not found.
        "500":
          description: Failed to create record.
      operationId: createDomainRecord
      summary: Create DNS record
      description: Adds a new DNS resource record to the domain.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                record:
                  type: object
                  properties:
                    id:
                      type: string
                      nullable: true
                    type:
                      type: string
                    name:
                      type: string
                    value:
                      type: string
                    ttl:
                      type: number
                    priority:
                      type: number
                      nullable: true
                    comment:
                      type: string
                      nullable: true
                  required:
                    - type
                    - name
                    - value
                    - ttl
                  additionalProperties: false
              required:
                - record
  /api/v1/spaces/assets/domains/{domain}/records/transfer:
    post:
      tags:
        - Domain Records
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Records transferred successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  transferred:
                    type: number
                  errors:
                    type: array
                    items:
                      type: string
                  message:
                    type: string
        "400":
          description: Invalid domain, no records selected, or Premium DNS not enabled.
        "404":
          description: Domain not found.
        "500":
          description: Failed to transfer records.
      operationId: transferRecordsToSectigo
      summary: Transfer records to Sectigo zone
      description: Transfers DNS records from the default (openprovider) zone to the
        Sectigo zone. Requires Premium DNS addon to be enabled. Existing records
        in the Sectigo zone will be replaced.
      security:
        - bearerAuth: []
      requestBody:
        description: Optional selection of specific records to transfer
        content:
          application/json:
            schema:
              type: object
              properties:
                selectedRecordIds:
                  type: array
                  items:
                    type: string
                  description: Array of record IDs to transfer. If not provided, all records are
                    transferred.
  /api/v1/spaces/assets/domains/{domain}/renewals:
    post:
      tags:
        - Domains
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Domain renewed successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  info:
                    type: object
                    properties:
                      registryStatus:
                        type: string
                      registrationDate:
                        type: string
                        format: date-time
                      renewalDate:
                        type: string
                        format: date-time
                      cancelled:
                        type: boolean
                    required:
                      - registryStatus
                      - registrationDate
                      - renewalDate
                      - cancelled
                    additionalProperties: false
                required:
                  - info
        "400":
          description: Invalid request.
        "404":
          description: Domain not found.
        "500":
          description: Failed to renew domain.
      operationId: renewSpaceDomain
      summary: Renew domain registration
      description: Extends the registration period of a domain by the specified number
        of years.
      security:
        - bearerAuth: []
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                years:
                  type: integer
                  minimum: 1
                  description: Number of years to extend (default 1)
  /api/v1/spaces/assets/domains/{domain}/renewals/pause:
    post:
      tags:
        - Domains
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Domain renewal paused successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: Indicates if the operation was successful
      operationId: pauseSpaceDomainRenewal
      summary: Pause domain renewal
      description: Pauses the automatic renewal of a domain within the Space.
      security:
        - bearerAuth: []
  /api/v1/spaces/assets/domains/{domain}/restore:
    post:
      tags:
        - Domains
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Domain restored successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  domain:
                    type: object
                    properties:
                      id:
                        type: string
                      domain_name:
                        type: string
                      extension:
                        type: string
                      status:
                        type: string
                      created_at:
                        type: string
                        format: date-time
                      expires_at:
                        type: string
                        format: date-time
                        nullable: true
                      auto_renew:
                        type: string
                        enum:
                          - on
                          - off
                          - default
                    required:
                      - id
                      - domain_name
                      - extension
                      - status
                      - created_at
                      - expires_at
                      - auto_renew
                    additionalProperties: false
                required:
                  - domain
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found or not terminated.
        "500":
          description: Failed to restore domain.
      operationId: restoreSpaceDomain
      summary: Restore terminated domain
      description: Reactivates a previously terminated domain within the Space.
      security:
        - bearerAuth: []
  /api/v1/spaces/assets/domains/{domain}/unlocks:
    post:
      tags:
        - Domains
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Auth code returned.
          content:
            application/json:
              schema:
                type: object
                properties:
                  authCode:
                    type: string
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        domain:
                          type: string
                        authCode:
                          type: string
                      required:
                        - domain
                        - authCode
        "400":
          description: Invalid domain.
        "401":
          description: Unauthenticated.
        "404":
          description: Domain not found.
        "500":
          description: Failed to unlock domain for transfer.
      operationId: unlockSpaceDomain
      summary: Unlock domain and return auth code
      description: Unlocks one or more domains for transfer in Openprovider and
        retrieves auth codes.
      security:
        - bearerAuth: []
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                relock:
                  type: boolean
                  description: Relock domains instead of unlocking
                domains:
                  type: array
                  items:
                    type: string
                  description: Optional list of domains to unlock in bulk (must include the path
                    domain).
  /api/v1/spaces/assets/domains/{domain}/unlocks/refresh:
    post:
      tags:
        - Domains
      parameters:
        - in: path
          name: domain
          required: true
          schema:
            type: string
          description: Domain name in FQDN format
      responses:
        "200":
          description: Domain auth code refreshed successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  authCode:
                    type: string
                    description: The refreshed authorization code for the domain
                required:
                  - authCode
        "400":
          description: Invalid domain.
        "404":
          description: Domain not found.
        "500":
          description: Failed to refresh domain auth code.
      operationId: refreshSpaceDomainAuthCode
      summary: Refresh domain auth code
      description: Refreshes the auth code for a domain in Openprovider.
      security:
        - bearerAuth: []
  /api/v1/spaces/assets/domains:
    get:
      tags:
        - Domains
      parameters: []
      responses:
        "200":
          description: Domain list loaded successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  domains:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        domain_name:
                          type: string
                        extension:
                          type: string
                        status:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                          format: date-time
                        expires_at:
                          type: string
                          format: date-time
                          nullable: true
                        auto_renew:
                          type: string
                          enum:
                            - on
                            - off
                            - default
                      required:
                        - id
                        - domain_name
                        - extension
                        - status
                        - created_at
                        - expires_at
                        - auto_renew
                      additionalProperties: false
                required:
                  - domains
        "401":
          description: Unauthenticated.
        "500":
          description: Failed to load domains.
      operationId: listSpaceDomains
      summary: List domains in current Space
      description: Returns all domains associated with the authenticated Space from
        the domains schema.
      security:
        - bearerAuth: []
  /api/v1/spaces/assets/licenses/addons:
    get:
      tags:
        - Space Licenses
      parameters:
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
          description: UUID of the space to query.
        - in: query
          name: spaceSlug
          required: false
          deprecated: true
          schema:
            type: string
          description: Legacy slug of the space.
      responses:
        "200":
          description: Addon information retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  active:
                    type: array
                    items:
                      type: object
                      properties:
                        slug:
                          type: string
                        priceMonthly:
                          type: number
                        priceAnnually:
                          type: number
                        expiresAt:
                          type: string
                          format: date
                      required:
                        - slug
                        - priceMonthly
                        - priceAnnually
                        - expiresAt
                  available:
                    type: array
                    items:
                      type: object
                      properties:
                        slug:
                          type: string
                        priceMonthly:
                          type: number
                        priceAnnually:
                          type: number
                      required:
                        - slug
                        - priceMonthly
                        - priceAnnually
                required:
                  - active
                  - available
        "400":
          description: Invalid space identifier.
        "500":
          description: Failed to fetch addons.
      operationId: listLicenseAddons
      summary: List addons for a space
      description: Returns active and available addons for the given space.
      security:
        - bearerAuth: []
    patch:
      tags:
        - Space Licenses
      parameters: []
      responses:
        "200":
          description: Addon scheduled for removal.
          content:
            application/json:
              schema:
                type: object
                properties:
                  addon:
                    type: object
                    properties:
                      slug:
                        type: string
                      priceMonthly:
                        type: number
                      priceAnnually:
                        type: number
                      expiresAt:
                        type: string
                        format: date
                    required:
                      - slug
                      - priceMonthly
                      - priceAnnually
                      - expiresAt
                required:
                  - addon
        "400":
          description: Invalid space identifier or addon slug.
        "500":
          description: Failed to disable addon.
      operationId: disableLicenseAddon
      summary: Disable addon
      description: Marks an addon to be removed when the current billing period ends.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                spaceId:
                  type: string
                  format: uuid
                spaceSlug:
                  type: string
                  deprecated: true
                slug:
                  type: string
              required:
                - spaceId
                - slug
            examples:
              example:
                summary: Disable statistics addon
                value:
                  spaceId: b5d8940d-53fc-4c8d-aafa-9e6f8a4ad65e
                  slug: stats
    post:
      tags:
        - Space Licenses
      parameters: []
      responses:
        "201":
          description: Addon purchase queued for next billing cycle.
          content:
            application/json:
              schema:
                type: object
                properties:
                  addon:
                    type: object
                    properties:
                      slug:
                        type: string
                      priceMonthly:
                        type: number
                      priceAnnually:
                        type: number
                      expiresAt:
                        type: string
                        format: date
                    required:
                      - slug
                      - priceMonthly
                      - priceAnnually
                      - expiresAt
                required:
                  - addon
        "400":
          description: Invalid space identifier or addon slug.
        "500":
          description: Failed to purchase addon.
      operationId: purchaseLicenseAddon
      summary: Purchase addon
      description: Adds a new addon to the space starting with the next billing cycle.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                spaceId:
                  type: string
                  format: uuid
                spaceSlug:
                  type: string
                  deprecated: true
                slug:
                  type: string
              required:
                - spaceId
                - slug
            examples:
              example:
                summary: Buy statistics addon
                value:
                  spaceId: b5d8940d-53fc-4c8d-aafa-9e6f8a4ad65e
                  slug: stats
  /api/v1/spaces/assets/licenses:
    get:
      tags:
        - Space Licenses
      parameters:
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
          description: UUID of the space (preferred identifier).
        - in: query
          name: spaceSlug
          required: false
          deprecated: true
          schema:
            type: string
          description: Legacy slug of the space. Prefer using spaceId.
      responses:
        "200":
          description: Licensing details for the space.
          content:
            application/json:
              schema:
                type: object
                properties:
                  products:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        currentPlan:
                          type: string
                          enum:
                            - Startup
                            - Business
                            - Enterprise
                        currentBillingCycle:
                          type: string
                          enum:
                            - Monthly
                            - Annual
                        nextBillingDate:
                          type: string
                          format: date
                        totalSeats:
                          type: integer
                        seatsData:
                          type: array
                          items:
                            type: object
                            properties:
                              user:
                                type: string
                                format: email
                              role:
                                type: string
                            required:
                              - user
                              - role
                        activeAddons:
                          type: array
                          items:
                            type: object
                            properties:
                              slug:
                                type: string
                              priceMonthly:
                                type: number
                              priceAnnually:
                                type: number
                            required:
                              - slug
                              - priceMonthly
                              - priceAnnually
                        availableAddons:
                          type: array
                          items:
                            type: object
                            properties:
                              slug:
                                type: string
                              priceMonthly:
                                type: number
                              priceAnnually:
                                type: number
                            required:
                              - slug
                              - priceMonthly
                              - priceAnnually
                        selectedPlan:
                          type: string
                          enum:
                            - Startup
                            - Business
                            - Enterprise
                        selectedBillingCycle:
                          type: string
                          enum:
                            - Monthly
                            - Annual
                        billingMode:
                          type: string
                          enum:
                            - seat-based
                            - usage-based
                      required:
                        - name
                        - currentPlan
                        - currentBillingCycle
                        - nextBillingDate
                        - totalSeats
                        - seatsData
                        - activeAddons
                        - availableAddons
                        - selectedPlan
                        - selectedBillingCycle
                        - billingMode
                required:
                  - products
        "400":
          description: Invalid space identifier.
        "500":
          description: Failed to fetch licenses.
      operationId: getSpaceLicenses
      summary: List Space licenses
      description: Returns current products, seat assignments and available addons for
        the specified space.
      security:
        - bearerAuth: []
  /api/v1/spaces/assets/licenses/plans:
    get:
      tags:
        - Space Licenses
      parameters:
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
          description: UUID of the space to query.
        - in: query
          name: spaceSlug
          required: false
          deprecated: true
          schema:
            type: string
          description: Legacy slug of the space. Prefer using spaceId.
      responses:
        "200":
          description: Plan options retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  plans:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          enum:
                            - Startup
                            - Business
                            - Enterprise
                        description:
                          type: string
                        priceMonthly:
                          type: number
                        priceAnnually:
                          type: number
                      required:
                        - name
                        - description
                        - priceMonthly
                        - priceAnnually
                required:
                  - plans
        "400":
          description: Invalid space identifier.
        "500":
          description: Failed to fetch plans.
      operationId: getLicensePlans
      summary: List available license plans
      description: Returns available subscription plans that can be applied to the space.
      security:
        - bearerAuth: []
    patch:
      tags:
        - Space Licenses
      parameters: []
      responses:
        "200":
          description: Plan updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  plan:
                    type: string
                    enum:
                      - Startup
                      - Business
                      - Enterprise
                  billingCycle:
                    type: string
                    enum:
                      - Monthly
                      - Annual
                required:
                  - plan
                  - billingCycle
        "400":
          description: Invalid space identifier or missing plan data.
        "500":
          description: Failed to update plan.
      operationId: updateLicensePlan
      summary: Update selected plan
      description: Changes the plan and billing cycle for the provided space. Takes
        effect immediately.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                spaceId:
                  type: string
                  format: uuid
                spaceSlug:
                  type: string
                  deprecated: true
                plan:
                  type: string
                  enum:
                    - Startup
                    - Business
                    - Enterprise
                billingCycle:
                  type: string
                  enum:
                    - Monthly
                    - Annual
              required:
                - spaceId
                - plan
                - billingCycle
            examples:
              example:
                summary: Downgrade to Startup annually
                value:
                  spaceId: b5d8940d-53fc-4c8d-aafa-9e6f8a4ad65e
                  plan: Startup
                  billingCycle: Annual
  /api/v1/spaces/assets/licenses/seats/increase:
    post:
      tags:
        - Space Licenses
      parameters: []
      responses:
        "200":
          description: Seat allocation increased successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  totalSeats:
                    type: integer
                required:
                  - totalSeats
        "400":
          description: Invalid space identifier or increase amount.
        "500":
          description: Failed to increase seats.
      operationId: increaseLicenseSeats
      summary: Increase seat count
      description: Adds additional seats to the purchased allocation for a space.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                spaceId:
                  type: string
                  format: uuid
                spaceSlug:
                  type: string
                  deprecated: true
                amount:
                  type: integer
                  minimum: 1
                currentTotal:
                  type: integer
                  minimum: 0
              required:
                - spaceId
                - amount
            examples:
              example:
                summary: Increase seats by 5
                value:
                  spaceId: b5d8940d-53fc-4c8d-aafa-9e6f8a4ad65e
                  amount: 5
                  currentTotal: 10
  /api/v1/spaces/assets/licenses/seats:
    delete:
      tags:
        - Space Licenses
      parameters: []
      responses:
        "204":
          description: Seat removed.
        "400":
          description: Invalid space identifier or seat id.
        "500":
          description: Failed to remove seat.
      operationId: removeLicenseSeat
      summary: Remove a seat from a space
      description: Deletes a seat assignment from the space.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                spaceId:
                  type: string
                  format: uuid
                spaceSlug:
                  type: string
                  deprecated: true
                id:
                  type: integer
              required:
                - spaceId
                - id
            examples:
              example:
                summary: Remove seat 42
                value:
                  spaceId: b5d8940d-53fc-4c8d-aafa-9e6f8a4ad65e
                  id: 42
    get:
      tags:
        - Space Licenses
      parameters:
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
          description: UUID of the space.
        - in: query
          name: spaceSlug
          required: false
          deprecated: true
          schema:
            type: string
          description: Legacy slug of the space.
        - in: query
          name: page
          required: false
          schema:
            type: integer
            minimum: 1
          description: Page number (>= 1).
        - in: query
          name: pageSize
          required: false
          schema:
            type: integer
            minimum: 1
          description: Number of seats per page.
      responses:
        "200":
          description: Seat list retrieved successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  seats:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        email:
                          type: string
                          format: email
                        role:
                          type: string
                      required:
                        - id
                        - email
                        - role
                  total:
                    type: integer
                required:
                  - seats
                  - total
        "400":
          description: Invalid space identifier or pagination values.
        "500":
          description: Failed to fetch seats.
      operationId: listLicenseSeats
      summary: List seats for a space
      description: Returns a paginated list of seat assignments for the specified space.
      security:
        - bearerAuth: []
    patch:
      tags:
        - Space Licenses
      parameters: []
      responses:
        "200":
          description: Seat updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  role:
                    type: string
                required:
                  - id
                  - role
        "400":
          description: Invalid space identifier or seat payload.
        "500":
          description: Failed to update seat.
      operationId: updateLicenseSeat
      summary: Update seat role
      description: Changes the role of an existing seat in the space.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                spaceId:
                  type: string
                  format: uuid
                spaceSlug:
                  type: string
                  deprecated: true
                id:
                  type: integer
                role:
                  type: string
              required:
                - spaceId
                - id
                - role
            examples:
              example:
                summary: Promote user to admin
                value:
                  spaceId: b5d8940d-53fc-4c8d-aafa-9e6f8a4ad65e
                  id: 5
                  role: Admin
    post:
      tags:
        - Space Licenses
      parameters: []
      responses:
        "201":
          description: Seats added successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  seats:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        email:
                          type: string
                          format: email
                        role:
                          type: string
                      required:
                        - id
                        - email
                        - role
                required:
                  - seats
        "400":
          description: Invalid space identifier or seats payload.
        "500":
          description: Failed to add seats.
      operationId: addLicenseSeats
      summary: Add seats to a space
      description: Creates seat assignments for users within the specified space.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                spaceId:
                  type: string
                  format: uuid
                spaceSlug:
                  type: string
                  deprecated: true
                seats:
                  type: array
                  items:
                    type: object
                    properties:
                      user:
                        type: string
                        format: email
                      role:
                        type: string
                    required:
                      - user
                      - role
                  minItems: 1
              required:
                - spaceId
                - seats
            examples:
              example:
                summary: Add two members
                value:
                  spaceId: b5d8940d-53fc-4c8d-aafa-9e6f8a4ad65e
                  seats:
                    - user: alice@example.com
                      role: Admin
                    - user: bob@example.com
                      role: Member
  /api/v1/spaces/audit-logs:
    get:
      tags:
        - Space Audit Logs
      parameters:
        - in: query
          name: space_id
          required: true
          schema:
            type: string
            format: uuid
          description: Space identifier.
        - in: query
          name: limit
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 25
          description: Maximum number of items to return.
        - in: query
          name: offset
          required: false
          schema:
            type: integer
            minimum: 0
            default: 0
          description: Offset for pagination.
        - in: query
          name: category
          required: false
          schema:
            type: string
            enum:
              - domains
              - certificates
              - billing
              - spaces
              - security
          description: Filter by audit category.
        - in: query
          name: audit_status
          required: false
          schema:
            type: string
            enum:
              - success
              - failed
              - pending
          description: Filter by audit status.
        - in: query
          name: action
          required: false
          schema:
            type: string
          description: Filter by exact action string.
        - in: query
          name: from
          required: false
          schema:
            type: string
            format: date-time
          description: ISO timestamp for the earliest event to include.
        - in: query
          name: to
          required: false
          schema:
            type: string
            format: date-time
          description: ISO timestamp for the latest event to include.
        - in: query
          name: search
          required: false
          schema:
            type: string
          description: Search string applied to actor, action, and resource fields.
      responses:
        "200":
          description: Audit logs for the requested space.
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        space_id:
                          type: string
                        actor:
                          type: string
                        action:
                          type: string
                        category:
                          type: string
                        audit_status:
                          type: string
                        resource:
                          type: string
                        occurred_at:
                          type: string
                          format: date-time
                        metadata:
                          type: object
                          additionalProperties: true
                        source:
                          type: object
                          additionalProperties: true
                  nextCursor:
                    type: string
                    nullable: true
                  total:
                    type: integer
                    nullable: true
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthenticated.
        "500":
          description: Server error.
      operationId: listSpaceAuditLogs
      summary: List Space audit logs
      description: Returns audit log entries for the specified space. Requires owner
        or admin permissions enforced via RLS.
      security:
        - bearerAuth: []
  /api/v1/spaces:
    post:
      tags:
        - Space Actions
      parameters: []
      responses:
        "200":
          description: Space created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  spaceSlug:
                    type: string
                  spaceId:
                    type: string
                    format: uuid
        "400":
          description: Validation error (name, slug, email, etc.).
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden – userId mismatch.
        "409":
          description: Slug already in use.
        "500":
          description: Server error while creating Space or membership.
      operationId: createSpace
      summary: Create new Space
      description: Creates a Space and an initial membership for the authenticated
        user. Name must be 3–80 characters without URL-forming punctuation. Slug
        must be 4–50 chars (lowercase letters, numbers, hyphens). `type` must be
        `personal` or `business`.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - userId
                - userFirstName
                - userLastName
                - userEmail
              properties:
                userId:
                  type: string
                  format: uuid
                  description: Authenticated user ID (must match token subject).
                userFirstName:
                  type: string
                userLastName:
                  type: string
                userEmail:
                  type: string
                  format: email
                name:
                  type: string
                  description: Space name, 3–80 characters without URL-forming punctuation.
                slug:
                  type: string
                  description: Space slug, 4–50 chars; lowercase letters, numbers, hyphens.
                country:
                  type: string
                  description: Optional ISO-3166-1 alpha-2 code (e.g., DE, US).
                contact_email:
                  type: string
                  format: email
                  description: Overrides contact email; defaults to userEmail.
                type:
                  type: string
                  enum:
                    - personal
                    - business
                  default: personal
                business_name:
                  type: string
                  description: Required if `type` is `business`; 5–100 chars.
            examples:
              personal:
                value:
                  userId: 4e6f9c2a-9a0d-43b2-9c2d-1f6b8f2a0a11
                  userFirstName: Alex
                  userLastName: Doe
                  userEmail: alex@example.com
                  name: Alex Personal Space
                  slug: alex-doe-space
                  country: DE
                  type: personal
              business:
                value:
                  userId: 4e6f9c2a-9a0d-43b2-9c2d-1f6b8f2a0a11
                  userFirstName: Alex
                  userLastName: Doe
                  userEmail: alex@example.com
                  name: Dashio GmbH
                  slug: dashio
                  country: DE
                  contact_email: ops@dashio.net
                  type: business
                  business_name: Dashio GmbH
  /api/v1/spaces/members:
    delete:
      tags:
        - Space Members
      parameters: []
      responses:
        "200":
          description: Member removed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                required:
                  - success
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden — insufficient role or self-removal.
        "404":
          description: Member not found.
        "409":
          description: Cannot remove last owner.
        "500":
          description: Server error.
      operationId: deleteSpaceMember
      summary: Remove member from Space
      description: Removes a member from a Space. Only `owner` or `admin` may remove
        members; only an `owner` may remove another `owner`.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - memberId
              properties:
                spaceId:
                  type: string
                  format: uuid
                  description: Space ID.
                memberId:
                  type: string
                  format: uuid
                  description: Membership row ID.
    get:
      tags:
        - Space Members
      parameters:
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
          description: Space ID.
      responses:
        "200":
          description: Members for the given Space.
          content:
            application/json:
              schema:
                type: object
                properties:
                  members:
                    type: array
                    items:
                      type: object
                      description: A row from the `member_details` view.
                      properties:
                        id:
                          type: string
                        space_id:
                          type: string
                          format: uuid
                        user_id:
                          type: string
                          format: uuid
                        email:
                          type: string
                          format: email
                        first_name:
                          type: string
                        last_name:
                          type: string
                        role:
                          type: string
                          description: owner | admin | member
                        created_at:
                          type: string
                          format: date-time
        "400":
          description: Invalid parameters.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden — insufficient role.
        "500":
          description: Server error.
      operationId: getSpaceMembers
      summary: List members of Space
      description: Returns all members from the `member_details` view. Only `owner` or
        `admin` may list members.
      security:
        - bearerAuth: []
    post:
      tags:
        - Space Members
      parameters: []
      responses:
        "200":
          description: User added as member.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden — insufficient role.
        "404":
          description: User not found by email.
        "409":
          description: User already a member of Space.
        "500":
          description: Server error.
      operationId: addSpaceMember
      summary: Add existing user to Space
      description: Adds an existing user (looked up by email) to a Space with role
        `member`. Only `owner` or `admin` may invite. Email must be valid, IDs
        must be UUID strings.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - email
              properties:
                spaceId:
                  type: string
                  format: uuid
                  description: Space ID.
                email:
                  type: string
                  format: email
                  description: User email to invite.
            examples:
              invite:
                value:
                  spaceId: 3b2b0c5b-9e2f-4c6f-8a4e-1c2d3e4f5a6b
                  email: teammate@example.com
    put:
      tags:
        - Space Members
      parameters: []
      responses:
        "200":
          description: Member role updated.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
        "400":
          description: Invalid request parameters or invalid ownership transfer target.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden — insufficient role or attempted owner assignment by
            non-owner.
        "404":
          description: Member not found.
        "409":
          description: Ownership transfer required or invalid owner count.
        "500":
          description: Server error.
      operationId: updateSpaceMemberRole
      summary: Update member role in Space
      description: Updates the role to one of `owner`, `admin`, or `member`. Only
        `owner` or `admin` may update roles; only an `owner` may assign the
        `owner` role. Admins may update members but cannot modify admin/owner
        memberships. Ownership transfer is explicit and keeps exactly one owner.
        IDs must be UUID strings.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - memberId
                - role
              properties:
                spaceId:
                  type: string
                  format: uuid
                  description: Space ID.
                memberId:
                  type: string
                  description: Membership row ID.
                role:
                  type: string
                  enum:
                    - owner
                    - admin
                    - member
                  description: New role to assign.
  /api/v1/spaces/members/invitations:
    delete:
      tags:
        - Space Member Invitations
      parameters:
        - name: spaceId
          in: query
          required: true
          schema:
            type: string
            format: uuid
        - name: invitationId
          in: query
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Invitation cancelled.
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden.
        "500":
          description: Server error.
      operationId: cancelSpaceInvitation
      summary: Cancel pending invitation
      description: Marks a pending invitation as cancelled. Only owners and admins may
        cancel invitations for their Space.
      security:
        - bearerAuth: []
    get:
      tags:
        - Space Member Invitations
      parameters:
        - name: spaceId
          in: query
          required: true
          schema:
            type: string
            format: uuid
          description: Space ID to list invitations for.
      responses:
        "200":
          description: List of invitations.
          content:
            application/json:
              schema:
                type: object
                properties:
                  invitations:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                        space_id:
                          type: string
                          format: uuid
                        invited_email:
                          type: string
                          format: email
                        role:
                          type: string
                          enum:
                            - admin
                            - member
                        status:
                          type: string
                          enum:
                            - pending
                            - accepted
                            - cancelled
                            - expired
                        created_at:
                          type: string
                          format: date-time
                        expires_at:
                          type: string
                          format: date-time
        "400":
          description: Invalid spaceId.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden.
        "500":
          description: Server error.
      operationId: listSpaceInvitations
      summary: List pending Space invitations
      description: Returns pending, non-expired invitations for a given Space. Only
        owners and admins may access this list.
      security:
        - bearerAuth: []
    post:
      tags:
        - Space Member Invitations
      parameters: []
      responses:
        "200":
          description: Invitation created or refreshed.
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden.
        "404":
          description: Space not found.
        "409":
          description: User already member of Space.
        "500":
          description: Server error.
      operationId: createSpaceInvitation
      summary: Add pending Space invitation
      description: Allows owners or admins to invite a user by email to join a Space.
        Invitations last for 7 days.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - email
                - firstName
                - lastName
              properties:
                spaceId:
                  type: string
                  format: uuid
                email:
                  type: string
                  format: email
                role:
                  type: string
                  enum:
                    - admin
                    - member
                  default: member
                firstName:
                  type: string
                  description: First name of the invitee to prefill sign-up.
                lastName:
                  type: string
                  description: Last name of the invitee to prefill sign-up.
            examples:
              invite:
                value:
                  spaceId: 3b2b0c5b-9e2f-4c6f-8a4e-1c2d3e4f5a6b
                  email: teammate@example.com
                  role: member
  /api/v1/spaces/members/invitations/mine:
    get:
      tags:
        - Space Member Invitations
      parameters: []
      responses:
        "200":
          description: Invitations for the user.
          content:
            application/json:
              schema:
                type: object
                properties:
                  invitations:
                    type: array
                    items:
                      type: object
                      properties:
                        invitation_id:
                          type: string
                          format: uuid
                        space_id:
                          type: string
                          format: uuid
                        space_name:
                          type: string
                        space_slug:
                          type: string
                        role:
                          type: string
                          enum:
                            - admin
                            - member
                        invited_email:
                          type: string
                          format: email
                        expires_at:
                          type: string
                          format: date-time
                        created_at:
                          type: string
                          format: date-time
        "401":
          description: Unauthenticated.
        "500":
          description: Server error.
      operationId: listMyInvitations
      summary: List current user invitations
      description: Returns pending, non-expired invitations for the authenticated user.
      security:
        - bearerAuth: []
  /api/v1/spaces/members/invitations/respond:
    post:
      tags:
        - Space Member Invitations
      parameters: []
      responses:
        "200":
          description: Invitation handled.
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthenticated.
        "403":
          description: Invitation does not belong to user.
        "404":
          description: Invitation not found or expired.
        "500":
          description: Server error.
      operationId: respondToInvitation
      summary: Respond to Space invitations
      description: Allows the invited user to accept or decline a pending invitation
        using its token.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: []
              properties:
                token:
                  type: string
                  description: Invitation token.
                invitationId:
                  type: string
                  format: uuid
                  description: Invitation ID.
                action:
                  type: string
                  enum:
                    - accept
                    - decline
                  default: accept
  /api/v1/spaces/settings/rename:
    patch:
      tags:
        - Space Settings
      parameters: []
      responses:
        "200":
          description: Space name updated successfully.
          content:
            application/json:
              schema:
                type: object
                required:
                  - success
                properties:
                  success:
                    type: boolean
                    example: true
              examples:
                success:
                  value:
                    success: true
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden — caller is not owner/admin or userId mismatch.
        "500":
          description: Failed to update Space name.
      operationId: renameSpace
      summary: Rename Space
      description: Updates the display name of a Space. Caller must be authenticated
        and a member of the Space with role **owner** or **admin**. The `name`
        must pass the shared server-side Space name validation.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - userId
                - name
              properties:
                spaceId:
                  type: string
                  format: uuid
                  description: Space ID (UUID).
                userId:
                  type: string
                  format: uuid
                  description: Authenticated user ID (UUID); must match the caller.
                name:
                  type: string
                  description: New Space name. 3–80 characters; URL-forming punctuation is not
                    allowed.
                  example: Marketing Team - EU
            examples:
              valid:
                value:
                  spaceId: 1c2b3a4d-5e6f-7081-92a3-b4c5d6e7f801
                  userId: 9f8e7d6c-5b4a-3210-9a87-6543210fedcb
                  name: Dashio Core Platform
  /api/v1/spaces/settings/slug:
    patch:
      tags:
        - Space Settings
      parameters: []
      responses:
        "200":
          description: Space slug updated successfully.
          content:
            application/json:
              schema:
                type: object
                required:
                  - success
                properties:
                  success:
                    type: boolean
                    example: true
              examples:
                success:
                  value:
                    success: true
        "400":
          description: Invalid request parameters.
        "401":
          description: Unauthenticated.
        "403":
          description: Forbidden — caller is not owner/admin or userId mismatch.
        "409":
          description: Slug already in use.
        "500":
          description: Failed to update Space slug.
      operationId: updateSpaceSlug
      summary: Update Space slug
      description: Updates the slug of a Space. Caller must be authenticated and a
        member of the Space with role **owner** or **admin**. The `slug` must be
        4–50 characters, lowercase letters/numbers/hyphens only.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - userId
                - slug
              properties:
                spaceId:
                  type: string
                  format: uuid
                  description: Space ID (UUID).
                userId:
                  type: string
                  format: uuid
                  description: Authenticated user ID (UUID); must match the caller.
                slug:
                  type: string
                  description: "New Space slug. 4–50 characters; allowed: lowercase letters,
                    numbers, hyphens."
                  example: marketing-team
            examples:
              valid:
                value:
                  spaceId: 1c2b3a4d-5e6f-7081-92a3-b4c5d6e7f801
                  userId: 9f8e7d6c-5b4a-3210-9a87-6543210fedcb
                  slug: dashio-core
  /api/v1/spaces/settings/verified-domains:
    get:
      tags:
        - Space Settings
      parameters:
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
          description: ID of the Space whose domains should be listed.
      responses:
        "200":
          description: List of domains for the given Space.
          content:
            application/json:
              schema:
                type: object
                properties:
                  domains:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          description: Domain name.
                        status:
                          type: string
                          enum:
                            - verified
                            - pending
                            - expired
                          description: Verification status of the domain.
                        code:
                          type: string
                          description: TXT record code for verification.
                        expiresAt:
                          type: integer
                          description: Expiration timestamp (epoch ms).
        "400":
          description: Missing or invalid spaceId parameter.
      operationId: getVerifiedDomains
      summary: List verified domains
      description: Returns a list of domains added for verification in the given
        Space. Each domain includes its name, verification status (`verified`,
        `pending`, or `expired`), the DNS TXT record code, and the expiration
        timestamp.
    post:
      tags:
        - Space Settings
      parameters: []
      responses:
        "200":
          description: Domain verification entry created.
          content:
            application/json:
              schema:
                type: object
                properties:
                  domain:
                    type: object
                    properties:
                      name:
                        type: string
                      code:
                        type: string
                      expiresAt:
                        type: integer
                      status:
                        type: string
                        enum:
                          - verified
                          - pending
        "400":
          description: Invalid parameters provided.
      operationId: addVerifiedDomain
      summary: Add domain verification
      description: Adds a domain to a Space for verification. Generates a DNS TXT
        record code and stores it until the verification expires or completes.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - spaceSlug
                - name
              properties:
                spaceId:
                  type: string
                  format: uuid
                  description: Space ID (UUID).
                spaceSlug:
                  type: string
                  description: Slug of the Space.
                name:
                  type: string
                  description: Domain name to verify.
            examples:
              valid:
                value:
                  spaceId: 1c2b3a4d-5e6f-7081-92a3-b4c5d6e7f801
                  spaceSlug: marketing-team
                  name: dashio.net
  /api/v1/spaces/settings/verified-domains/remove:
    post:
      tags:
        - Space Settings
      parameters: []
      responses:
        "200":
          description: Domain verification entry removed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
        "400":
          description: Invalid parameters provided.
      operationId: removeVerifiedDomain
      summary: Remove domain verification
      description: Removes a domain verification record from a Space. This does not
        affect DNS; it only removes the verification state from the database.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - name
              properties:
                spaceId:
                  type: string
                  format: uuid
                  description: Space ID (UUID).
                name:
                  type: string
                  description: Domain name to remove from verification.
  /api/v1/spaces/settings/verified-domains/verify:
    post:
      tags:
        - Space Settings
      parameters: []
      responses:
        "200":
          description: Verification result.
          content:
            application/json:
              schema:
                type: object
                properties:
                  verified:
                    type: boolean
                    description: Whether the domain is verified.
              examples:
                success:
                  value:
                    verified: true
                failed:
                  value:
                    verified: false
        "400":
          description: Invalid parameters provided.
      operationId: verifyDomain
      summary: Verify domain via TXT record
      description: Checks the DNS TXT record for a given domain in a Space. If the TXT
        record matches the stored code, the domain is marked as verified.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - spaceId
                - name
              properties:
                spaceId:
                  type: string
                  format: uuid
                  description: Space ID (UUID).
                name:
                  type: string
                  description: Domain name to verify.
  /api/v1/spaces/stats:
    get:
      tags:
        - Space Actions
      parameters:
        - in: query
          name: spaceId
          required: true
          schema:
            type: string
            format: uuid
          description: Space UUID.
        - in: query
          name: showYearlyTotal
          required: false
          schema:
            type: string
            enum:
              - "true"
              - "false"
              - "1"
              - "0"
          description: If true, displays total yearly payment instead of next payment
            amount (for testing).
      responses:
        "200":
          description: Statistics for the given Space.
          content:
            application/json:
              schema:
                type: object
                properties:
                  stats:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        value:
                          type: string
                        icon:
                          type: string
                          description: Icon identifier.
                        comment:
                          type: string
                          description: Optional comment.
        "400":
          description: Invalid `spaceSlug`.
      operationId: getSpaceStats
      summary: Get Space statistics
      description: Returns billing and resource statistics for a Space. Use
        `showYearlyTotal=true` to display total yearly payment projection
        instead of next payment amount.
  /api/v1/support/contact:
    post:
      tags:
        - Contact
      parameters: []
      responses:
        "200":
          description: Contact form successfully submitted.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Contact form submitted successfully
        "422":
          description: Validation failed or Turnstile token is missing/invalid.
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    example: 422
                  statusMessage:
                    type: string
                    example: Validation Failed
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                        example: Invalid email address.
                    required:
                      - message
                required:
                  - statusCode
                  - statusMessage
                  - data
        "500":
          description: Internal server error during processing or email delivery.
      operationId: postSupportContact
      summary: Submit contact form
      description: Handles website contact form submissions. Validates required
        fields, verifies a Turnstile token, stores data in Supabase, and sends
        confirmation and notification emails.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - first_name
                - last_name
                - email
                - message
                - agreed
                - token
              properties:
                first_name:
                  type: string
                  description: minLength is 2
                last_name:
                  type: string
                  description: minLength is 2
                email:
                  type: string
                  format: email
                message:
                  type: string
                  description: minLength is 10
                agreed:
                  type: boolean
                  description: Must be true to indicate agreement with terms
                token:
                  type: string
                  description: Cloudflare Turnstile token
                company_name:
                  type: string
                  nullable: true
                position_name:
                  type: string
                  nullable: true
                phone_number:
                  type: string
                  nullable: true
                user_id:
                  type: string
                  nullable: true
              additionalProperties: false
            examples:
              example:
                summary: Valid contact submission
                value:
                  first_name: Jane
                  last_name: Doe
                  email: jane.doe@example.com
                  message: I am interested in your enterprise services.
                  agreed: true
                  token: turnstile-token
                  company_name: Acme GmbH
                  position_name: IT Manager
                  phone_number: +49 123 456789
                  user_id: f8c6a5db-4d41-4c76-bc83-123456789abc
  /api/v1/support/feedback:
    post:
      tags:
        - Contact
      parameters: []
      responses:
        "200":
          description: Feedback sent.
        "422":
          description: Feedback validation or Turnstile verification failed.
        "500":
          description: Feedback delivery failed.
      operationId: postSupportFeedback
      summary: Send website feedback
      description: Validates website feedback and sends it to the support team through
        Resend.
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - name
                - message
                - page
                - token
              properties:
                name:
                  type: string
                email:
                  type: string
                  format: email
                message:
                  type: string
                page:
                  type: string
                token:
                  type: string
                  description: Cloudflare Turnstile token
                screenshot:
                  type: string
                  format: binary
                  description: Sanitized WebP screenshot
  /api/v1/support/tickets/{ticket_id}:
    get:
      tags:
        - Tickets
      parameters:
        - in: path
          name: ticket_id
          required: true
          schema:
            type: string
            format: uuid
          description: Ticket identifier
      responses:
        "200":
          description: Ticket fetched successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ticket:
                    type: object
                    description: Ticket record including resolved space name.
                    properties:
                      id:
                        type: string
                      subject:
                        type: string
                      message:
                        type: string
                      status:
                        type: string
                        enum:
                          - waiting-for-support
                          - waiting-for-customer
                          - closed
                      priority:
                        type: string
                        enum:
                          - low
                          - medium
                          - high
                      space_id:
                        type: string
                      space_name:
                        type: string
                      user_id:
                        type: string
                      created_at:
                        type: string
                        format: date-time
                      updated_at:
                        type: string
                        format: date-time
                        nullable: true
                    additionalProperties: true
                  comments:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        ticket_id:
                          type: string
                        user_id:
                          type: string
                        body:
                          type: string
                        created_at:
                          type: string
                          format: date-time
                        user_name:
                          type: string
                          nullable: true
                        user_email:
                          type: string
                          nullable: true
                      additionalProperties: true
                  history:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        ticket_id:
                          type: string
                        from_status:
                          type: string
                          nullable: true
                        to_status:
                          type: string
                        changed_at:
                          type: string
                          format: date-time
                        changed_by:
                          type: string
                        changed_by_name:
                          type: string
                          nullable: true
                        changed_by_email:
                          type: string
                          nullable: true
                      additionalProperties: true
                  attachments:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        ticket_id:
                          type: string
                        filename:
                          type: string
                        uploaded_at:
                          type: string
                          format: date-time
                        size:
                          type: number
                          nullable: true
                      additionalProperties: true
                required:
                  - ticket
                  - comments
                  - history
                  - attachments
        "400":
          description: Invalid ticket id.
        "401":
          description: Unauthenticated.
        "500":
          description: Failed to fetch ticket.
      operationId: getSupportTicket
      summary: Get ticket details
      description: Returns a ticket with space name, comments, status history, and
        attachments for the authenticated user.
      security:
        - bearerAuth: []
    patch:
      tags:
        - Tickets
      parameters:
        - in: path
          name: ticket_id
          required: true
          schema:
            type: string
            format: uuid
          description: Ticket identifier
      responses:
        "200":
          description: Ticket updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ticket:
                    type: object
                    properties:
                      id:
                        type: string
                      subject:
                        type: string
                      message:
                        type: string
                      status:
                        type: string
                        enum:
                          - waiting-for-support
                          - waiting-for-customer
                          - closed
                      priority:
                        type: string
                        enum:
                          - low
                          - medium
                          - high
                      space_id:
                        type: string
                      user_id:
                        type: string
                      created_at:
                        type: string
                        format: date-time
                      updated_at:
                        type: string
                        format: date-time
                    additionalProperties: true
                required:
                  - ticket
        "400":
          description: No valid fields provided or invalid ticket id.
        "401":
          description: Unauthenticated.
        "500":
          description: Failed to update ticket.
      operationId: patchSupportTicket
      summary: Update a ticket
      description: Updates mutable ticket fields such as subject, priority, or status
        for the authenticated user.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                subject:
                  type: string
                priority:
                  type: string
                  enum:
                    - low
                    - medium
                    - high
                status:
                  type: string
                  enum:
                    - waiting-for-support
                    - waiting-for-customer
                    - closed
              additionalProperties: false
            examples:
              example:
                summary: Change status and priority
                value:
                  status: waiting-for-customer
                  priority: high
  /api/v1/support/tickets/{ticket_id}/attachments:
    get:
      tags:
        - Tickets
      parameters:
        - in: path
          name: ticket_id
          required: true
          schema:
            type: string
            format: uuid
          description: Ticket identifier
      responses:
        "200":
          description: Attachments fetched successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  attachments:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        ticket_id:
                          type: string
                        file_name:
                          type: string
                        storage_path:
                          type: string
                        uploaded_at:
                          type: string
                          format: date-time
                        size:
                          type: number
                          nullable: true
                      additionalProperties: true
                required:
                  - attachments
        "400":
          description: Invalid ticket id.
        "401":
          description: Unauthenticated.
        "404":
          description: Ticket not found.
        "500":
          description: Failed to fetch attachments.
      operationId: getSupportTicketAttachments
      summary: List ticket attachments
      description: Returns all file attachments associated with the specified ticket
        for the authenticated user.
      security:
        - bearerAuth: []
    post:
      tags:
        - Tickets
      parameters:
        - in: path
          name: ticket_id
          required: true
          schema:
            type: string
            format: uuid
          description: Ticket identifier
      responses:
        "200":
          description: Attachment recorded successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  attachment:
                    type: object
                    properties:
                      id:
                        type: string
                      ticket_id:
                        type: string
                      file_name:
                        type: string
                      storage_path:
                        type: string
                      uploaded_at:
                        type: string
                        format: date-time
                    additionalProperties: true
                required:
                  - attachment
        "400":
          description: Invalid ticket id or missing file data.
        "401":
          description: Unauthenticated.
        "404":
          description: Ticket not found.
        "500":
          description: Failed to add attachment.
      operationId: postSupportTicketAttachment
      summary: Add ticket attachment
      description: Records a metadata row for an existing file in storage and
        associates it with the specified ticket.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - file_name
                - storage_path
              properties:
                file_name:
                  type: string
                  description: Original file name
                storage_path:
                  type: string
                  description: Supabase Storage path to the uploaded file
              additionalProperties: false
            examples:
              example:
                summary: Valid attachment payload
                value:
                  file_name: error-screenshot.png
                  storage_path: tickets/8c0b9b9a-9a77-4e1c-b6a3-1d6d8f5fbe01/error-screenshot.png
  /api/v1/support/tickets/{ticket_id}/comments:
    get:
      tags:
        - Tickets
      parameters:
        - in: path
          name: ticket_id
          required: true
          schema:
            type: string
            format: uuid
          description: Ticket identifier
      responses:
        "200":
          description: Comments fetched successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  comments:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        ticket_id:
                          type: string
                        user_id:
                          type: string
                        message:
                          type: string
                        created_at:
                          type: string
                          format: date-time
                        user_name:
                          type: string
                          nullable: true
                        user_email:
                          type: string
                          nullable: true
                      additionalProperties: true
                required:
                  - comments
        "400":
          description: Invalid ticket id.
        "401":
          description: Unauthenticated.
        "404":
          description: Ticket not found.
        "500":
          description: Failed to fetch comments.
      operationId: getSupportTicketComments
      summary: List ticket comments
      description: Returns all comments for the specified ticket, enriched with author
        name and email when available.
      security:
        - bearerAuth: []
    post:
      tags:
        - Tickets
      parameters:
        - in: path
          name: ticket_id
          required: true
          schema:
            type: string
            format: uuid
          description: Ticket identifier
      responses:
        "200":
          description: Comment added successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  comment:
                    type: object
                    properties:
                      id:
                        type: string
                      ticket_id:
                        type: string
                      user_id:
                        type: string
                      message:
                        type: string
                      created_at:
                        type: string
                        format: date-time
                    additionalProperties: true
                required:
                  - comment
        "400":
          description: Invalid ticket id or message.
        "401":
          description: Unauthenticated.
        "500":
          description: Failed to add comment.
      operationId: postSupportTicketComment
      summary: Add ticket comment
      description: Adds a new comment to the specified ticket for the authenticated user.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - message
              properties:
                message:
                  type: string
              additionalProperties: false
            examples:
              example:
                summary: Minimal comment payload
                value:
                  message: Here is an update with error logs attached.
  /api/v1/support/tickets/{ticket_id}/status_history:
    get:
      tags:
        - Tickets
      parameters:
        - in: path
          name: ticket_id
          required: true
          schema:
            type: string
            format: uuid
          description: Ticket identifier
      responses:
        "200":
          description: Status history fetched successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  history:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        ticket_id:
                          type: string
                        from_status:
                          type: string
                          nullable: true
                          enum:
                            - waiting-for-support
                            - waiting-for-customer
                            - closed
                            - "null"
                        to_status:
                          type: string
                          enum:
                            - waiting-for-support
                            - waiting-for-customer
                            - closed
                        changed_at:
                          type: string
                          format: date-time
                        changed_by:
                          type: string
                        changed_by_name:
                          type: string
                          nullable: true
                        changed_by_email:
                          type: string
                          nullable: true
                      additionalProperties: true
                required:
                  - history
        "400":
          description: Invalid ticket id.
        "401":
          description: Unauthenticated.
        "500":
          description: Failed to fetch status history.
      operationId: getSupportTicketStatusHistory
      summary: List ticket status history
      description: Returns the status change history for the specified ticket,
        including who performed each change.
      security:
        - bearerAuth: []
    post:
      tags:
        - Tickets
      parameters:
        - in: path
          name: ticket_id
          required: true
          schema:
            type: string
            format: uuid
          description: Ticket identifier
      responses:
        "200":
          description: Status change recorded successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  history:
                    type: object
                    properties:
                      id:
                        type: string
                      ticket_id:
                        type: string
                      from_status:
                        type: string
                        nullable: true
                        enum:
                          - waiting-for-support
                          - waiting-for-customer
                          - closed
                          - "null"
                      to_status:
                        type: string
                        enum:
                          - waiting-for-support
                          - waiting-for-customer
                          - closed
                      changed_at:
                        type: string
                        format: date-time
                      changed_by:
                        type: string
                      changed_by_name:
                        type: string
                        nullable: true
                      changed_by_email:
                        type: string
                        nullable: true
                    additionalProperties: true
                    required:
                      - id
                      - ticket_id
                      - to_status
                      - changed_at
                      - changed_by
                required:
                  - history
        "400":
          description: Invalid ticket id or status.
        "401":
          description: Unauthenticated.
        "500":
          description: Failed to log status change.
      operationId: postSupportTicketStatusHistory
      summary: Add status history entry
      description: Appends a new status change record to the specified ticket for the
        authenticated user.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - to_status
              properties:
                to_status:
                  type: string
                  enum:
                    - waiting-for-support
                    - waiting-for-customer
                    - closed
                  description: New ticket status
                from_status:
                  type: string
                  nullable: true
                  enum:
                    - waiting-for-support
                    - waiting-for-customer
                    - closed
                    - "null"
                  description: Previous status (optional)
              additionalProperties: false
            examples:
              example:
                summary: Close a ticket
                value:
                  from_status: waiting-for-customer
                  to_status: closed
  /api/v1/support/tickets:
    get:
      tags:
        - Tickets
      parameters: []
      responses:
        "200":
          description: Tickets fetched successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  tickets:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        subject:
                          type: string
                        message:
                          type: string
                        status:
                          type: string
                          enum:
                            - waiting-for-support
                            - waiting-for-customer
                            - closed
                        priority:
                          type: string
                          enum:
                            - low
                            - medium
                            - high
                        space:
                          type: string
                          description: Space name or id
                        createdAt:
                          type: string
                          format: date-time
                        lastUpdated:
                          type: string
                          format: date-time
                          nullable: true
                      additionalProperties: false
                required:
                  - tickets
        "401":
          description: Unauthenticated.
        "500":
          description: Failed to load tickets.
      operationId: getSupportTickets
      summary: List user tickets
      description: Returns all support tickets belonging to the authenticated user,
        newest first.
      security:
        - bearerAuth: []
    post:
      tags:
        - Tickets
      parameters: []
      responses:
        "200":
          description: Ticket created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  ticket:
                    type: object
                    description: Created ticket row
                    properties:
                      id:
                        type: string
                      subject:
                        type: string
                      message:
                        type: string
                      status:
                        type: string
                        example: waiting-for-support
                      priority:
                        type: string
                        enum:
                          - low
                          - medium
                          - high
                      space_id:
                        type: string
                      user_id:
                        type: string
                      created_at:
                        type: string
                        format: date-time
                      updated_at:
                        type: string
                        format: date-time
                        nullable: true
                    additionalProperties: true
                required:
                  - ticket
        "400":
          description: Invalid subject, message, or missing space_id.
        "401":
          description: Unauthenticated.
        "500":
          description: Failed to create ticket.
      operationId: postSupportTickets
      summary: Create a support ticket
      description: Creates a new support ticket for the authenticated user.
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - subject
                - message
                - space_id
              properties:
                subject:
                  type: string
                  description: minLength is 5
                message:
                  type: string
                  description: minLength is 30
                space_id:
                  type: string
                  description: Associated space identifier
                priority:
                  type: string
                  enum:
                    - low
                    - medium
                    - high
                  default: low
              additionalProperties: false
            examples:
              example:
                summary: Minimal valid payload
                value:
                  subject: Billing question
                  message: I need help updating my billing address for the next invoice.
                  space_id: space_123
                  priority: low
  /security.txt:
    get:
      tags:
        - App Routes
      parameters: []
      responses:
        "200":
          description: OK
  /__nuxt_error:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /_scripts/p/{*param1}:
    get:
      tags:
        - Internal
      parameters:
        - name: "*param1"
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: OK
  /__site-config__/debug.json:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /robots.txt:
    get:
      tags:
        - App Routes
      parameters: []
      responses:
        "200":
          description: OK
  /__robots__/debug.json:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /__robots__/debug-path.json:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /__robots__/debug-production.json:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /api/savory:
    get:
      tags:
        - API Routes
      parameters: []
      responses:
        "200":
          description: OK
  /__skew-devtools/debug:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /__skew-devtools/debug-production:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /__sitemap__/debug.json:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /__sitemap__/debug-production.json:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /__sitemap__/style.xsl:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /sitemap.xml:
    get:
      tags:
        - App Routes
      parameters: []
      responses:
        "200":
          description: OK
  /__nuxt-seo-utils/debug.json:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /__schema-org__/debug.json:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /__nuxt_island/{*param1}:
    get:
      tags:
        - Internal
      parameters:
        - name: "*param1"
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: OK
  /_openapi.json:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /_scalar:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
  /_swagger:
    get:
      tags:
        - Internal
      parameters: []
      responses:
        "200":
          description: OK
x-tagGroups:
  - name: Marketing
    tags:
      - Marketing
      - Marketing Billing
  - name: Billing
    tags:
      - Billing Contacts
      - Billing Profiles
      - Checkouts
      - Stripe Actions
  - name: Careers
    tags:
      - Jobs
  - name: Community
    tags:
      - Newsletter
      - Roadmap
      - Waitlist
  - name: Products
    tags:
      - Certificate Products
      - Domain Products
  - name: Spaces
    tags:
      - Space Actions
      - Space Assets
      - Space Licenses
      - Space Audit Logs
      - Space Members
      - Space Member Invitations
      - Space Settings
  - name: Support
    tags:
      - Contact
      - Tickets
