openapi: 3.1.0
info:
  title: Datman API
  version: 2026-11-02
tags:
  - name: Transactions
    description: List and search payment transactions for the reseller bound to the
      caller's API key.
  - name: Merchant details
    description: Read a merchant's profile, owner, business and bank details.
  - name: Payment configuration
    description: Read a merchant's payment provider, fees, limits and payout settings.
  - name: Onboarding
    description: Onboarding progress and hosted onboarding links.
  - name: KYC documents
    description: KYC documents for a merchant.
  - name: Merchant users
    description: Portal users who can access a merchant.
  - name: Reseller portfolio
    description: Summary and onboarding status across all merchants under your reseller.
  - name: Transaction details
    description: Full detail, splits, refunds and webhook deliveries for one transaction.
  - name: Payouts
    description: A merchant's payouts and payout totals.
  - name: Balances
    description: Merchant balances and payment, refund and net totals.
  - name: Merchant association
    description: Create, reactivate or update the merchants you onboard.
      Authenticated with a Datman-issued partner API key.
  - name: Onboarding status
    description: Check where a merchant is in onboarding and verification.
  - name: Embedded dashboard
    description: Tokens and URLs for embedding the Datman merchant dashboard in your app.
  - name: Webhooks
    description: Callbacks that Datman sends to your webhook URL.
  - name: Hosted Payment
    description: Send the shopper to Datman's hosted payment form with an encrypted
      payload. No API key in the request; the payload is encrypted on your
      server with your secret key.
  - name: Payment modifications
    description: Refund, capture, adjust or reverse an existing payment.
  - name: Internal transfers
    description: Move funds between two merchants and get notified when the transfer
      completes.
  - name: Split commission types
    description: Manage the commission types used when splitting a payment between
      merchants.
paths:
  /v1/transactions/list:
    post:
      operationId: listTransactions
      summary: List transactions in a date range
      description: Returns a cursor-paginated page of transactions for the caller's
        reseller between fromDate and toDate (calendar dates in the caller's
        timezone), newest first. For API key callers the reseller is always
        taken from the key; a different resellerId in the body is rejected with
        403.
      tags:
        - Transactions
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TransactionListRequest"
            examples:
              dateRange:
                summary: Transactions for a date range
                value:
                  fromDate: 2026-10-01
                  toDate: 2026-10-14
                  limit: 25
                  timezone: Europe/London
              merchantStatusFilter:
                summary: One merchant, successful and refunded only
                value:
                  fromDate: 2026-10-01
                  toDate: 2026-10-14
                  merchantId: 123456
                  status:
                    - SUCCESS
                    - REFUND
                  limit: 10
                  cursor: eyJ0IjoiMjAyNi0xMC0xNCAwOToxMjo0NyIsInBJZCI6MTAwMjMwLCJjSWQiOm51bGx9
      responses:
        "200":
          description: "A page of transactions. When the reseller has no configuration an
            empty page is returned (without data.timezone). When merchantId
            refers to a liable merchant the body also carries `isLiable: true`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TransactionListResponse"
              examples:
                transactionsFound:
                  summary: Transactions found
                  value:
                    data:
                      transactions:
                        - id: p_100231
                          source: payments
                          transactionTime: 2026-10-14 13:45:12
                          orderRef: "987654321"
                          amount: 24.5
                          currencyCode: GBP
                          status: SUCCESS
                          merchantId: 123456
                          merchantName: Example Pizza Co
                          resellerOrderId: ORD-10045
                          paymentMethod: New Card
                          transactionModeId: 1
                          internalReference: REF-10045
                          last4Digits: "1111"
                          shopperId: null
                          net: 23.9
                          deductions: 0.6
                          datman_fee: 0.6
                      timezone: Europe/London
                    pagination:
                      hasMore: true
                      nextCursor: eyJ0IjoiMjAyNi0xMC0xNCAwOToxMjo0NyIsInBJZCI6MTAwMjMwLCJjSWQiOm51bGx9
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "422":
          description: The request body failed validation.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidFromDate:
                  summary: fromDate is not YYYY-MM-DD
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: fromDate must be YYYY-MM-DD
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/transactions/by-order-id:
    post:
      operationId: searchTransactionsByOrderId
      summary: Search transactions by order identifier
      description: Looks up all transactions matching an identifier, keyed by searchBy
        (order ID by default, or merchant reference, reseller order ID, or
        merchant ID). The merchantId search is bounded by fromDate/toDate,
        defaulting to yesterday through today in the caller's timezone.
      tags:
        - Transactions
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/OrderSearchRequest"
            examples:
              byOrderId:
                summary: Search by order ID
                value:
                  query: "987654321"
                  searchBy: orderId
              byMerchantId:
                summary: Search by merchant ID within a date window
                value:
                  query: "123456"
                  searchBy: merchantId
                  fromDate: 2026-10-13
                  toDate: 2026-10-14
                  limit: 25
                  timezone: Europe/London
      responses:
        "200":
          description: "Matching transactions. No match (or no reseller configuration)
            returns an empty page. For a liable merchant (searchBy merchantId)
            the body carries `isLiable: true` and a top-level `timezone` instead
            of `data.timezone`."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OrderSearchResponse"
              examples:
                transactionsFound:
                  summary: Transactions found
                  value:
                    data:
                      transactions:
                        - id: p_100231
                          source: payments
                          transactionTime: 2026-10-14 13:45:12
                          orderRef: "987654321"
                          amount: 24.5
                          currencyCode: GBP
                          status: SUCCESS
                          merchantId: 123456
                          merchantName: Example Pizza Co
                          resellerOrderId: ORD-10045
                          paymentMethod: New Card
                          transactionModeId: 1
                          internalReference: REF-10045
                          last4Digits: "1111"
                          shopperId: null
                          net: 23.9
                          deductions: 0.6
                          datman_fee: 0.6
                      timezone: Europe/London
                    pagination:
                      hasMore: false
                      nextCursor: null
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "422":
          description: The request body failed validation.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                missingQuery:
                  summary: query is missing or empty
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: query is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/summary:
    get:
      operationId: getMerchantSummary
      summary: Get merchant summary
      description: Returns the merchant's name, owning reseller, country and the
        per-section onboarding statuses (account, payout, business, owners,
        bank, terms of service), plus whether the merchant is itself a reseller
        and whether it is liable. The merchant must belong to the reseller that
        owns the API key; any other merchant id returns 404. Returns 404 as well
        when the merchant has no onboarding record.
      tags:
        - Merchant details
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
      responses:
        "200":
          description: Merchant summary.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantSummaryResponse"
              examples:
                activeMerchant:
                  summary: Fully onboarded merchant
                  value:
                    data:
                      merchant_id: 123456
                      merchant_name: Example Pizza Co
                      canonical_reseller_id: 42
                      country: United Kingdom
                      account_status: ACTIVE
                      payout_status: ACTIVE
                      business_status: VERIFIED
                      owners_status: VERIFIED
                      bank_status: Verified
                      tos_status: ACCEPTED
                      is_reseller: false
                      is_liable: true
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller, or it has no
            onboarding record.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/payment-config:
    get:
      operationId: getMerchantPaymentConfig
      summary: Get payment configuration
      description: "Returns the merchant's payment provider, fee tier, your reseller
        pricing on top of the tier, gateway settings and transaction limits. The
        effective limits (`max_transaction`, `xpress_sale_limit`) fall back to
        the country default when the merchant-level value is unset or 0. The raw
        `merchant_*` and `country_*` values are returned separately.
        `buying_rate_*` is your reseller's cost rate for this merchant, and is
        null when no rate is on file. Returns `data: {}` when the merchant has
        no gateway customer record. The merchant must belong to your reseller,
        otherwise 404."
      tags:
        - Payment configuration
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
      responses:
        "200":
          description: Payment configuration. `data` is an empty object when the merchant
            has no gateway customer record.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantPaymentConfigResponse"
              examples:
                configured:
                  summary: Merchant with a fee tier and a country-default transaction limit
                  value:
                    data:
                      fee_tier_name: Standard
                      fee_tier_percentage: 1.5
                      fee_tier_fixed: 0.2
                      ext_reseller_percentage_fee: 0.25
                      ext_reseller_fixed_fee: 0.05
                      gateway_name: null
                      billing_address: null
                      hide_gpay_apay: null
                      mid_status: null
                      min_transaction: null
                      max_transaction: 5000
                      xpress_sale_limit: 250
                      daily_limit: null
                      merchant_max_transaction: 0
                      merchant_xpress_sale_limit: 250
                      country_max_transaction: 5000
                      country_xpress_sale_limit: 100
                      fee_tier_id: 3
                      buying_rate_percentage: 1.2
                      buying_rate_fixed: 0.15
                noCustomerRecord:
                  summary: No gateway customer record for this merchant
                  value:
                    data: {}
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/owner-details:
    get:
      operationId: getMerchantOwnerDetails
      summary: Get primary owner details
      description: "Returns the merchant's primary owner: name, contact details, date
        of birth, nationality, ownership percentage and home address.
        `owner_details` is null when the merchant has no primary owner on file.
        The merchant must belong to your reseller, otherwise 404."
      tags:
        - Merchant details
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
      responses:
        "200":
          description: Primary owner details, or null.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantOwnerDetailsResponse"
              examples:
                owner:
                  summary: Merchant with a primary owner
                  value:
                    data:
                      owner_details:
                        title: Mr
                        full_name: Alex Example
                        email: owner@example.com
                        telephone_number: "+447700900123"
                        date_of_birth: 1985-04-12T00:00:00.000Z
                        nationality: British
                        ownership_percentage: 100
                        address_line1: 1 Example Street
                        address_line2: null
                        city: London
                        county: Greater London
                        post_code: EC1A 1AA
                        state: null
                        country: United Kingdom
                noOwner:
                  summary: No primary owner on file
                  value:
                    data:
                      owner_details: null
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/business-details:
    get:
      operationId: getMerchantBusinessDetails
      summary: Get business details
      description: "Returns the merchant's business profile: legal and trading names,
        company and VAT numbers, legal entity type, industry, contact details,
        and the registered and trading addresses. It also includes a short
        summary of the primary owner's contact details. Returns `data: {}` when
        there is no merchant record. Fields inside the nested objects are null
        when the related record is missing. The merchant must belong to your
        reseller, otherwise 404."
      tags:
        - Merchant details
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
      responses:
        "200":
          description: Business details.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantBusinessDetailsResponse"
              examples:
                limitedCompany:
                  summary: UK limited company
                  value:
                    data:
                      business_details:
                        legal_name: Example Pizza Co Ltd
                        trading_name: Example Pizza Co
                        company_number: "01234567"
                        legal_entity: Limited Company
                        industry: Restaurants
                        vat_number: GB123456789
                        telephone_number: "+442079460000"
                        website_url: https://www.example.com
                        registered_address:
                          address_line1: 1 Example Street
                          address_line2: null
                          city: London
                          county: Greater London
                          post_code: EC1A 1AA
                          state: null
                          country: United Kingdom
                        trading_address:
                          address_line1: 2 Example Road
                          address_line2: Unit 4
                          city: London
                          county: Greater London
                          post_code: EC1A 2BB
                          state: null
                          country: United Kingdom
                      owner_details:
                        full_name: Alex Example
                        email: owner@example.com
                        telephone_number: "+447700900123"
                        address_line1: 1 Example Street
                        address_line2: null
                        city: London
                        county: Greater London
                        post_code: EC1A 1AA
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/bank-details:
    get:
      operationId: getMerchantBankDetails
      summary: Get bank details
      description: Returns the merchant's payout bank account. Account identifiers
        (sort code, account number, routing number, BSB, transit number and
        financial institution number) are masked, so only the last 3 characters
        are shown, prefixed with `****`. Identifiers that don't apply to the
        account's country are null. `verified_on` is set only when `status` is
        `Verified`. `data` is null when there is no merchant record. The
        merchant must belong to your reseller, otherwise 404.
      tags:
        - Merchant details
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
      responses:
        "200":
          description: Masked bank details.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantBankDetailsResponse"
              examples:
                ukAccount:
                  summary: Verified UK bank account
                  value:
                    data:
                      name_of_bank: Example Bank
                      account_holder_name: Example Pizza Co Ltd
                      sort_code: "****456"
                      account_number: "****234"
                      routing_number: null
                      bsb_code: null
                      transit_number: null
                      financial_institution_number: null
                      account_type: null
                      country: United Kingdom
                      status: Verified
                      verified_on: 2026-03-01T10:15:00.000Z
                pendingAccount:
                  summary: Bank account awaiting verification
                  value:
                    data:
                      name_of_bank: Example Bank
                      account_holder_name: Example Pizza Co Ltd
                      sort_code: "****456"
                      account_number: "****234"
                      routing_number: null
                      bsb_code: null
                      transit_number: null
                      financial_institution_number: null
                      account_type: null
                      country: United Kingdom
                      status: Pending
                      verified_on: null
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/onboarding:
    get:
      operationId: getMerchantOnboarding
      summary: Get onboarding status
      description: "Returns the merchant's onboarding record: section statuses,
        verification tier, the onboarding link, any outstanding missing details,
        and one merged list of onboarding errors. The `errors` list combines
        three sources (legacy errors, missing details and payment provider KYC
        errors) and keeps only the first occurrence of each field. Returns
        `data: {}` when the merchant has no onboarding record. The merchant must
        belong to your reseller, otherwise 404."
      tags:
        - Onboarding
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
      responses:
        "200":
          description: Onboarding status, or an empty object when there is no onboarding
            record.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantOnboardingResponse"
              examples:
                inProgress:
                  summary: Onboarding with outstanding items
                  value:
                    data:
                      merchant_id: 123456
                      merchant_name: Example Pizza Co
                      onboarding_link: https://onboarding.example.com/start/abc123
                      overview_page: https://onboarding.example.com/overview/abc123
                      account_status: PENDING
                      payout_status: PENDING
                      business_status: VERIFIED
                      owners_status: PENDING
                      bank_status: Pending
                      tos_status: ACCEPTED
                      verification_tier: "1"
                      missing_details:
                        bank issues:
                          - Upload a bank statement
                      note: null
                      country: United Kingdom
                      errors:
                        - title: Bank Issues
                          field: Upload a bank statement
                          reported_at: null
                        - title: Individual
                          field: identificationData.number
                          reported_at: 2026-03-01T10:15:00.000Z
                noRecord:
                  summary: Merchant without an onboarding record
                  value:
                    data: {}
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/onboarding/documents:
    get:
      operationId: listMerchantKycDocuments
      summary: List KYC documents
      description: Lists the KYC documents uploaded for the merchant's verification.
        This covers the merchant's primary legal entity, its associated legal
        entities (for example owners and signatories) and its transfer
        instruments. Only file names and upload times are returned, never the
        document contents. Returns an empty list when the merchant has no legal
        entity on file, or when the verification service can't be reached. The
        merchant must belong to your reseller, otherwise 404.
      tags:
        - KYC documents
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
      responses:
        "200":
          description: KYC documents on file.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantKycDocumentsResponse"
              examples:
                documents:
                  summary: Merchant with uploaded documents
                  value:
                    data:
                      documents:
                        - name: passport.pdf
                          uploaded_at: 2026-02-14T09:30:00.000Z
                        - name: bank-statement.pdf
                          uploaded_at: 2026-02-15T11:00:00.000Z
                none:
                  summary: No legal entity or no documents
                  value:
                    data:
                      documents: []
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/users:
    get:
      operationId: listMerchantUsers
      summary: List merchant users
      description: Lists the portal users who have an active role on the merchant,
        with each user's display name, email, role and status. `status` is
        `Active` once the user has completed sign-up and `Pending` otherwise.
        Revoked and deleted users are excluded. The list is not paginated. The
        merchant must belong to your reseller, otherwise 404.
      tags:
        - Merchant users
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
      responses:
        "200":
          description: Users with access to the merchant.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantUsersResponse"
              examples:
                users:
                  summary: Owner and a pending staff member
                  value:
                    data:
                      - relationship_id: 9001
                        id: 5001
                        name: Alex Example
                        email: owner@example.com
                        roles:
                          - Owner
                        merchant_role_id: 1
                        reseller_id: 42
                        status: Active
                        last_login: "-"
                      - relationship_id: 9002
                        id: 5002
                        name: staff
                        email: staff@example.com
                        roles:
                          - Manager
                        merchant_role_id: 3
                        reseller_id: 42
                        status: Pending
                        last_login: "-"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/payouts:
    get:
      operationId: listMerchantPayouts
      summary: List payouts
      description: Lists the merchant's most recent payouts across all payout
        providers, newest first. Finalised batches are excluded, and provider
        payout transactions are included only when their status is `SENT` or
        `FAILED`. Amounts are in major currency units (for example pounds). Use
        `limit` to cap the number of rows. There is no cursor or offset. The
        merchant must belong to your reseller, otherwise 404.
      tags:
        - Payouts
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
        - name: limit
          in: query
          required: false
          description: Maximum number of payouts to return. Defaults to 50 and is capped
            at 200. Missing, zero or non-numeric values use the default.
          schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
          example: 50
      responses:
        "200":
          description: Recent payouts, newest first.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantPayoutsResponse"
              examples:
                payouts:
                  summary: Recent payouts
                  value:
                    data:
                      - id: 778899
                        total: 1250.75
                        status: SENT
                        expected_date: 2026-03-03T00:00:00.000Z
                        sort_date: 2026-03-02T07:00:12.000Z
                        payment_provider: DATMAN
                      - id: 445566
                        total: 980.4
                        status: PENDING
                        expected_date: 2026-02-24T00:00:00.000Z
                        sort_date: 2026-02-24T00:00:00.000Z
                        payment_provider: DATMAN
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/payout-stats:
    get:
      operationId: getMerchantPayoutStats
      summary: Get payout statistics
      description: Returns the merchant's provider payout transactions grouped by
        status, with the number of payouts and the total amount (in major
        currency units) for each status. This covers all time. Payout batches
        are not counted. Returns an empty list when the merchant has no payout
        transactions. The merchant must belong to your reseller, otherwise 404.
      tags:
        - Payouts
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
      responses:
        "200":
          description: Payout counts and totals by status.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantPayoutStatsResponse"
              examples:
                stats:
                  summary: Sent and failed payouts
                  value:
                    data:
                      - status: SENT
                        order_count: 42
                        total_amount: 18250.5
                      - status: FAILED
                        order_count: 1
                        total_amount: 310
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId is required
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/merchants/{merchantId}/balance:
    get:
      operationId: getMerchantBalance
      summary: Get account balance
      description: Returns the merchant's current available balance in major currency
        units, rounded to 2 decimal places. The balance includes card and
        payment takings, internal transfers and in-transit provider funds, minus
        completed payouts, depending on the merchant's country and payout setup.
        `pending` and `on_hold` are always 0. Returns all zeros when the
        merchant has no gateway customer record. The merchant must belong to
        your reseller, otherwise 404.
      tags:
        - Balances
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Numeric merchant id. Must be a positive integer belonging to your
            reseller.
          schema:
            type: integer
            minimum: 1
          example: 123456
      responses:
        "200":
          description: Current balance.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantBalanceResponse"
              examples:
                balance:
                  summary: Merchant with an available balance
                  value:
                    data:
                      available: 2345.67
                      pending: 0
                      on_hold: 0
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: The merchant does not belong to your reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                notFound:
                  summary: Merchant not found or not in your reseller
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The merchantId path segment is not numeric.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: Non-numeric merchant id
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId must be numeric
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/transactions/refund-details:
    get:
      operationId: getRefundDetails
      summary: Get refunds recorded against a transaction
      description: Returns the refunds (amount and time) recorded against one payment,
        newest first. For `source=payments` (the default for any value other
        than `card_payment`) the lookup is keyed on orderRef. For
        `source=card_payment` it is keyed on pspReference (the legacy
        CrossReference), or on orderId when isLiable is true. For API key
        callers the merchant that owns the record must belong to the key's
        reseller; otherwise, or when no such record exists, the response is 404.
        This route is registered before `GET /v1/transactions/{orderRef}`, so
        the literal path `/v1/transactions/refund-details` always reaches this
        handler, never the transaction detail lookup.
      tags:
        - Transaction details
      security:
        - ApiKeyAuth: []
      parameters:
        - name: source
          in: query
          required: true
          description: Which table the payment lives in. `card_payment` is the legacy
            table; any other non-empty value is treated as `payments`.
          schema:
            type: string
            examples:
              - payments
              - card_payment
        - name: orderRef
          in: query
          required: false
          description: Datman order reference. Required when source is `payments`. The
            snake_case alias `order_ref` is also accepted.
          schema:
            type: string
          example: "987654321"
        - name: pspReference
          in: query
          required: false
          description: Legacy card_payment CrossReference. Required when source is
            `card_payment` and isLiable is not true. The snake_case alias
            `psp_reference` is also accepted.
          schema:
            type: string
        - name: orderId
          in: query
          required: false
          description: card_payment order ID. Required when source is `card_payment` and
            isLiable is true.
          schema:
            type: string
        - name: isLiable
          in: query
          required: false
          description: Only the exact string `true` enables liable-account lookup; any
            other value means false.
          schema:
            type: string
            enum:
              - "true"
              - "false"
            default: "false"
        - name: timezone
          in: query
          required: false
          description: IANA timezone to render refund times in. Not validated; an unknown
            name results in a 500. When omitted, times are Europe/London.
          schema:
            type: string
          example: Europe/London
      responses:
        "200":
          description: The refunds for the transaction (an empty array when there are
            none). The timezone the times are expressed in is returned in
            `meta.timezone`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpRefundDetailsResponse"
              examples:
                refundsFound:
                  summary: One partial refund on a payments transaction
                  value:
                    data:
                      - amount: -5
                        time: 2026-10-14 15:02:10
                    meta:
                      timezone: Europe/London
                noRefunds:
                  summary: No refunds recorded
                  value:
                    data: []
                    meta:
                      timezone: Europe/London
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: No record matches the identifier, or (for API key callers) its
            merchant does not belong to the key's reseller. The two cases are
            deliberately indistinguishable.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                transactionNotFound:
                  summary: Unknown or out-of-scope transaction
                  value:
                    error:
                      code: NOT_FOUND
                      message: Transaction not found
        "422":
          description: source is missing, or the identifier that source/isLiable require
            is missing. The message is the same for every case.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                missingParams:
                  summary: A required query parameter is missing
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: Missing required query params
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/transactions/{orderRef}:
    get:
      operationId: getTransaction
      summary: Get full details of a transaction
      description: Returns every payment row recorded under an order reference,
        together with its refunds, chargebacks, revenue splits and shopper. For
        API key callers the merchant on the transaction must belong to the key's
        reseller; an unknown order reference and one outside the reseller's
        scope both return 404. Pass `timezone` to get timestamps as `YYYY-MM-DD
        HH:MM:SS` in that zone (see the timestamp notes on the schema).
      tags:
        - Transaction details
      security:
        - ApiKeyAuth: []
      parameters:
        - name: orderRef
          in: path
          required: true
          description: Datman order reference.
          schema:
            type: string
          example: "987654321"
        - name: timezone
          in: query
          required: false
          description: IANA timezone to render timestamps in. Invalid names are ignored.
            When no timezone is resolved, `timezone` in the response is
            Europe/London and timestamps are raw ISO strings.
          schema:
            type: string
          example: Europe/London
      responses:
        "200":
          description: The transaction, its refunds, chargebacks, splits and shopper.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpTransactionDetailResponse"
              examples:
                transactionWithRefund:
                  summary: A successful payment with a partial refund (timezone=Europe/London)
                  value:
                    data:
                      transactions:
                        - id: 100231
                          order_ref: "987654321"
                          amount: "24.5000"
                          net: "23.9000"
                          fee: "0.6000"
                          datman_fee: 0.6
                          transaction_time: 2026-10-14 13:45:12
                          refund_reason_id: null
                          reason: null
                          currency_code: GBP
                          status_id: 1
                          status: SUCCESS
                          merchant_id: 123456
                          internal_reference: REF-10045
                          shopper_id: null
                          last4_digits: "1111"
                          transaction_mode_id: 1
                          payment_method: New Card
                      refunds:
                        - amount: "-5.0000"
                          net: "-5.0000"
                          fee: "0.0000"
                          internal_reference: REF-10045-R1
                          transaction_time: 2026-10-14 15:02:10
                          reason: Customer request
                      chargebacks: []
                      shopper:
                        first_name: Alex
                        last_name: Example
                        email: alex@example.com
                        address: 1 Example Street
                      splits: []
                      timezone: Europe/London
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: "API key callers only: no transaction exists for the order
            reference, it has no attributable merchant, or the merchant is
            outside the key's reseller."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                transactionNotFound:
                  summary: Unknown or out-of-scope order reference
                  value:
                    error:
                      code: NOT_FOUND
                      message: Transaction not found
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          description: A query failed. The underlying message is logged, not returned.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                databaseError:
                  summary: Detail query failed
                  value:
                    error:
                      code: INTERNAL_ERROR
                      message: Database error
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/transactions/{orderRef}/splits:
    get:
      operationId: getTransactionSplits
      summary: Get the revenue split breakdown for a transaction
      description: Returns the split-commission rows recorded for an order (one per
        partner share), including how much of each share has been refunded. For
        API key callers the order's merchant must belong to the key's reseller;
        otherwise, or when the order does not exist, the response is 404. An
        order with no splits returns an empty array.
      tags:
        - Transaction details
      security:
        - ApiKeyAuth: []
      parameters:
        - name: orderRef
          in: path
          required: true
          description: Datman order reference.
          schema:
            type: string
          example: "987654321"
      responses:
        "200":
          description: The split rows for the order (possibly empty).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpTransactionSplitsResponse"
              examples:
                splitsFound:
                  summary: Order split between the merchant and a partner
                  value:
                    data:
                      - amount: "22.0500"
                        amount_refunded: "0.0000"
                        commission_type: merchant
                        merchant_id: 123456
                      - amount: "2.4500"
                        amount_refunded: "0.0000"
                        commission_type: partner
                        merchant_id: 123457
                noSplits:
                  summary: Order without splits
                  value:
                    data: []
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: "API key callers only: the order does not exist or its merchant is
            outside the key's reseller."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                transactionNotFound:
                  summary: Unknown or out-of-scope order reference
                  value:
                    error:
                      code: NOT_FOUND
                      message: Transaction not found
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/transactions/{id}/webhook-payload:
    get:
      operationId: getTransactionWebhookPayloads
      summary: Get webhook deliveries for a transaction
      description: "Returns the webhook calls Datman made for a payment and for every
        payment that shares its order reference: the URL called, the event
        action, the payload sent, the HTTP status received, and when it was
        sent. Any key named `token` is removed from payloads. For API key
        callers the payment's merchant must belong to the key's reseller;
        otherwise, or when the payment does not exist, the response is 404."
      tags:
        - Transaction details
      security:
        - ApiKeyAuth: []
      parameters:
        - name: id
          in: path
          required: true
          description: Numeric payment ID (payments.id).
          schema:
            type: integer
            minimum: 1
          example: 100231
      responses:
        "200":
          description: Webhook delivery log rows (an empty array when there are none, or
            when the payment exists but has no order reference).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpWebhookPayloadResponse"
              examples:
                deliveriesFound:
                  summary: One successful delivery
                  value:
                    data:
                      - card_payment_id: 100231
                        webhook_url: https://example.com/webhooks/datman
                        action: payment_success
                        payload:
                          order_id: "987654321"
                          amount: "24.50"
                        created_at: 2026-10-14T13:45:14.000Z
                        http_response_code: 200
                        omt: REF-10045
                noDeliveries:
                  summary: No webhooks recorded
                  value:
                    data: []
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: "API key callers only: the payment does not exist or its merchant
            is outside the key's reseller."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                transactionNotFound:
                  summary: Unknown or out-of-scope payment ID
                  value:
                    error:
                      code: NOT_FOUND
                      message: Transaction not found
        "422":
          description: The id is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidId:
                  summary: id is not a positive integer
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: id must be a positive integer
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/transactions/merchant-summary:
    post:
      operationId: getMerchantTransactionSummary
      summary: Get payment and refund totals for a merchant
      description: Returns the total of successful payments (net), the total refunded
        (including chargebacks), and the difference, for one merchant between
        fromDate and toDate (calendar dates, at most 90 days apart). For API key
        callers the reseller is taken from the key and the merchant must belong
        to it, otherwise 404. Body keys may be camelCase or snake_case.
      tags:
        - Balances
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CpMerchantSummaryRequest"
            examples:
              lastTwoWeeks:
                summary: Totals for one merchant over two weeks
                value:
                  merchantId: 123456
                  fromDate: 2026-10-01
                  toDate: 2026-10-14
                  timezone: Europe/London
      responses:
        "200":
          description: The merchant's totals. is_liable is true when the merchant is a
            liable account (totals then come from its own payments regardless of
            reseller scope). When the reseller has no queryable configuration
            the totals are zero and is_liable is omitted.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpMerchantTransactionSummaryResponse"
              examples:
                summaryFound:
                  summary: Totals for the window
                  value:
                    data:
                      payment_total: 1250.4
                      refund_total: 35
                      net: 1215.4
                      is_liable: false
                noScope:
                  summary: Reseller has no queryable configuration
                  value:
                    data:
                      payment_total: 0
                      refund_total: 0
                      net: 0
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          $ref: "#/components/responses/Forbidden"
        "404":
          description: API key callers only. The merchant is not mapped to the key's
            reseller.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                merchantNotFound:
                  summary: Unknown or out-of-scope merchant
                  value:
                    error:
                      code: NOT_FOUND
                      message: Merchant not found
        "422":
          description: The request body failed validation.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidMerchantId:
                  summary: merchantId missing or not numeric
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: merchantId must be an integer
                invalidFromDate:
                  summary: fromDate is not YYYY-MM-DD
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: fromDate must be YYYY-MM-DD
                rangeTooLong:
                  summary: Window longer than 90 days
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: Date range cannot exceed 90 days
                notAnObject:
                  summary: Body is missing or not a JSON object
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: Request body must be a JSON object
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          description: The summary query or a required configuration failed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                summaryFailed:
                  summary: Summary query failed
                  value:
                    error:
                      code: INTERNAL_ERROR
                      message: Summary query failed
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/onboarding/reseller-merchants-summary:
    post:
      operationId: getResellerMerchantsSummary
      summary: Get onboarding totals across the reseller's merchants
      description: "Returns counts of the reseller's merchants by onboarding state:
        total, fully verified, verification tier, staggered onboarding, and
        closed or suspended. For API key callers the reseller is always taken
        from the key; `resellerId` may be omitted, and if sent it must match or
        the response is 403. The body must be valid JSON, so send `{}` when
        there is nothing to pass."
      tags:
        - Reseller portfolio
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CpResellerMerchantsSummaryRequest"
            examples:
              keyScope:
                summary: Use the API key's reseller
                value: {}
              explicitReseller:
                summary: Name the reseller explicitly (must match the key)
                value:
                  resellerId: 8007
      responses:
        "200":
          description: Onboarding counts for the reseller's merchants.
          headers:
            X-Onboarding-Cache:
              description: HIT when served from the in-memory cache, otherwise MISS.
              schema:
                type: string
                enum:
                  - HIT
                  - MISS
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpResellerMerchantsSummaryResponse"
              examples:
                summaryFound:
                  summary: Portfolio onboarding counts
                  value:
                    data:
                      summary:
                        total_merchants: 42
                        staggered_onboarding: "30"
                        up_to1000: "8"
                        up_to5000: "12"
                        fully_verified: "25"
                        closed_or_suspended: "3"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: The API key has no reseller, or the body names a different reseller
            than the key's.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                resellerMismatch:
                  summary: resellerId does not match the key
                  value:
                    error:
                      code: FORBIDDEN
                      message: Access denied to this reseller
        "422":
          description: The body is not valid JSON, or resellerId is not a positive integer.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidJson:
                  summary: Body missing or not JSON
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: Invalid JSON body
                invalidResellerId:
                  summary: resellerId is not a positive integer
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: Invalid reseller_id
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /v1/onboarding/reseller-merchants-onboarding-status:
    post:
      operationId: listResellerMerchantsOnboardingStatus
      summary: List onboarding status for the reseller's merchants
      description: "Returns the onboarding record of each of the reseller's merchants:
        business, owner, bank, payout, account and terms-of-service status,
        verification tier, outstanding errors, onboarding links and tags, plus
        every tag the reseller has defined. Set `enablePagination: true` to
        page, search, sort and filter; without it every merchant is returned and
        only `isLiableOnly` and sorting apply. For API key callers the reseller
        is always taken from the key; `resellerId` is optional and must match if
        sent."
      tags:
        - Reseller portfolio
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CpResellerMerchantsStatusRequest"
            examples:
              firstPage:
                summary: First page of 20, newest first
                value:
                  enablePagination: true
                  page: 1
                  limit: 20
              searchActive:
                summary: Search active merchants by name or ID
                value:
                  enablePagination: true
                  page: 1
                  limit: 10
                  search: example pizza
                  activeOnly: true
                  sortField: createdAt
                  sortOrder: desc
              wholePortfolio:
                summary: Every merchant, no pagination
                value: {}
      responses:
        "200":
          description: Merchant onboarding rows, all tags defined by the reseller, and the
            total. With pagination, `total` is the number of matching merchants
            across all pages; without it, `total` is the number of rows
            returned.
          headers:
            X-Onboarding-Cache:
              description: HIT when served from the in-memory cache, otherwise MISS.
              schema:
                type: string
                enum:
                  - HIT
                  - MISS
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CpResellerMerchantsStatusResponse"
              examples:
                merchantsFound:
                  summary: One page with one merchant
                  value:
                    data:
                      rows:
                        - id: 5501
                          merchant_id: 123456
                          account_holder_id: AH00000000000000000000001
                          reseller_name: Example Reseller Ltd
                          country: United Kingdom
                          merchant_name: Example Pizza Co
                          trading_name: Example Pizza Co
                          business_status: 1
                          owner_status: 1
                          bank_status: 0
                          payout_status: 0
                          account_status: 1
                          tos_status: 1
                          verification_tier: Tier 1
                          internal_tags: null
                          onboarding_link: https://onboarding.example.com/a1b2c3d4
                          overview_page: null
                          average_weekly_orders: 120
                          due_in_days: 14
                          raw_data: null
                          list_of_errors: null
                          note: null
                          get_all_low_errors: null
                          is_reseller: 0
                          created_at: 2026-09-02T10:15:00.000Z
                          hosted_onboarding_enabled: 1
                      all_tags: []
                      total: 1
                      summary: null
        "401":
          $ref: "#/components/responses/Unauthorized"
        "403":
          description: The API key has no reseller, or the body names a different reseller
            than the key's.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                resellerMismatch:
                  summary: resellerId does not match the key
                  value:
                    error:
                      code: FORBIDDEN
                      message: Access denied to this reseller
        "422":
          description: The request body failed validation.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalidJson:
                  summary: Body missing or not JSON
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: Invalid JSON body
                invalidSortField:
                  summary: Unsupported sortField
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: "Invalid sortField: merchantName"
                invalidSortOrder:
                  summary: sortOrder is not asc or desc
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: "Invalid sortOrder: newest"
                invalidResellerId:
                  summary: resellerId is not a positive integer
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: Invalid reseller_id
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/InternalError"
        "503":
          $ref: "#/components/responses/ServiceUnavailable"
    servers:
      - url: https://sandbox-portal.datmanlabs.com/api
        description: Sandbox
  /api/v1/merchants/merchant-association:
    post:
      operationId: merchantAssociation
      summary: Create, reactivate or update a merchant association
      description: Single entry point for partner merchant lifecycle actions selected
        by `action`. `create` onboards a new merchant (or associates a store
        with an existing user), `reactivate` extends an expired signup link, and
        `update` changes the credentials of a user who has not yet completed
        signup.
      tags:
        - Merchant association
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantAssociationRequest"
            examples:
              create:
                summary: Create a merchant for a store
                value:
                  action: create
                  storeId: "123456"
                  isPartner: false
                  email: owner@example.com
                  phoneNumber: "+447700900000"
                  country: United Kingdom
                  firstName: Jane
                  lastName: Doe
                  businessName: Example Foods Ltd
                  tradingName: Example Foods
                  changeOfownership: false
                  isReseller: false
                  businessType: Limited
                  platform:
                    - 1
                    - 2
                  webhookUrl: https://partner.example.com/webhooks/onboarding
              reactivate:
                summary: Reactivate a signup link
                value:
                  action: reactivate
                  merchantId: "1000001"
              update:
                summary: Update pending user credentials
                value:
                  action: update
                  oldCredentials:
                    email: old@example.com
                    phoneNumber: ""
                  newCredentials:
                    email: new@example.com
                    phoneNumber: ""
      responses:
        "200":
          description: Action processed. Note that some business-rule outcomes (for
            example user not found or update limit exhausted on `update`) are
            also returned with HTTP 200 and a Datman internal `statusCode`
            (4005-4009) in the body.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantAssociationResponse"
              examples:
                merchantCreated:
                  summary: New merchant created
                  value:
                    message: New merchant account has been created and has been added to the
                      owner@example.com
                    merchantId: 1000001
                    merchant_status: 0
                    account_verification_status: false
                    bank_verification_status: false
                    email: owner@example.com
                    responseCode: 1001
                    businessName: Example Foods Ltd
                    tradingName: Example Foods
                    signup_link: https://portal.example.com/example-partner
        "400":
          description: Request body failed Joi validation, or a business rule rejected it
            (for example store already associated, reseller country mismatch,
            invalid merchant type configuration).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantAssociationError"
              examples:
                missingEmail:
                  summary: Validation error (email missing on create)
                  value:
                    message: "'email' is a mandatory field when creating a record. Please include
                      your email address."
        "401":
          description: Missing or invalid `api_key` header.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvalidApiKeyError"
        "429":
          description: Rate limit exceeded for repeated requests with the same reference.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RateLimitExceededError"
        "500":
          description: Unexpected server error.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ServerError"
    servers:
      - url: https://portal-api-sandbox.datmancrm.com/merchants/sandbox
        description: Sandbox
      - url: https://portal-api.datmancrm.com/merchants/prod
        description: Production
  /api/v1/merchants/merchant-account-status/{merchantId}:
    get:
      operationId: getMerchantAccountStatus
      summary: Get merchant account status
      description: Returns the onboarding, bank and account verification status of a
        merchant associated with the calling partner, plus outstanding
        verification issues and the merchant's fee tier.
      tags:
        - Onboarding status
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Datman merchant ID.
          schema:
            type: string
            pattern: ^\d+$
          example: "1000001"
      responses:
        "200":
          description: Merchant status.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantAccountStatusResponse"
              examples:
                activeMerchant:
                  summary: Active, fully verified merchant
                  value:
                    status: Active
                    bank_verification_status: Verified
                    account_verification_status: Verified
                    verification_status:
                      account_status: ACTIVE
                      payout_status: ACTIVE
                      issues: []
                      verification_tier: T1
                    feeTier:
                      - id: 2
        "401":
          description: Missing or invalid `api_key` header.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UnauthorisedError"
        "404":
          description: Merchant does not exist or is not associated with the caller's
            customer type.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantNotFoundError"
              examples:
                merchantNotFound:
                  summary: Merchant not found for this partner
                  value:
                    message: Merchant not found
                    statusCode: 7001
        "500":
          description: Unexpected server error.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ServerError"
    servers:
      - url: https://portal-api-sandbox.datmancrm.com/merchants/sandbox
        description: Sandbox
      - url: https://portal-api.datmancrm.com/merchants/prod
        description: Production
  /api/v1/merchants/merchant-associationV2:
    post:
      operationId: merchantAssociationV2
      summary: Create, reactivate, update, patch or upload documents for a merchant (V2)
      description: Version 2 of the merchant association endpoint. The `action` field
        picks the operation. `create` onboards a merchant and also accepts full
        onboarding sections (`bankDetails`, `businessDetails`, `ownerDetails`,
        `tradingDetails`, `businessDealDetails`). `reactivate` extends an
        expired signup link. `update` changes the credentials of a user who has
        not yet completed signup. `patch` fills in onboarding data for an
        existing merchant. `uploadDocuments` queues up to 5 base64-encoded KYC
        documents for the merchant and returns HTTP 202.
      tags:
        - Merchant association
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MerchantAssociationV2Request"
            examples:
              createWithDetails:
                summary: Create a merchant with onboarding details
                value:
                  action: create
                  storeId: "123456"
                  isPartner: false
                  email: owner@example.com
                  phoneNumber: "+447700900000"
                  country: United Kingdom
                  firstName: Jane
                  lastName: Doe
                  businessName: Example Foods Ltd
                  tradingName: Example Foods
                  changeOfownership: false
                  isReseller: false
                  businessType: Limited
                  platform:
                    - 1
                  webhookUrl: https://partner.example.com/webhooks/onboarding
                  bankDetails:
                    accountName: EXAMPLE FOODS LTD
                    bankSortCode: "000000"
                    ibanNumber: ""
                    bsbNumber: ""
                    transitNumber: ""
                    financialInstitutionNumber: ""
                    routingNumber: ""
                    accountNumber: "00000000"
                    bankName: Example Bank
                    address:
                      addressLine1: 1 Example Street
                      addressLine2: ""
                  businessDetails:
                    businessType: Limited
                    companyRegistrationNumber: "00000000"
                    organisationType: Private Company
                    trustType: Other Trust
                    address:
                      addressLine1: 1 Example Street
                      addressLine2: ""
                      state: ""
                      city: London
                      county: Greater London
                      country: United Kingdom
                      postCode: SW1A 1AA
                    contact:
                      phoneNumber: "+447700900000"
                      email: owner@example.com
                      website: https://www.example.com
                  ownerDetails:
                    title: Ms
                    firstName: Jane
                    lastName: Doe
                    citizenship: British
                    dateOfBirth: 1985-01-31
                    abnNumber: ""
                    einNumber: ""
                    ssnNumber: ""
                    personalId: ""
                    ppsNumber: ""
                    vatNumber: ""
                    vatExists: false
                    address:
                      addressLine1: 1 Example Street
                      addressLine2: ""
                      state: ""
                      city: London
                      county: Greater London
                      country: United Kingdom
                      postCode: SW1A 1AA
                    contact:
                      phoneNumber: "+447700900000"
                      email: owner@example.com
                  tradingDetails:
                    name: Example Foods
                    address:
                      addressLine1: 1 Example Street
                      addressLine2: ""
                      state: ""
                      city: London
                      county: Greater London
                      country: United Kingdom
                      postCode: SW1A 1AA
                  businessDealDetails:
                    setupFee: "0"
                    monthlyRent: "0"
                    contractDurationMonths: "12"
                    fixedTransactionFee: "0.20"
                    interchangeRate: "1.50"
              reactivate:
                summary: Reactivate a signup link
                value:
                  action: reactivate
                  merchantId: "1000001"
              update:
                summary: Update pending user credentials
                value:
                  action: update
                  oldCredentials:
                    email: old@example.com
                    phoneNumber: ""
                  newCredentials:
                    email: new@example.com
                    phoneNumber: ""
              patch:
                summary: Fill in missing onboarding fields
                value:
                  action: patch
                  merchantId: "1000001"
                  overrideDetails: false
                  isSyncEnabled: true
                  businessDetails:
                    contact:
                      website: https://www.example.com
                  ownerDetails:
                    dateOfBirth: 1985-01-31
              uploadDocuments:
                summary: Upload a KYC document
                value:
                  action: uploadDocuments
                  merchantId: "1000001"
                  attachments:
                    - documentTypeId: 1
                      filename: passport.pdf
                      content: JVBERi0xLjQKJcfsj6IKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c+PgplbmRvYmoK
      responses:
        "200":
          description: "Action processed (create, reactivate, update or patch). Some
            business-rule outcomes also come back as HTTP 200: `update` with a
            Datman internal `statusCode` 4005-4009, `reactivate` when the
            merchant or link isn't found, and every `patch` failure (merchant
            not found, nothing to update, validation errors)."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantAssociationV2Response"
              examples:
                merchantCreated:
                  summary: New merchant created with onboarding details
                  value:
                    message: New merchant account has been created and has been added to the
                      owner@example.com
                    merchantId: 1000001
                    merchant_status: 0
                    account_verification_status: false
                    bank_verification_status: false
                    email: owner@example.com
                    responseCode: 1002
                    businessName: Example Foods Ltd
                    tradingName: Example Foods
                    signup_link: https://portal.example.com/example-partner
                patchApplied:
                  summary: Patch applied, one existing field skipped
                  value:
                    message: Merchant details updated successfully.
                    merchantId: "1000001"
                    skippedFields:
                      - ownerDetails.dateOfBirth
                    skippedMessage: Patch operation allowed only on empty fields. Existing values
                      are immutable
                patchNothingToUpdate:
                  summary: Patch with no applicable fields
                  value:
                    message: No applicable fields to update.
                    merchantId: "1000001"
                credentialsUpdated:
                  summary: Credentials updated
                  value:
                    message: The user credentials have been successfully updated.
                    statusCode: 6003
        "202":
          description: "`uploadDocuments` accepted. The documents are stored and queued
            for processing. If a webhook is configured, the result is sent
            there."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantUploadDocumentsAccepted"
              examples:
                accepted:
                  summary: Documents accepted
                  value:
                    message: Your document will be attached to this merchant shortly. We will notify
                      you via webhook if configured when processing completes.
                    statusCode: 10005
                acceptedPendingOtherSide:
                  summary: Front of a two-sided document accepted
                  value:
                    message: Your document will be attached to this merchant shortly. We will notify
                      you via webhook if configured when processing completes.
                    reminder: You uploaded the front of your driving licence. Please also upload the
                      back using document type 17 when you can.
                    statusCode: 10006
        "400":
          description: Invalid JSON, failed schema validation, a missing onboarding
            section on `create`, bank details that could not be decrypted, a
            rejected document upload, or a business rule (store already
            associated, invalid reseller ID, reseller country mismatch).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MerchantAssociationV2Error"
              examples:
                validationFailed:
                  summary: Schema validation error
                  value:
                    message: Some of the information you sent could not be accepted. Please review
                      the items below, fix any issues, and try again.
                    statusCode: 10110
                    details:
                      - path: email
                        message: "'email' is a mandatory field when creating a record. Please include
                          your email address."
                missingSection:
                  summary: Onboarding section missing on create
                  value:
                    message:
                      - key: bankDetails
                        error: Bank details are mandatory.
                invalidJson:
                  summary: Body is not valid JSON
                  value:
                    message: Invalid JSON format in request body
                    statusCode: 9001
                storeAlreadyAssociated:
                  summary: Store already associated
                  value:
                    message: This store is already associated with an active merchant!
                    merchantId: 1000001
                documentRejected:
                  summary: Document content does not match its extension
                  value:
                    message: "Attachment content does not match file extension for documentTypeId 1.
                      Allowed extensions: .pdf, .jpg, .jpeg, .png"
                    statusCode: 10111
        "401":
          description: Missing or invalid `api_key` header.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvalidApiKeyError"
              examples:
                invalidKey:
                  summary: Invalid API key
                  value:
                    message: Invalid API key
                    errorCode: 1019
        "429":
          description: Rate limit exceeded for repeated requests with the same store ID or
            client IP.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RateLimitExceededError"
        "500":
          description: Unexpected server error.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ServerError"
    servers:
      - url: https://portal-api-sandbox.datmancrm.com/merchants/sandbox
        description: Sandbox
      - url: https://portal-api.datmancrm.com/merchants/prod
        description: Production
  /api/v1/documents/upload-document/{merchantId}:
    servers:
      - url: https://portal-api-sandbox.datmancrm.com/documents/sandbox
        description: Sandbox
      - url: https://portal-api.datmancrm.com/documents/prod
        description: Production
    post:
      operationId: uploadOnboardingDocument
      summary: Upload a KYC document for a merchant
      description: Uploads one onboarding (KYC) document for a merchant as
        multipart/form-data. The new document replaces any earlier document of
        the same type and is set to need approval. Only merchants created
        through the merchant association API can receive documents.
      tags:
        - KYC documents
      security:
        - DocumentUploadApiKey: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Datman merchant ID.
          schema:
            type: string
            pattern: ^\d+$
          example: "1000001"
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: "#/components/schemas/DocumentUploadForm"
            examples:
              passport:
                summary: Upload a passport scan
                value:
                  documentTypeId: 1
                  file: (binary PDF, 100 KB to 10 MB)
      responses:
        "200":
          description: 'Document uploaded. The body is JSON-encoded twice: it decodes to
            the JSON string `"success"` (including the quote characters).'
          content:
            application/json:
              schema:
                type: string
              examples:
                success:
                  summary: Upload succeeded
                  value: '"success"'
        "400":
          description: Multipart body could not be parsed, more than one file was sent, or
            the form failed validation (file type, 100 KB to 10 MB size,
            documentTypeId 1-15).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MessageError"
              examples:
                fileTooSmall:
                  summary: File size out of range
                  value:
                    message: File size must be between 100kb to 10mb.
                tooManyFiles:
                  summary: More than one file
                  value:
                    message: You can only upload one document at a time
        "401":
          description: Missing or wrong `api_key` header.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MessageError"
              examples:
                unauthorized:
                  summary: Wrong document upload key
                  value:
                    message: UNAUTHORIZED
        "404":
          description: "The merchant was not created through the merchant association API.
            The body is JSON-encoded twice: it decodes to a string that holds a
            JSON object."
          content:
            application/json:
              schema:
                type: string
              examples:
                notAssociated:
                  summary: Merchant not created by the association API
                  value: '{"message":"Document upload is allowed only for merchants created by MID
                    creation API"}'
        "429":
          description: Rate limit exceeded for the client IP. The body is a bare JSON
            string.
          content:
            application/json:
              schema:
                type: string
              examples:
                rateLimited:
                  summary: Rate limit exceeded
                  value: Too many requests with the same reference
        "500":
          description: Unexpected server error.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ServerError"
  /api/v1/bifrost/get-embed-token/{merchantId}:
    servers:
      - url: https://portal-api-sandbox.datmancrm.com/bifrost/sandbox
        description: Sandbox
      - url: https://portal-api.datmancrm.com/bifrost/prod
        description: Production
    get:
      operationId: getEmbedToken
      summary: Get an embedded dashboard session token
      description: Creates a short-lived (10 minute) session for the embedded merchant
        dashboard and returns its token. The merchant must belong to the calling
        partner.
      tags:
        - Embedded dashboard
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Datman merchant ID.
          schema:
            type: string
          example: "1000001"
      responses:
        "200":
          description: Session token created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmbedTokenResponse"
              examples:
                token:
                  summary: Session token
                  value:
                    token: 0123456789abcdef0123456789abcdef
                    expiresAt: 1767225600
        "401":
          description: Missing or invalid `api_key` header.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UnauthorisedError"
              examples:
                unauthorised:
                  summary: Unauthorised
                  value:
                    message: UNAUTHORISED
        "404":
          description: Merchant does not exist or does not belong to the calling partner.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MessageError"
              examples:
                notFound:
                  summary: Merchant not found
                  value:
                    message: Merchant does not exist
        "500":
          description: Unexpected server error. The body is the serialised error object,
            usually empty.
          content:
            application/json:
              schema:
                type: object
  /api/v1/bifrost/get-embededurl/{merchantId}/{page}:
    servers:
      - url: https://portal-api-sandbox.datmancrm.com/bifrost/sandbox
        description: Sandbox
      - url: https://portal-api.datmancrm.com/bifrost/prod
        description: Production
    get:
      operationId: getEmbedUrl
      summary: Get an embedded dashboard URL
      description: Creates a short-lived (10 minute) session for the embedded merchant
        dashboard and returns a ready-to-load URL for the requested page. The
        merchant must belong to the calling partner.
      tags:
        - Embedded dashboard
      security:
        - ApiKeyAuth: []
      parameters:
        - name: merchantId
          in: path
          required: true
          description: Datman merchant ID.
          schema:
            type: string
          example: "1000001"
        - name: page
          in: path
          required: true
          description: Dashboard page to open.
          schema:
            type: string
            enum:
              - overview
              - payment
              - payout
          example: overview
      responses:
        "200":
          description: Embed URL created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EmbedUrlResponse"
              examples:
                url:
                  summary: Embed URL for the overview page
                  value:
                    url: https://embed.example.com/overview?token=0123456789abcdef0123456789abcdef
                    expiresAt: 1767225600
        "401":
          description: Missing or invalid `api_key` header, or an unknown `page`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MessageError"
              examples:
                unauthorised:
                  summary: Unauthorised
                  value:
                    message: UNAUTHORISED
                unknownPage:
                  summary: Unknown page
                  value:
                    message: Page does not exist
        "404":
          description: Merchant does not exist or does not belong to the calling partner.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MessageError"
              examples:
                notFound:
                  summary: Merchant not found
                  value:
                    message: Merchant does not exist
        "500":
          description: Unexpected server error. The body is the serialised error object,
            usually empty.
          content:
            application/json:
              schema:
                type: object
  /opto/card.php:
    servers:
      - url: https://sandbox-payments.datmanpay.com
        description: Sandbox
      - url: https://payments.datmanpay.com
        description: Production
    get:
      operationId: hostedPaymentPage
      summary: Open the hosted payment form (Sale)
      description: >-
        Redirect the shopper's browser to this URL to take a card payment on
        Datman's hosted payment form. Build the URL on your server: encrypt a
        `HostedPaymentPayload` (the order, the shopper and your redirect and
        webhook URLs) with your secret key, and pass it as `data` together with
        your `pub_key`. There is no API key header.


        After the payment the shopper is sent to `redirect_url` (success) or
        `cancel_url` (cancelled). Always take the final status from the [payment
        status webhook](/api-explorer/webhooks/1/webhook/paymentStatus) sent to
        `webhook_url`, not from the redirect. See the [Hosted payment
        guide](/docs/hosted-payment) for the encryption code.
      tags:
        - Hosted Payment
      x-playground: false
      x-guide: /docs/hosted-payment
      security: []
      parameters:
        - name: data
          in: query
          required: true
          description: Your `HostedPaymentPayload` as JSON, encrypted with AES-256-CBC
            using your secret key, then base64-encoded twice (see the guide).
            URL-encode it when you build the URL.
          schema:
            type: string
            contentEncoding: base64
            contentMediaType: application/json
            contentSchema:
              $ref: "#/components/schemas/HostedPaymentPayload"
          examples:
            sale:
              summary: Encrypted sale payload (dummy value)
              value: RW5jcnlwdGVkUGF5bG9hZEdvZXNIZXJl
        - name: pub_key
          in: query
          required: true
          description: Your public key, issued by Datman together with your secret key.
            Datman uses it to find the secret that decrypts `data`.
          schema:
            type: string
          examples:
            sale:
              summary: Your public key (dummy value)
              value: pk_test_example
      responses:
        "200":
          description: An HTML page that sends the shopper's browser straight on to the
            payment form. If the request can't be processed, the page shows an
            error message instead, for example "Unable to process this request!"
            (a required key is missing, or `data` doesn't decrypt with your
            secret) or "Online payment not available for this merchant
            account!".
          content:
            text/html:
              schema:
                type: string
              examples:
                redirect:
                  summary: Shopper forwarded to the payment form
                  value: <meta http-equiv='refresh' content='0;url=https://...'>
                requestError:
                  summary: Missing key or wrong secret
                  value: <html><center><h2>Unable to process this request!</h2></center></html>
                notAvailable:
                  summary: Online payments switched off for the merchant
                  value: <html><center><h2>Online payment not available for this merchant
                    account!</h2></center></html>
        "301":
          description: The browser is redirected (`Location` header) to the payment form
            instead. It follows this automatically; nothing changes for you.
          headers:
            Location:
              description: Where the browser goes next.
              schema:
                type: string
  /api2.php?action=refund:
    servers:
      - url: https://sandbox-payments.datmanpay.com
        description: Sandbox
      - url: https://payments.datmanpay.com
        description: Production
    post:
      operationId: refundPayment
      summary: Refund a payment
      description: >-
        Refunds all or part of a payment, identified by your `order_id` and the
        `merchant_id`. The refund can't be more than what's left to refund on
        the payment. If the payment was only authorised (a pre-auth), it is
        captured in full first and then refunded.


        **Errors are returned with HTTP 200.** Check `outcome` in the body: it
        is `success` or `failed`, and `message` explains a failure. This
        includes an invalid or missing `api_token`.
      tags:
        - Payment modifications
      security:
        - ApiTokenAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/RefundRequest"
            examples:
              refund:
                summary: Partial refund to card
                value:
                  merchant_id: "663412"
                  order_id: "100245"
                  amount: 10.5
                  reason: Item out of stock
              refundWithSplit:
                summary: Refund with split refunds
                value:
                  merchant_id: "663412"
                  order_id: "100246"
                  amount: 20
                  reason: Order cancelled
                  refund_split_fee:
                    - partner_merchant_id: 663500
                      refund_amount: 3.5
      responses:
        "200":
          description: The refund result (`outcome` is `success`), or why it failed
            (`outcome` is `failed`).
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/RefundResponse"
                  - $ref: "#/components/schemas/PaymentModificationFailedResponse"
              examples:
                refunded:
                  summary: Refund succeeded
                  value:
                    outcome: success
                    destination:
                      CARD: "10.50"
                    transaction_methods:
                      ECOM: "24.50"
                preAuthRefund:
                  summary: Refund of an uncaptured pre-auth
                  value:
                    outcome: success
                    message: "Pre-auth transaction: will be captured and then refunded"
                    destination:
                      CARD: "10.50"
                    transaction_methods:
                      ECOM: "24.50"
                refundTooHigh:
                  summary: Refund amount too high
                  value:
                    outcome: failed
                    message: Refund amount (30.00) cannot be greater than the original transaction
                      amount (24.50).
                alreadyRefunded:
                  summary: Already refunded
                  value:
                    outcome: failed
                    message: "Transaction already refunded: Item out of stock"
                invalidToken:
                  summary: Missing or invalid api_token
                  value:
                    outcome: failed
                    message: Token is empty or Invalid token
  /api2.php?action=capture:
    servers:
      - url: https://sandbox-payments.datmanpay.com
        description: Sandbox
      - url: https://payments.datmanpay.com
        description: Production
    post:
      operationId: capturePayment
      summary: Capture a pre-authorised payment
      description: >-
        Captures a payment that was only authorised (a pre-auth). The amount can
        be equal to or less than the authorised amount. Identify the payment by
        its `xref` (`O<order_id>M<merchant_id>T<payment_id>`), which you receive
        in the payment status webhook.


        Validation errors are returned with HTTP 200 and `outcome: failed`. When
        the request reaches the payment provider, its HTTP status is returned:
        201 when accepted, or an error status. `outcome` is then `success` even
        if the provider returned an error.
      tags:
        - Payment modifications
      security:
        - ApiTokenAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CaptureOrAdjustmentRequest"
            examples:
              capture:
                summary: Capture the full amount
                value:
                  xref: O100247M663412T4821940
                  merchant_id: "663412"
                  amount: 24.5
      responses:
        "200":
          description: The request failed before reaching the payment provider.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentModificationFailedResponse"
              examples:
                captureTooHigh:
                  summary: Capture amount too high
                  value:
                    outcome: failed
                    code: 400
                    message: Capture amount cannot be greater than the authorised amount of 24.50
                notFound:
                  summary: Payment not found
                  value:
                    outcome: failed
                    message: No record found for the given order_id
                invalidToken:
                  summary: Missing or invalid api_token
                  value:
                    outcome: failed
                    message: Token is empty or Invalid token
        "201":
          description: The payment provider accepted the capture.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentModificationAcceptedResponse"
              examples:
                captureReceived:
                  summary: Capture received
                  value:
                    outcome: success
                    payment_reference: QFQTPCQ8HXSKGK82
                    status: received
                    amount: 24.5
        "500":
          $ref: "#/components/responses/PaymentModificationProviderFailed"
  /api2.php?action=adjustment:
    servers:
      - url: https://sandbox-payments.datmanpay.com
        description: Sandbox
      - url: https://payments.datmanpay.com
        description: Production
    post:
      operationId: adjustPaymentAmount
      summary: Adjust the amount of a pre-authorised payment
      description: >-
        Changes the authorised amount of a pre-auth before it's captured, for
        example when the final order total differs. Identify the payment by its
        `xref` (`O<order_id>M<merchant_id>T<payment_id>`). Pass `split_fee` to
        change the splits; without it the existing splits are kept.


        Validation errors are returned with HTTP 200 and `outcome: failed`. When
        the request reaches the payment provider, its HTTP status is returned:
        201 when accepted, 422 when refused, or an error status. `outcome` is
        then `success` even if the provider returned an error.
      tags:
        - Payment modifications
      security:
        - ApiTokenAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CaptureOrAdjustmentRequest"
            examples:
              adjustment:
                summary: Increase the authorised amount
                value:
                  xref: O100247M663412T4821940
                  merchant_id: "663412"
                  amount: 27.75
      responses:
        "200":
          description: The request failed before reaching the payment provider.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentModificationFailedResponse"
              examples:
                overLimit:
                  summary: Amount over the merchant's limit
                  value:
                    outcome: failed
                    code: 1006
                    message: Amount exceeds the limit
                splitTooHigh:
                  summary: Splits too high
                  value:
                    outcome: failed
                    code: 400
                    message: Total split cannot be greater than or equal to order value (30.00 /
                      27.75)
                notFound:
                  summary: Payment not found
                  value:
                    outcome: failed
                    message: No record found for the given order_id
        "201":
          description: The payment provider accepted the adjustment.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentModificationAcceptedResponse"
              examples:
                adjustmentAuthorised:
                  summary: Adjustment authorised
                  value:
                    outcome: success
                    payment_reference: QFQTPCQ8HXSKGK82
                    status: authorised
                    amount: 27.75
        "422":
          description: The payment provider refused the adjustment. `outcome` is still
            `success`; read `message` and `reason`.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentModificationProviderError"
              examples:
                refused:
                  summary: Adjustment refused
                  value:
                    outcome: success
                    request_id: 5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    message: Amount adjustment refused
                    resultCode: Refused
                    reason: Refused
        "500":
          $ref: "#/components/responses/PaymentModificationProviderFailed"
  /api2.php?action=auth_reversal:
    servers:
      - url: https://sandbox-payments.datmanpay.com
        description: Sandbox
      - url: https://payments.datmanpay.com
        description: Production
    post:
      operationId: reversePaymentAuthorisation
      summary: Reverse a pre-authorisation
      description: >-
        Cancels a payment that was authorised but not captured, releasing the
        hold on the shopper's funds. Identify the payment by its `xref`
        (`O<order_id>M<merchant_id>T<payment_id>`).


        Validation errors are returned with HTTP 200 and `outcome: failed`. When
        the request reaches the payment provider, its HTTP status is returned:
        201 when accepted, or an error status. `outcome` is then `success` even
        if the provider returned an error.
      tags:
        - Payment modifications
      security:
        - ApiTokenAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/AuthReversalRequest"
            examples:
              authReversal:
                summary: Reverse a pre-auth
                value:
                  xref: O100247M663412T4821940
                  merchant_id: "663412"
      responses:
        "200":
          description: The request failed before reaching the payment provider.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentModificationFailedResponse"
              examples:
                inProgress:
                  summary: Reversal already in progress
                  value:
                    outcome: failed
                    message: Auth reversal already in progress
                completed:
                  summary: Already reversed
                  value:
                    outcome: failed
                    message: Auth reversal already completed
        "201":
          description: The payment provider accepted the reversal.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaymentModificationAcceptedResponse"
              examples:
                reversalReceived:
                  summary: Auth reversal received
                  value:
                    outcome: success
                    payment_reference: QFQTPCQ8HXSKGK82
                    status: received
        "500":
          $ref: "#/components/responses/PaymentModificationProviderFailed"
  /api/v1/transfer/internal:
    servers:
      - url: https://sandbox-payments.datmanpay.com/rest
        description: Sandbox (base path from docs; verify)
      - url: https://payments.datmanpay.com/rest
        description: Production (base path inferred; verify)
    post:
      operationId: createInternalTransfer
      summary: Transfer funds between two merchants
      description: >-
        Moves `amount` from the source merchant's balance to the destination
        merchant's balance. Both merchants must be enabled for internal
        transfers and be in the same country.


        The transfer is processed asynchronously: the response only confirms it
        was accepted. Datman then sends a [transfer
        succeeded](/api-explorer/transfers/1/webhook/internalTransferSucceeded)
        or [transfer
        failed](/api-explorer/transfers/1/webhook/internalTransferFailed)
        webhook to `webhook_url`.
      tags:
        - Internal transfers
      security:
        - ApiTokenAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InternalTransferRequest"
            examples:
              deliveryFee:
                summary: Transfer a delivery fee
                value:
                  source_merchant_id: "663412"
                  destination_merchant_id: "663500"
                  amount: 350
                  transfer_category_code: 1
                  description: Delivery fee for order ORD-100245
                  reference: REF-100245-DLV
                  webhook_url: https://partner.example.com/webhooks/transfers
                  order_id: ORD-100245
      responses:
        "202":
          description: The transfer was accepted and is being processed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InternalTransferAccepted"
              examples:
                accepted:
                  summary: Transfer accepted
                  value:
                    request_id: 3f1c2b6a-8d4e-4f0a-9b7c-1e2d3c4b5a69
                    reference: REF-100245-DLV
                    status: processing
        "400":
          description: The request is invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorCodeResponse"
              examples:
                sameMerchant:
                  summary: Same source and destination
                  value:
                    error_code: SAME_SOURCE_AND_DESTINATION_MERCHANT
                    message: Source and destination merchant cannot be the same
                validation:
                  summary: Validation error
                  value:
                    message: '"Source Merchant ID" is required'
        "401":
          description: The `api_token` header is missing or invalid.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorCodeResponse"
              examples:
                invalidToken:
                  summary: Missing or invalid api_token
                  value:
                    error_code: UNAUTHORIZED
                    message: Token is empty or Invalid token
        "403":
          description: "The transfer isn't allowed: a merchant isn't enabled for internal
            transfers, the merchants are in different countries or have
            different customer types, internal transfers aren't enabled for the
            country, or the amount is over the limit."
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorCodeResponse"
              examples:
                senderNotEnabled:
                  summary: Source merchant not enabled
                  value:
                    error_code: INTERNAL_TRANSFER_SENDER_NOT_ENABLED
                    message: Internal transfer sender feature is not enabled for this merchant
                overLimit:
                  summary: Amount over the limit
                  value:
                    error_code: AMOUNT_EXCEEDED_THRESHOLD
                    message: Cannot transfer amount exceeding the threshold limit
                differentCountry:
                  summary: Merchants in different countries
                  value:
                    error_code: MERCHANTS_DIFFERENT_COUNTRY
                    message: Source and destination merchants must belong to the same country
        "404":
          description: The source or destination merchant doesn't exist.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorCodeResponse"
              examples:
                sourceNotFound:
                  summary: Source merchant not found
                  value:
                    error_code: SOURCE_MERCHANT_NOT_FOUND
                    message: Source merchant not found
                destinationNotFound:
                  summary: Destination merchant not found
                  value:
                    error_code: DESTINATION_MERCHANT_NOT_FOUND
                    message: Destination merchant not found
        "500":
          description: Internal server error.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MessageResponse"
              example:
                message: Unable to process your request at the moment. Please try again later.
  /api/v1/split-commission-types:
    servers:
      - url: https://sandbox-payments.datmanpay.com/rest
        description: Sandbox (base path from docs; verify)
      - url: https://payments.datmanpay.com/rest
        description: Production (base path inferred; verify)
    get:
      operationId: listSplitCommissionTypes
      summary: List split commission types
      description: "Returns the commission types you can use in a split: the `global`
        types every partner can use, and the `custom` types you created. Pass
        `type_id` to return a single type."
      tags:
        - Split commission types
      security:
        - ApiTokenAuth: []
      parameters:
        - name: type_id
          in: query
          required: false
          description: Return only this commission type.
          schema:
            type: integer
          examples:
            single:
              summary: One commission type
              value: 3
      responses:
        "200":
          description: The commission types.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SplitCommissionTypeList"
              examples:
                list:
                  summary: Global and custom types
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: success
                    data:
                      custom:
                        - id: 104
                          commission_type: Packaging_Fee
                          business_provider: OMNICART
                          created_at: 2026-09-01T10:15:00.000Z
                          updated_at: 2026-09-01T10:15:00.000Z
                      global:
                        - id: 1
                          commission_type: Food_Goods
                          business_provider: null
                          created_at: 2023-01-01T00:00:00.000Z
                          updated_at: 2023-01-01T00:00:00.000Z
                        - id: 3
                          commission_type: Delivery_Fee
                          business_provider: null
                          created_at: 2023-01-01T00:00:00.000Z
                          updated_at: 2023-01-01T00:00:00.000Z
        "401":
          $ref: "#/components/responses/SplitCommissionUnauthorized"
        "404":
          description: The commission type doesn't exist.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OutcomeErrorResponse"
              examples:
                notFound:
                  summary: Type not found
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: failed
                    message: Split commission type not found
        "500":
          $ref: "#/components/responses/SplitCommissionServerError"
    post:
      operationId: createSplitCommissionType
      summary: Create a split commission type
      description: Creates a custom commission type. Names must be unique
        (case-insensitive) among your types, including deleted ones.
      tags:
        - Split commission types
      security:
        - ApiTokenAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SplitCommissionTypeRequest"
            examples:
              packagingFee:
                summary: Create a packaging fee type
                value:
                  commission_type: Packaging_Fee
      responses:
        "201":
          description: The commission type was created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SplitCommissionTypeResult"
              examples:
                created:
                  summary: Type created
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: success
                    data:
                      id: 104
                      commission_type: Packaging_Fee
                      business_provider: OMNICART
                      created_at: 2026-09-01T10:15:00.000Z
        "400":
          description: The name is missing or already used.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OutcomeErrorResponse"
              examples:
                missing:
                  summary: Name missing
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: failed
                    message: commission_type is required and must be a non-empty string
                duplicate:
                  summary: Name already used
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: failed
                    message: "Duplicate commission_type found. A commission type with the same name
                      already exists with ID: 104"
        "401":
          $ref: "#/components/responses/SplitCommissionUnauthorized"
        "500":
          $ref: "#/components/responses/SplitCommissionServerError"
  /api/v1/split-commission-types/{type_id}:
    servers:
      - url: https://sandbox-payments.datmanpay.com/rest
        description: Sandbox (base path from docs; verify)
      - url: https://payments.datmanpay.com/rest
        description: Production (base path inferred; verify)
    parameters:
      - name: type_id
        in: path
        required: true
        description: The id of one of your custom commission types (above 100).
        schema:
          type: integer
          minimum: 101
        examples:
          custom:
            summary: A custom type
            value: 104
    put:
      operationId: updateSplitCommissionType
      summary: Rename a split commission type
      description: Changes the name of one of your custom commission types. Built-in
        types (id 100 or below) can't be changed.
      tags:
        - Split commission types
      security:
        - ApiTokenAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SplitCommissionTypeRequest"
            examples:
              rename:
                summary: Rename a type
                value:
                  commission_type: Packaging_Charge
      responses:
        "200":
          description: The commission type was renamed.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SplitCommissionTypeResult"
              examples:
                updated:
                  summary: Type renamed
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: success
                    data:
                      id: 104
                      commission_type: Packaging_Charge
                      business_provider: OMNICART
                      created_at: 2026-09-01T10:15:00.000Z
                      updated_at: 2026-10-16T09:30:00.000Z
        "400":
          description: The name is missing or already used, or the type is built in.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OutcomeErrorResponse"
              examples:
                builtIn:
                  summary: Built-in type
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: failed
                    message: You do not have access to update split commission types with ID less
                      than or equal to 100
        "401":
          $ref: "#/components/responses/SplitCommissionUnauthorized"
        "404":
          description: The type doesn't exist or isn't yours.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OutcomeErrorResponse"
              examples:
                notFound:
                  summary: Type not found
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: failed
                    message: Split commission type not found or you do not have permission to update
                      it
        "500":
          $ref: "#/components/responses/SplitCommissionServerError"
    delete:
      operationId: deleteSplitCommissionType
      summary: Delete a split commission type
      description: Deletes one of your custom commission types. Built-in types (id 100
        or below) can't be deleted. A deleted type's name can't be reused.
      tags:
        - Split commission types
      security:
        - ApiTokenAuth: []
      responses:
        "200":
          description: The commission type was deleted.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OutcomeMessageResponse"
              examples:
                deleted:
                  summary: Type deleted
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: success
                    message: Split commission type deleted successfully
        "400":
          description: The type is built in.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OutcomeErrorResponse"
              examples:
                builtIn:
                  summary: Built-in type
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: failed
                    message: You do not have access to delete split commission types with ID less
                      than or equal to 100
        "401":
          $ref: "#/components/responses/SplitCommissionUnauthorized"
        "404":
          description: The type doesn't exist, is already deleted or isn't yours.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/OutcomeErrorResponse"
              examples:
                notFound:
                  summary: Type not found
                  value:
                    requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                    outcome: failed
                    message: Split commission type not found or already deleted or you do not have
                      permission to delete it
        "500":
          $ref: "#/components/responses/SplitCommissionServerError"
webhooks:
  paymentStatus:
    post:
      operationId: paymentStatusWebhook
      summary: Payment status notification
      description: Datman sends a JSON POST to your configured webhook URL when the
        status of a payment changes. Verify the `HMACSignature` header before
        trusting the payload.
      tags:
        - Webhooks
      security: []
      parameters:
        - name: HMACSignature
          in: header
          required: false
          description: HMAC-SHA256 of the JSON body using your webhook secret, hex-encoded.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PaymentStatusWebhook"
            examples:
              paymentAuthorised:
                summary: Payment authorised
                value:
                  order_id: ORD-100245
                  amount: "24.50"
                  currency: GBP
                  customer_id: CUST-55021
                  xref: O88213045M663412T4821937
                  status: authorisation
                  success: "true"
                  date: 2026-10-15T12:34:56+01:00
                  three_ds_authenticated: "true"
                  three_ds_authenticated_response: Y
                  card_bin: "411111"
                  last4_digits: "1111"
                  shopper_ip: 203.0.113.42
                  shopper_email: jane.doe@example.com
                  expiry_date: 03/2030
                  avs_result: 4 AVS not supported for this card type
                  cvc_result: 1 Matches
                  card_type: visa
              paymentRefused:
                summary: Payment refused
                value:
                  order_id: ORD-100246
                  amount: "24.50"
                  currency: GBP
                  customer_id: CUST-55021
                  xref: O88213046M663412T4821938
                  status: authorisation
                  success: "false"
                  date: 2026-10-15T12:34:56+01:00
                  three_ds_authenticated: "false"
                  three_ds_authenticated_response: N
                  card_bin: "411111"
                  last4_digits: "1111"
                  shopper_ip: 203.0.113.42
                  shopper_email: jane.doe@example.com
                  expiry_date: 03/2030
                  avs_result: 4 AVS not supported for this card type
                  cvc_result: 2 Does not match
                  card_type: visa
                  reason: CVC Declined
      responses:
        "200":
          description: Acknowledge receipt of the notification.
  internalTransferSucceeded:
    post:
      operationId: internalTransferSucceededWebhook
      summary: Internal transfer succeeded
      description: Datman sends a JSON POST to the `webhook_url` of an internal
        transfer when the funds have moved. Verify the `X-Datman-Signature`
        header over the raw request body before trusting the payload. The
        notification is sent once and isn't retried.
      tags:
        - Internal transfers
      security: []
      parameters:
        - $ref: "#/components/parameters/DatmanSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InternalTransferSucceededWebhook"
            examples:
              succeeded:
                summary: Transfer succeeded
                value:
                  request_id: 3f1c2b6a-8d4e-4f0a-9b7c-1e2d3c4b5a69
                  status: success
                  currency: GBP
                  source_merchant_id: "663412"
                  destination_merchant_id: "663500"
                  amount: 350
                  transfer_category_code: 1
                  description: Delivery fee for order ORD-100245
                  reference: REF-100245-DLV
                  webhook_url: https://partner.example.com/webhooks/transfers
                  order_id: ORD-100245
      responses:
        "200":
          description: Acknowledge receipt of the notification.
  internalTransferFailed:
    post:
      operationId: internalTransferFailedWebhook
      summary: Internal transfer failed
      description: Datman sends a JSON POST to the `webhook_url` of an internal
        transfer when the transfer fails. The body has a `reason` and no
        `status`. Verify the `X-Datman-Signature` header over the raw request
        body before trusting the payload. The notification is sent once and
        isn't retried.
      tags:
        - Internal transfers
      security: []
      parameters:
        - $ref: "#/components/parameters/DatmanSignature"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InternalTransferFailedWebhook"
            examples:
              insufficientFunds:
                summary: Insufficient funds
                value:
                  reason: Insufficient funds
                  request_id: 3f1c2b6a-8d4e-4f0a-9b7c-1e2d3c4b5a69
                  currency: GBP
                  source_merchant_id: "663412"
                  destination_merchant_id: "663500"
                  amount: 350
                  transfer_category_code: 1
                  description: Delivery fee for order ORD-100245
                  reference: REF-100245-DLV
                  webhook_url: https://partner.example.com/webhooks/transfers
                  order_id: ORD-100245
      responses:
        "200":
          description: Acknowledge receipt of the notification.
components:
  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Machine-readable SCREAMING_SNAKE error code.
              examples:
                - UNAUTHORIZED
                - FORBIDDEN
                - VALIDATION_ERROR
                - RATE_LIMITED
                - INTERNAL_ERROR
                - DB_TIMEOUT
                - DB_CLIENT_CLOSED
            message:
              type: string
              description: Human-readable error message.
            details:
              description: Optional extra context about the error.
    TransactionStatusFilter:
      type: string
      description: A status value accepted in the `status` filter. Any other value is
        rejected with 422.
      enum:
        - SUCCESS
        - REFUND
        - DECLINE
        - RISK-CHECK-DECLINE
        - FAILED
        - ERROR
        - 3DS-PROGRESS
        - PRE_AUTH
        - AUTHORISED
        - CANCELLED
        - DISPUTES
    Pagination:
      type: object
      required:
        - hasMore
        - nextCursor
      properties:
        hasMore:
          type: boolean
          description: Whether more results exist after this page.
        nextCursor:
          type:
            - string
            - "null"
          description: Opaque cursor to pass as `cursor` for the next page; null when
            hasMore is false.
    Transaction:
      type: object
      description: A normalized transaction row. Fields present can vary by reseller
        query type.
      required:
        - id
        - source
        - transactionTime
      additionalProperties: true
      properties:
        id:
          type: string
          description: Transaction identifier (usually prefixed `p_` for payments or `c_`
            for legacy card payments).
        source:
          type: string
          enum:
            - payments
            - card_payment
          description: Source table of the transaction.
        transactionTime:
          type: string
          description: Transaction timestamp, converted to the response timezone when one
            is resolved.
        orderRef:
          type: string
          description: Datman order reference.
        amount:
          type: number
          description: Gross amount in major currency units.
        currencyCode:
          type: string
          description: ISO currency code.
        status:
          type: string
          enum:
            - SUCCESS
            - REFUNDED
            - DECLINE
            - RISK-CHECK-DECLINE
            - FAILED
            - ERROR
            - 3DS-PROGRESS
            - PRE_AUTH
            - AUTHORISED
            - CANCELLED
            - DISPUTES
        merchantId:
          type:
            - integer
            - string
            - "null"
          description: Merchant identifier.
        merchantName:
          type:
            - string
            - "null"
        customerType:
          type:
            - string
            - "null"
        resellerOrderId:
          type:
            - string
            - "null"
          description: The reseller's original order ID, when an ID mapping exists.
        paymentMethod:
          type: string
        transactionModeId:
          type:
            - integer
            - "null"
        internalReference:
          type:
            - string
            - "null"
          description: Merchant reference.
        pspReference:
          type:
            - string
            - "null"
        last4Digits:
          type:
            - string
            - "null"
        shopperId:
          type:
            - string
            - "null"
        net:
          type:
            - number
            - "null"
        deductions:
          type:
            - number
            - "null"
          description: Fees deducted.
        datman_fee:
          type:
            - number
            - "null"
        amountRefunded:
          type:
            - number
            - "null"
          description: Present on liable-merchant results.
    TransactionListRequest:
      type: object
      required:
        - fromDate
        - toDate
      properties:
        fromDate:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Start calendar date (YYYY-MM-DD), inclusive, in the request timezone.
        toDate:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: End calendar date (YYYY-MM-DD), inclusive, in the request timezone.
        limit:
          type: number
          maximum: 50
          default: 25
          description: Page size. Values above 50 are rejected with 422.
        cursor:
          type: string
          description: The `pagination.nextCursor` value from a previous page.
        status:
          type: array
          items:
            $ref: "#/components/schemas/TransactionStatusFilter"
          description: Only return transactions with these statuses.
        merchantId:
          type: integer
          description: Restrict to one merchant. Non-integer values are ignored.
        timezone:
          type: string
          description: IANA timezone used to interpret the dates and render timestamps.
            Defaults to Europe/London.
          examples:
            - Europe/London
        resellerId:
          type: integer
          description: Optional for API key callers (the key's reseller is always used);
            if supplied it must match, otherwise 403.
    TransactionListResponse:
      type: object
      required:
        - data
        - pagination
      properties:
        data:
          type: object
          required:
            - transactions
          properties:
            transactions:
              type: array
              items:
                $ref: "#/components/schemas/Transaction"
            timezone:
              type: string
              description: Timezone the timestamps are expressed in (Europe/London when none
                resolved).
        pagination:
          $ref: "#/components/schemas/Pagination"
        isLiable:
          type: boolean
          description: Present (true) only when merchantId is a liable merchant.
    OrderSearchRequest:
      type: object
      required:
        - query
      properties:
        query:
          type: string
          minLength: 1
          maxLength: 200
          description: The value to search for (trimmed). The legacy field name `orderId`
            is accepted when `query` is absent.
        searchBy:
          type: string
          enum:
            - orderId
            - merchantReference
            - resellerOrderId
            - merchantId
          default: orderId
          description: Which identifier `query` is matched against. For merchantId,
            `query` must be numeric.
        cursor:
          type: string
          description: The `pagination.nextCursor` value from a previous page.
        limit:
          type: number
          minimum: 1
          maximum: 100
          default: 25
          description: Page size. Values outside 1-100 fall back to 25.
        status:
          type: array
          items:
            $ref: "#/components/schemas/TransactionStatusFilter"
          description: Only return transactions with these statuses.
        timezone:
          type: string
          description: IANA timezone used to render timestamps (and the merchantId date
            window).
          examples:
            - Europe/London
        fromDate:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: searchBy merchantId only. Start calendar date; defaults to yesterday.
        toDate:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: searchBy merchantId only. End calendar date; defaults to today.
    OrderSearchResponse:
      type: object
      required:
        - data
        - pagination
      properties:
        data:
          type: object
          required:
            - transactions
          properties:
            transactions:
              type: array
              items:
                $ref: "#/components/schemas/Transaction"
            timezone:
              type: string
              description: Timezone the timestamps are expressed in. Omitted on empty results.
        pagination:
          $ref: "#/components/schemas/Pagination"
        isLiable:
          type: boolean
          description: Present (true) only for a liable-merchant result.
        timezone:
          type: string
          description: Present only on liable-merchant results with rows, in place of
            data.timezone.
    CpAddress:
      type: object
      description: Postal address. Every field is null when no address is on file.
      required:
        - address_line1
        - address_line2
        - city
        - county
        - post_code
        - state
        - country
      properties:
        address_line1:
          type:
            - string
            - "null"
        address_line2:
          type:
            - string
            - "null"
        city:
          type:
            - string
            - "null"
        county:
          type:
            - string
            - "null"
        post_code:
          type:
            - string
            - "null"
        state:
          type:
            - string
            - "null"
        country:
          type:
            - string
            - "null"
    CpMerchantSummary:
      type: object
      required:
        - merchant_id
        - merchant_name
        - canonical_reseller_id
        - country
        - account_status
        - payout_status
        - business_status
        - owners_status
        - bank_status
        - tos_status
        - is_reseller
        - is_liable
      properties:
        merchant_id:
          type: integer
          description: Merchant id.
        merchant_name:
          type: string
          description: Merchant name as recorded at onboarding.
        canonical_reseller_id:
          type:
            - integer
            - "null"
          description: Id of the reseller that owns the merchant.
        country:
          type:
            - string
            - "null"
          description: Country name, for example `United Kingdom`.
        account_status:
          type:
            - string
            - "null"
          description: Overall account onboarding status.
        payout_status:
          type:
            - string
            - "null"
          description: Payout onboarding status.
        business_status:
          type:
            - string
            - "null"
          description: Business-details verification status.
        owners_status:
          type:
            - string
            - "null"
          description: Owner verification status.
        bank_status:
          type:
            - string
            - "null"
          description: Bank-account verification status.
        tos_status:
          type:
            - string
            - "null"
          description: Terms-of-service acceptance status.
        is_reseller:
          type: boolean
          description: Whether the merchant is itself a reseller.
        is_liable:
          type: boolean
          description: Whether the merchant is liable (gateway `is_liable` flag).
    CpMerchantSummaryResponse:
      type: object
      required:
        - data
      properties:
        data:
          $ref: "#/components/schemas/CpMerchantSummary"
    CpMerchantPaymentConfig:
      type: object
      description: Payment configuration. Every listed property is present when the
        merchant has a gateway customer record. Otherwise the object is empty.
      properties:
        payment_provider:
          type:
            - string
            - "null"
          description: Code of the payment provider that processes the merchant's payments.
        fee_tier_name:
          type:
            - string
            - "null"
        fee_tier_percentage:
          type:
            - number
            - "null"
          description: Fee tier percentage fee.
        fee_tier_fixed:
          type:
            - number
            - "null"
          description: Fee tier fixed fee per transaction, in major currency units.
        ext_reseller_percentage_fee:
          type:
            - number
            - "null"
          description: Your reseller percentage fee on top of the tier.
        ext_reseller_fixed_fee:
          type:
            - number
            - "null"
          description: Your reseller fixed fee on top of the tier, in major currency units.
        gateway_name:
          type:
            - string
            - "null"
        billing_address:
          type:
            - string
            - "null"
          description: Billing-address setting on the gateway configuration, passed
            through unchanged.
        hide_gpay_apay:
          type:
            - string
            - "null"
          description: Whether Google Pay / Apple Pay are hidden, as stored on the gateway
            configuration.
        mid_status:
          type: "null"
          description: Reserved. Always null.
        min_transaction:
          type: "null"
          description: Reserved. Always null.
        max_transaction:
          type:
            - number
            - "null"
          description: Effective maximum single-transaction value (merchant value, else
            country default).
        xpress_sale_limit:
          type:
            - number
            - "null"
          description: Effective express-sale limit (merchant value, else country default).
        daily_limit:
          type: "null"
          description: Reserved. Always null.
        merchant_max_transaction:
          type:
            - number
            - "null"
          description: Merchant-level maximum single-transaction value. 0 means unset.
        merchant_xpress_sale_limit:
          type:
            - number
            - "null"
          description: Merchant-level express-sale limit. 0 means unset.
        country_max_transaction:
          type:
            - number
            - "null"
          description: Country default maximum single-transaction value.
        country_xpress_sale_limit:
          type:
            - number
            - "null"
          description: Country default express-sale limit.
        fee_tier_id:
          type:
            - integer
            - "null"
        buying_rate_percentage:
          type:
            - number
            - "null"
          description: Your reseller's cost (buying) percentage rate, or null if none is
            on file.
        buying_rate_fixed:
          type:
            - number
            - "null"
          description: Your reseller's cost (buying) fixed rate, or null if none is on file.
    CpMerchantPaymentConfigResponse:
      type: object
      required:
        - data
      properties:
        data:
          $ref: "#/components/schemas/CpMerchantPaymentConfig"
    CpOwnerDetails:
      type: object
      required:
        - title
        - full_name
        - email
        - telephone_number
        - date_of_birth
        - nationality
        - ownership_percentage
        - address_line1
        - address_line2
        - city
        - county
        - post_code
        - state
        - country
      properties:
        title:
          type:
            - string
            - "null"
        full_name:
          type:
            - string
            - "null"
        email:
          type:
            - string
            - "null"
        telephone_number:
          type:
            - string
            - "null"
        date_of_birth:
          type:
            - string
            - "null"
          description: Date of birth as an ISO-8601 timestamp.
        nationality:
          type:
            - string
            - "null"
        ownership_percentage:
          type:
            - number
            - string
            - "null"
          description: Ownership percentage. May be returned as a decimal string.
        address_line1:
          type:
            - string
            - "null"
        address_line2:
          type:
            - string
            - "null"
        city:
          type:
            - string
            - "null"
        county:
          type:
            - string
            - "null"
        post_code:
          type:
            - string
            - "null"
        state:
          type:
            - string
            - "null"
        country:
          type:
            - string
            - "null"
    CpMerchantOwnerDetailsResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: object
          required:
            - owner_details
          properties:
            owner_details:
              oneOf:
                - $ref: "#/components/schemas/CpOwnerDetails"
                - type: "null"
    CpBusinessDetails:
      type: object
      required:
        - legal_name
        - trading_name
        - company_number
        - legal_entity
        - industry
        - vat_number
        - telephone_number
        - website_url
        - registered_address
        - trading_address
      properties:
        legal_name:
          type:
            - string
            - "null"
        trading_name:
          type:
            - string
            - "null"
        company_number:
          type:
            - string
            - "null"
          description: Company registration number.
        legal_entity:
          type:
            - string
            - "null"
          description: Legal entity type name, for example `Limited Company`.
        industry:
          type:
            - string
            - "null"
          description: Business category.
        vat_number:
          type:
            - string
            - "null"
        telephone_number:
          type:
            - string
            - "null"
        website_url:
          type:
            - string
            - "null"
        registered_address:
          $ref: "#/components/schemas/CpAddress"
        trading_address:
          $ref: "#/components/schemas/CpAddress"
    CpBusinessOwnerContact:
      type: object
      required:
        - full_name
        - email
        - telephone_number
        - address_line1
        - address_line2
        - city
        - county
        - post_code
      properties:
        full_name:
          type:
            - string
            - "null"
        email:
          type:
            - string
            - "null"
        telephone_number:
          type:
            - string
            - "null"
        address_line1:
          type:
            - string
            - "null"
        address_line2:
          type:
            - string
            - "null"
        city:
          type:
            - string
            - "null"
        county:
          type:
            - string
            - "null"
        post_code:
          type:
            - string
            - "null"
    CpMerchantBusinessDetailsResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: object
          description: Both properties are present for an existing merchant. Otherwise the
            object is empty.
          properties:
            business_details:
              $ref: "#/components/schemas/CpBusinessDetails"
            owner_details:
              $ref: "#/components/schemas/CpBusinessOwnerContact"
    CpMerchantBankDetails:
      type: object
      required:
        - name_of_bank
        - account_holder_name
        - sort_code
        - account_number
        - routing_number
        - bsb_code
        - transit_number
        - financial_institution_number
        - account_type
        - country
        - status
        - verified_on
      properties:
        name_of_bank:
          type:
            - string
            - "null"
        account_holder_name:
          type:
            - string
            - "null"
        sort_code:
          type:
            - string
            - "null"
          description: Masked UK sort code (last 3 characters), for example `****456`.
        account_number:
          type:
            - string
            - "null"
          description: Masked account number (last 3 characters), for example `****234`.
        routing_number:
          type:
            - string
            - "null"
          description: Masked US routing number.
        bsb_code:
          type:
            - string
            - "null"
          description: Masked Australian BSB code.
        transit_number:
          type:
            - string
            - "null"
          description: Masked Canadian transit number.
        financial_institution_number:
          type:
            - string
            - "null"
          description: Masked Canadian financial institution number.
        account_type:
          type:
            - string
            - "null"
        country:
          type:
            - string
            - "null"
          description: Merchant country name.
        status:
          type:
            - string
            - "null"
          description: Bank-account verification status, for example `Verified`.
        verified_on:
          type:
            - string
            - "null"
          description: ISO-8601 timestamp. Set only when `status` is `Verified`.
    CpMerchantBankDetailsResponse:
      type: object
      required:
        - data
      properties:
        data:
          oneOf:
            - $ref: "#/components/schemas/CpMerchantBankDetails"
            - type: "null"
    CpOnboardingError:
      type: object
      description: One outstanding onboarding issue. Entries from missing details and
        the payment provider always have `title`, `field` and `reported_at`.
        Legacy entries are passed through as stored and may include `message` or
        other keys.
      additionalProperties: true
      properties:
        title:
          type: string
          description: Category, for example `Bank Issues` or `Individual`.
        field:
          type: string
          description: The field or requirement concerned.
        message:
          type: string
        reported_at:
          type:
            - string
            - "null"
          description: ISO-8601 timestamp when the error was reported, if known.
    CpMerchantOnboarding:
      type: object
      description: Onboarding record. Every listed property is present when the
        merchant has an onboarding record. Otherwise the object is empty.
      properties:
        merchant_id:
          type: integer
        merchant_name:
          type:
            - string
            - "null"
        onboarding_link:
          type:
            - string
            - "null"
          description: Link to the onboarding journey.
        overview_page:
          type:
            - string
            - "null"
        account_status:
          type:
            - string
            - "null"
        payout_status:
          type:
            - string
            - "null"
        business_status:
          type:
            - string
            - "null"
        owners_status:
          type:
            - string
            - "null"
        bank_status:
          type:
            - string
            - "null"
        tos_status:
          type:
            - string
            - "null"
        verification_tier:
          type:
            - string
            - integer
            - "null"
        missing_details:
          type: object
          description: Outstanding information, keyed by category. The keys are dynamic
            and lowercased (for example `bank issues`). Each value is usually an
            array of issue descriptions.
          additionalProperties: true
        note:
          type:
            - string
            - "null"
        country:
          type:
            - string
            - "null"
        errors:
          type: array
          description: Merged, de-duplicated onboarding errors from all sources.
          items:
            $ref: "#/components/schemas/CpOnboardingError"
    CpMerchantOnboardingResponse:
      type: object
      required:
        - data
      properties:
        data:
          $ref: "#/components/schemas/CpMerchantOnboarding"
    CpKycDocument:
      type: object
      required:
        - name
        - uploaded_at
      properties:
        name:
          type: string
          description: File name as uploaded.
        uploaded_at:
          type:
            - string
            - "null"
          format: date-time
          description: Last modification time of the document.
    CpMerchantKycDocumentsResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: object
          required:
            - documents
          properties:
            documents:
              type: array
              items:
                $ref: "#/components/schemas/CpKycDocument"
    CpMerchantUser:
      type: object
      required:
        - relationship_id
        - id
        - name
        - email
        - roles
        - merchant_role_id
        - reseller_id
        - status
        - last_login
      properties:
        relationship_id:
          type:
            - integer
            - string
          description: Id of the user-to-merchant relationship.
        id:
          type:
            - integer
            - string
          description: User id.
        name:
          type: string
          description: Display name. Falls back to the email local-part.
        email:
          type: string
        roles:
          type: array
          description: Role names on this merchant (currently at most one).
          items:
            type: string
        merchant_role_id:
          type:
            - integer
            - "null"
        reseller_id:
          type:
            - integer
            - "null"
        status:
          type: string
          enum:
            - Active
            - Pending
            - Revoked
          description: "`Active` once sign-up is complete, otherwise `Pending`."
        last_login:
          type: string
          description: Not tracked. Always `-`.
    CpMerchantUsersResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/CpMerchantUser"
    CpMerchantPayout:
      type: object
      required:
        - id
        - total
        - status
        - expected_date
        - sort_date
        - payment_provider
      properties:
        id:
          type:
            - integer
            - string
          description: Payout batch id or payout transaction id, depending on the
            provider. Not unique across providers.
        total:
          type: number
          description: Payout amount in major currency units.
        status:
          type: string
          description: Provider payout status, for example `SENT` or `FAILED`.
        expected_date:
          type:
            - string
            - "null"
          description: Expected payout date as an ISO-8601 timestamp.
        sort_date:
          type:
            - string
            - "null"
          description: Timestamp used to order the list (pending date for batches,
            creation time for payout transactions).
        payment_provider:
          type: string
          description: Code of the provider that made the payout, for example `DATMAN`.
    CpMerchantPayoutsResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/CpMerchantPayout"
    CpMerchantPayoutStat:
      type: object
      required:
        - status
        - order_count
        - total_amount
      properties:
        status:
          type: string
          description: Payout status, for example `SENT` or `FAILED`.
        order_count:
          type: integer
          description: Number of payouts with this status.
        total_amount:
          type: number
          description: Total amount in major currency units.
    CpMerchantPayoutStatsResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/CpMerchantPayoutStat"
    CpMerchantBalance:
      type: object
      required:
        - available
        - pending
        - on_hold
      properties:
        available:
          type: number
          description: Available balance in major currency units, rounded to 2 decimal
            places.
        pending:
          type: number
          description: Always 0.
        on_hold:
          type: number
          description: Always 0.
    CpMerchantBalanceResponse:
      type: object
      required:
        - data
      properties:
        data:
          $ref: "#/components/schemas/CpMerchantBalance"
    CpDecimal:
      type:
        - string
        - number
      description: A MySQL DECIMAL computed in SQL. The shared DB client (mysql2
        without decimalNumbers) returns these as strings such as "24.5000";
        parse them as numbers.
    CpDbTimestamp:
      type: string
      description: A transaction timestamp. When a timezone was resolved it is
        "YYYY-MM-DD HH:MM:SS" in that timezone. Otherwise it is an ISO string
        such as "2026-10-14T13:45:12.000Z" whose digits are Europe/London
        wall-clock time, despite the Z suffix.
    CpRefundDetail:
      type: object
      required:
        - amount
        - time
      properties:
        amount:
          type:
            - number
            - string
          description: Refund amount in major units, negative. For source=payments it is
            computed in JS (number); for source=card_payment it is the raw
            card_payment.total column.
        time:
          type: string
          description: Refund time, "YYYY-MM-DD HH:MM:SS" in meta.timezone.
    CpRefundDetailsResponse:
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/CpRefundDetail"
        meta:
          type: object
          required:
            - timezone
          properties:
            timezone:
              type: string
              description: Timezone the times are expressed in (Europe/London when none
                given).
    CpTransactionDetailPayment:
      type: object
      description: One payments row recorded under the order reference.
      required:
        - id
        - order_ref
        - amount
        - transaction_time
      properties:
        id:
          type: integer
          description: Payment ID (payments.id). Use it with the webhook-payload endpoint.
        order_ref:
          type: string
        amount:
          $ref: "#/components/schemas/CpDecimal"
        net:
          oneOf:
            - $ref: "#/components/schemas/CpDecimal"
            - type: "null"
        fee:
          oneOf:
            - $ref: "#/components/schemas/CpDecimal"
            - type: "null"
        datman_fee:
          type:
            - number
            - "null"
          description: Datman fee in major units, computed from the fee tier; null when no
            fee configuration is found.
        transaction_time:
          $ref: "#/components/schemas/CpDbTimestamp"
        refund_reason_id:
          type:
            - integer
            - "null"
        reason:
          type:
            - string
            - "null"
          description: Decline or refund reason. Always null for successful positive
            payments.
        currency_code:
          type:
            - string
            - "null"
        status_id:
          type:
            - integer
            - "null"
          description: Raw transaction_status_id.
        status:
          type:
            - string
            - "null"
          enum:
            - SUCCESS
            - REFUNDED
            - DECLINE
            - RISK-CHECK-DECLINE
            - FAILED
            - ERROR
            - 3DS-PROGRESS
            - PRE_AUTH
            - AUTHORISED
            - CANCELLED
            - null
        merchant_id:
          type:
            - integer
            - "null"
        internal_reference:
          type:
            - string
            - "null"
          description: Merchant reference.
        shopper_id:
          type:
            - string
            - "null"
        last4_digits:
          type:
            - string
            - "null"
        transaction_mode_id:
          type:
            - integer
            - "null"
        payment_method:
          type:
            - string
            - "null"
          description: Display label for the payment method (for example New Card, Apple
            Pay, Card on File).
    CpTransactionDetailRefund:
      type: object
      required:
        - amount
        - transaction_time
      properties:
        amount:
          $ref: "#/components/schemas/CpDecimal"
        net:
          oneOf:
            - $ref: "#/components/schemas/CpDecimal"
            - type: "null"
        fee:
          oneOf:
            - $ref: "#/components/schemas/CpDecimal"
            - type: "null"
        internal_reference:
          type:
            - string
            - "null"
        transaction_time:
          $ref: "#/components/schemas/CpDbTimestamp"
        reason:
          type:
            - string
            - "null"
    CpTransactionDetailChargeback:
      type: object
      required:
        - amount
        - transaction_time
        - journal_type
        - status_badge
      properties:
        amount:
          $ref: "#/components/schemas/CpDecimal"
        internal_reference:
          type:
            - string
            - "null"
        transaction_time:
          $ref: "#/components/schemas/CpDbTimestamp"
        transaction_mode_id:
          type:
            - integer
            - "null"
        journal_type:
          type: string
          enum:
            - Chargeback
            - Initial Chargeback
            - Chargeback Reverse
            - Second Chargeback
        status_badge:
          type: string
          enum:
            - Chargeback
            - Chargeback Won
            - 2nd Chargeback
        last4_digits:
          type:
            - string
            - "null"
    CpTransactionShopper:
      type: object
      description: The shopper, from the shoppers table when the payment has a
        shopper_id, otherwise from the billing details on the payment. address
        is always null in the first case.
      properties:
        first_name:
          type:
            - string
            - "null"
        last_name:
          type:
            - string
            - "null"
        email:
          type:
            - string
            - "null"
        address:
          type:
            - string
            - "null"
    CpTransactionSplit:
      type: object
      required:
        - amount
        - amount_refunded
        - commission_type
        - merchant_id
      properties:
        amount:
          $ref: "#/components/schemas/CpDecimal"
        amount_refunded:
          $ref: "#/components/schemas/CpDecimal"
        commission_type:
          type: string
          description: Commission type name from split_commission_types.
        merchant_id:
          type:
            - integer
            - "null"
          description: The partner merchant that receives this share.
    CpTransactionDetail:
      type: object
      required:
        - transactions
        - refunds
        - chargebacks
        - shopper
        - splits
        - timezone
      properties:
        transactions:
          type: array
          description: Payment rows for the order, newest first. Empty for an unknown
            order (portal callers only; API key callers get 404).
          items:
            $ref: "#/components/schemas/CpTransactionDetailPayment"
        refunds:
          type: array
          items:
            $ref: "#/components/schemas/CpTransactionDetailRefund"
        chargebacks:
          type: array
          items:
            $ref: "#/components/schemas/CpTransactionDetailChargeback"
        shopper:
          oneOf:
            - $ref: "#/components/schemas/CpTransactionShopper"
            - type: "null"
        splits:
          type: array
          items:
            $ref: "#/components/schemas/CpTransactionSplit"
        timezone:
          type: string
          description: Timezone the timestamps are expressed in (Europe/London when none
            resolved).
    CpTransactionDetailResponse:
      type: object
      required:
        - data
      properties:
        data:
          $ref: "#/components/schemas/CpTransactionDetail"
    CpTransactionSplitsResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/CpTransactionSplit"
    CpWebhookDelivery:
      type: object
      required:
        - card_payment_id
        - webhook_url
        - action
        - payload
        - created_at
        - http_response_code
        - omt
      properties:
        card_payment_id:
          type: integer
          description: The payment ID (payments.id) the webhook was sent for.
        webhook_url:
          type: string
        action:
          type: string
          description: Webhook event name.
          examples:
            - payment_success
        payload:
          description: The payload that was sent, parsed from JSON when possible
            (otherwise the raw string), with any `token` key removed. Its keys
            are snake_cased by the response writer.
          oneOf:
            - type: object
              additionalProperties: true
            - type: string
        created_at:
          type: string
          description: When the webhook was sent (ISO string).
        http_response_code:
          type:
            - integer
            - "null"
          description: HTTP status returned by the webhook endpoint.
        omt:
          type:
            - string
            - "null"
          description: The payment's internal (merchant) reference.
    CpWebhookPayloadResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/CpWebhookDelivery"
    CpMerchantSummaryRequest:
      type: object
      description: Keys may be camelCase or snake_case (merchant_id, from_date, to_date).
      required:
        - merchantId
        - fromDate
        - toDate
      properties:
        merchantId:
          type:
            - integer
            - string
          description: Merchant to summarize. A numeric string is accepted.
        fromDate:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: Start calendar date (YYYY-MM-DD), inclusive.
        toDate:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
          description: End calendar date (YYYY-MM-DD), inclusive. At most 90 days after
            fromDate.
        timezone:
          type: string
          description: IANA timezone the dates are in. Recommended for API key callers;
            when omitted the dates are interpreted in UTC.
          examples:
            - Europe/London
        resellerId:
          type: integer
          description: Ignored for API key callers (the key's reseller is always used).
    CpMerchantTransactionSummary:
      type: object
      required:
        - payment_total
        - refund_total
        - net
      properties:
        payment_total:
          type: number
          description: Sum of net amounts of successful payments, in major units (2 dp).
        refund_total:
          type: number
          description: Sum of refunded and charged-back net amounts (positive), in major
            units (2 dp).
        net:
          type: number
          description: payment_total minus refund_total (2 dp).
        is_liable:
          type: boolean
          description: Whether the merchant is a liable account. Omitted when the reseller
            has no queryable scope.
    CpMerchantTransactionSummaryResponse:
      type: object
      required:
        - data
      properties:
        data:
          $ref: "#/components/schemas/CpMerchantTransactionSummary"
    CpResellerMerchantsSummaryRequest:
      type: object
      description: Keys may be camelCase or snake_case (reseller_id).
      properties:
        resellerId:
          type:
            - integer
            - string
          description: Optional for API key callers. If sent it must be a positive integer
            (or numeric string) equal to the key's reseller, otherwise 403 (or
            422 if malformed).
    CpResellerMerchantsSummary:
      type: object
      description: Counts over the reseller's merchants. All counts except
        total_merchants are SQL SUM() values and are likely returned as numeric
        strings; they are null when the reseller has no merchants.
      properties:
        total_merchants:
          type: integer
        staggered_onboarding:
          type:
            - string
            - integer
            - "null"
          description: Merchants with account and payout status both non-zero.
        up_to1000:
          type:
            - string
            - integer
            - "null"
          description: Merchants on verification tier "Tier 1".
        up_to5000:
          type:
            - string
            - integer
            - "null"
          description: Merchants on verification tier "Tier 2".
        fully_verified:
          type:
            - string
            - integer
            - "null"
          description: Merchants with bank, business, owner and ToS verified and account
            and payout active.
        closed_or_suspended:
          type:
            - string
            - integer
            - "null"
          description: Merchants with account_status 0.
    CpResellerMerchantsSummaryResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: object
          required:
            - summary
          properties:
            summary:
              oneOf:
                - $ref: "#/components/schemas/CpResellerMerchantsSummary"
                - type: "null"
    CpResellerMerchantsStatusRequest:
      type: object
      description: Keys may be camelCase or snake_case (reseller_id,
        enable_pagination, and so on).
      properties:
        resellerId:
          type:
            - integer
            - string
          description: Optional for API key callers; must match the key's reseller if sent.
        enablePagination:
          type: boolean
          default: false
          description: Turn on paging, search and the activeOnly/excludeMerchantId
            filters. When false every merchant is returned.
        page:
          type: integer
          minimum: 1
          default: 1
          description: Page number (pagination only).
        limit:
          type: integer
          minimum: 1
          default: 20
          description: Page size (pagination only). Not capped by the server.
        search:
          type: string
          default: ""
          description: Case-insensitive match on merchant name, trading name or merchant
            ID (pagination only).
        isLiableOnly:
          type: boolean
          default: false
          description: Only merchants flagged as resellers (liable accounts).
        activeOnly:
          type: boolean
          default: false
          description: Exclude closed or suspended merchants (account_status 0).
            Pagination only.
        excludeMerchantId:
          type: integer
          description: Leave this merchant out of the results. Pagination only.
        sortField:
          type: string
          enum:
            - createdAt
          description: Sort by merchant creation time. When omitted, rows are ordered by
            onboarding record, newest first.
        sortOrder:
          type: string
          enum:
            - asc
            - desc
          default: desc
    CpResellerMerchantOnboardingRow:
      type: object
      description: One merchant's onboarding record.
      properties:
        id:
          type: integer
          description: Onboarding record ID.
        merchant_id:
          type: integer
        account_holder_id:
          type:
            - string
            - "null"
          description: Account holder ID at the payment provider.
        reseller_name:
          type:
            - string
            - "null"
        country:
          type:
            - string
            - "null"
        merchant_name:
          type:
            - string
            - "null"
        trading_name:
          type:
            - string
            - "null"
        business_status:
          type:
            - integer
            - "null"
          description: 1 when business details are verified.
        owner_status:
          type:
            - integer
            - "null"
          description: 1 when owner details are verified.
        bank_status:
          type:
            - integer
            - "null"
          description: 1 when bank details are verified.
        payout_status:
          type:
            - integer
            - "null"
          description: 0 when payouts are not enabled.
        account_status:
          type:
            - integer
            - "null"
          description: 0 when the account is closed or suspended.
        tos_status:
          type:
            - integer
            - "null"
          description: 1 when the terms of service are accepted.
        verification_tier:
          type:
            - string
            - "null"
          examples:
            - Tier 1
            - Tier 2
        internal_tags:
          description: Tags assigned to the merchant (column type not declared in the repo).
        onboarding_link:
          type:
            - string
            - "null"
        overview_page:
          type:
            - string
            - "null"
        average_weekly_orders:
          type:
            - number
            - "null"
        due_in_days:
          type:
            - number
            - "null"
        raw_data:
          description: Raw onboarding data from the provider (column type not declared in
            the repo).
        list_of_errors:
          description: Outstanding verification errors (column type not declared in the
            repo).
        note:
          type:
            - string
            - "null"
        get_all_low_errors:
          description: Low-severity verification errors (column type not declared in the
            repo).
        is_reseller:
          type:
            - integer
            - "null"
          description: 1 when the merchant is a liable (reseller) account.
        created_at:
          type:
            - string
            - "null"
          description: Merchant creation time (ISO string).
        hosted_onboarding_enabled:
          type:
            - integer
            - "null"
        payment_provider:
          type:
            - string
            - "null"
          description: Payment provider from the gateway. Omitted when that lookup is
            unavailable.
    CpResellerMerchantsStatusResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: object
          required:
            - rows
            - all_tags
            - total
            - summary
          properties:
            rows:
              type: array
              items:
                $ref: "#/components/schemas/CpResellerMerchantOnboardingRow"
            all_tags:
              type: array
              description: Every onboarding tag the reseller has defined. Row columns are
                dynamic (SELECT *), with keys snake_cased.
              items:
                type: object
                additionalProperties: true
            total:
              type: integer
              description: Total matching merchants (paginated) or rows returned
                (unpaginated).
            summary:
              type: "null"
              description: Always null on this endpoint; use reseller-merchants-summary
                instead.
    MerchantCountry:
      type: string
      description: Supported merchant country.
      enum:
        - United Kingdom
        - Ireland
        - Australia
        - New Zealand
        - Canada
        - United States
        - Mexico
    E164PhoneNumber:
      type: string
      description: Phone number in E.164 format including country code.
      pattern: ^\+\d{7,15}$
    CredentialsPair:
      type: object
      additionalProperties: false
      required:
        - email
        - phoneNumber
      properties:
        email:
          type: string
          format: email
          description: Email address. In `newCredentials` it may be an empty string to
            leave unchanged.
        phoneNumber:
          type: string
          pattern: ^(\+\d{10,15})?$
          description: Phone number as +[country_code][number], or empty string to leave
            unchanged.
    MerchantAssociationRequest:
      type: object
      additionalProperties: false
      description: Fields are conditional on `action`. Fields not listed for an action
        are rejected. Only `create`, `reactivate` and `update` carry
        action-specific fields on this endpoint.
      required:
        - action
      properties:
        action:
          type: string
          enum:
            - create
            - reactivate
            - update
            - patch
            - uploadDocuments
          description: Operation to perform.
        storeId:
          type: string
          pattern: ^\d+$
          maxLength: 10
          description: Numeric store identifier. `create` only; required unless
            `isPartner` is true, and forbidden when `isPartner` is true.
        isPartner:
          type: boolean
          description: "`create` only (required). Set true to onboard a delivery partner
            without a `storeId`; must be true when `storeId` is omitted."
        webhookUrl:
          type: string
          format: uri
          pattern: ^https://
          maxLength: 200
          description: HTTPS URL that receives onboarding webhooks for the merchant
            created with `create`.
        email:
          type: string
          format: email
          maxLength: 254
          description: Merchant owner email. `create` only (required). Lower-cased by the
            server.
        phoneNumber:
          allOf:
            - $ref: "#/components/schemas/E164PhoneNumber"
          description: Merchant owner phone number. `create` only (required).
        country:
          allOf:
            - $ref: "#/components/schemas/MerchantCountry"
          description: Merchant country. `create` only (required).
        firstName:
          type: string
          minLength: 1
          maxLength: 80
          description: Owner first name. `create` only (required).
        lastName:
          type: string
          minLength: 1
          maxLength: 80
          description: Owner last name. `create` only (required).
        businessName:
          type: string
          minLength: 1
          maxLength: 80
          description: Legal business name (Unicode letters, digits and common
            punctuation). `create` only (required).
        tradingName:
          type:
            - string
            - "null"
          maxLength: 80
          description: Trading name. `create` only, optional; empty string or null allowed.
        changeOfownership:
          type: boolean
          description: Whether this is a change of ownership of an existing store.
            `create` only (required).
        isReseller:
          type: boolean
          description: Whether the merchant is a reseller. `create` only (required).
        merchantId:
          type: string
          pattern: ^\d+$
          maxLength: 100
          description: Datman merchant ID whose signup link is reactivated. `reactivate`
            only (required).
        resellerId:
          type: string
          pattern: ^\d{2,7}$
          description: Optional reseller ID (2-7 digits).
        countryOverride:
          type: boolean
          description: "`create` only, optional. When true, skips the check that `country`
            matches the reseller's configured country."
        platform:
          type: array
          uniqueItems: true
          description: IDs of the platforms to onboard on, as agreed with Datman. Defaults
            to all platforms when omitted.
          items:
            type: integer
            enum:
              - 1
              - 2
        businessType:
          type:
            - string
            - "null"
          enum:
            - Limited
            - Partnership
            - Sole Trader
            - Individual
            - Trust
            - Other
            - Corporation
            - ""
            - null
          description: "`create` only, optional. Allowed values depend on `country`:
            UK/Ireland: Limited, Partnership, Sole Trader, Individual;
            Australia: those plus Trust, Other; New Zealand and Mexico: Limited,
            Partnership, Sole Trader, Other, Individual; Canada: Limited, Sole
            Trader, Individual; United States: Limited, Sole Trader,
            Partnership, Corporation, Other, Individual."
        oldCredentials:
          allOf:
            - $ref: "#/components/schemas/CredentialsPair"
          description: Current user credentials. `update` only (required).
        newCredentials:
          allOf:
            - $ref: "#/components/schemas/CredentialsPair"
          description: New user credentials. `update` only (required). Must differ from
            `oldCredentials`; to change only the phone number, keep the same
            email in both and supply both phone numbers.
    MerchantAssociationResponse:
      type: object
      description: Result of the requested action. `create` returns the merchant
        fields; `reactivate` and `update` return `message` (and `statusCode` for
        update outcomes).
      properties:
        message:
          type: string
          description: Human-readable outcome.
        statusCode:
          type: integer
          description: Datman internal outcome code (not an HTTP status), e.g. 6003
            credentials updated, 4005-4009 update not possible.
        merchantId:
          type: integer
          description: Datman merchant ID (`create`).
        merchant_status:
          description: Merchant status value stored on the merchant record (`create`).
        account_verification_status:
          type: boolean
          description: Whether the merchant account is verified (`create`).
        bank_verification_status:
          type: boolean
          description: Whether the merchant bank account is verified (`create`).
        email:
          type: string
          format: email
          description: Owner email (`create`).
        responseCode:
          type: integer
          enum:
            - 1001
            - 1002
          description: Onboarding flow indicator (`create`). 1001 = staggered onboarding
            only; 1002 = extra details may be patched and the account might
            become unverified.
        businessName:
          type: string
          description: Legal business name (`create`).
        tradingName:
          type: string
          description: Trading name (`create`).
        signup_link:
          type: string
          description: Portal link for the new user to complete signup. Only present when
            a new user was created.
    MerchantAssociationError:
      type: object
      required:
        - message
      properties:
        message:
          type: string
          description: Validation or business-rule error message.
        statusCode:
          type: integer
          description: Datman internal error code, when available (e.g. 7003 reseller
            country mismatch).
        merchantId:
          type: integer
          description: Merchant ID, when the store is already associated.
    MerchantAccountStatusResponse:
      type: object
      properties:
        status:
          type: string
          description: Merchant status, for example `Not Submitted`, `Merchant pending`,
            `Verified`, `Active`, `Closed`, `Rejected` or `Watchlist`.
        bank_verification_status:
          type: string
          enum:
            - Unverified
            - Verified
          description: Bank account verification status.
        account_verification_status:
          type: string
          enum:
            - Unverified
            - Verified
          description: Merchant account verification status.
        verification_status:
          type: object
          description: Verification details from the payment provider.
          properties:
            account_status:
              type:
                - string
                - "null"
              description: Upper-cased account holder status (e.g. ACTIVE), or null if
                unavailable.
            payout_status:
              type:
                - string
                - "null"
              enum:
                - ACTIVE
                - INACTIVE
                - null
              description: Payout capability status, or null if unavailable.
            issues:
              type: array
              description: User-friendly descriptions of outstanding verification problems.
              items:
                type: string
            verification_tier:
              description: Verification tier, if configured.
        feeTier:
          type: array
          description: The merchant's current fee tier entry (filtered from the available
            fee tiers).
          items:
            type: object
            properties:
              id:
                description: Fee tier ID.
    InvalidApiKeyError:
      type: object
      properties:
        message:
          type: string
          example: Invalid API key
        errorCode:
          type: integer
          example: 1019
    UnauthorisedError:
      type: object
      properties:
        message:
          type: string
          example: UNAUTHORISED
    MerchantNotFoundError:
      type: object
      properties:
        message:
          type: string
          example: Merchant not found
        statusCode:
          type: integer
          description: Datman internal code.
          example: 7001
    RateLimitExceededError:
      type: object
      properties:
        message:
          type: string
          example: Too many requests with the same reference
        statusCode:
          type: integer
          description: Datman internal code.
          example: 6001
    ServerError:
      type: object
      properties:
        message:
          type: string
          example: Internal server error
    MerchantAssociationV2Request:
      type: object
      description: Fields depend on `action`. The onboarding sections (`bankDetails`,
        `businessDetails`, `ownerDetails`, `tradingDetails`,
        `businessDealDetails`) are required on `create` and optional on `patch`.
        Other top-level fields follow the same per-action rules as the V1
        endpoint, and fields not allowed for an action are rejected.
        `uploadDocuments` accepts only `action`, `merchantId` and `attachments`.
      required:
        - action
      properties:
        action:
          type: string
          enum:
            - create
            - reactivate
            - update
            - patch
            - uploadDocuments
          description: Operation to perform.
        storeId:
          type: string
          pattern: ^\d+$
          maxLength: 10
          description: Numeric store identifier. `create` only. Required unless
            `isPartner` is true, and not allowed when `isPartner` is true.
        isPartner:
          type: boolean
          description: "`create` only (required). Set true to onboard a delivery partner
            without a `storeId`. Must be true when `storeId` is omitted."
        webhookUrl:
          type: string
          format: uri
          pattern: ^https://
          maxLength: 200
          description: HTTPS URL that receives onboarding webhooks for the merchant
            created with `create`.
        email:
          type: string
          format: email
          maxLength: 254
          description: Merchant owner email. `create` only (required). The server converts
            it to lower case.
        phoneNumber:
          allOf:
            - $ref: "#/components/schemas/E164PhoneNumber"
          description: Merchant owner phone number. `create` only (required).
        country:
          allOf:
            - $ref: "#/components/schemas/MerchantCountry"
          description: Merchant country. `create` only (required). Also decides the
            country-specific rules for the onboarding sections.
        firstName:
          type: string
          minLength: 1
          maxLength: 80
          description: Owner first name. `create` only (required).
        lastName:
          type: string
          minLength: 1
          maxLength: 80
          description: Owner last name. `create` only (required).
        businessName:
          type: string
          minLength: 1
          maxLength: 80
          description: Legal business name. `create` only (required).
        tradingName:
          type:
            - string
            - "null"
          maxLength: 80
          description: Trading name. `create` only, optional. Empty string or null is
            allowed.
        changeOfownership:
          type: boolean
          description: Whether this is a change of ownership of an existing store.
            `create` only (required).
        isReseller:
          type: boolean
          description: Whether the merchant is a reseller. `create` only (required).
        merchantId:
          type: string
          pattern: ^\d+$
          maxLength: 100
          description: Datman merchant ID. Required for `reactivate`, `patch` and
            `uploadDocuments`. Must be sent as a string.
        resellerId:
          type: string
          pattern: ^\d{2,7}$
          description: Optional reseller ID (2-7 digits).
        countryOverride:
          type: boolean
          description: "`create` only, optional. When true, skips the check that `country`
            matches the reseller's configured country."
        platform:
          type: array
          uniqueItems: true
          description: IDs of the platforms to onboard on, as agreed with Datman. If
            omitted, the merchant is onboarded on all platforms.
          items:
            type: integer
            enum:
              - 1
              - 2
        businessType:
          type:
            - string
            - "null"
          enum:
            - Limited
            - Partnership
            - Sole Trader
            - Individual
            - Trust
            - Other
            - Corporation
            - ""
            - null
          description: "`create` only, optional. Allowed values depend on `country` (same
            rules as V1)."
        oldCredentials:
          allOf:
            - $ref: "#/components/schemas/CredentialsPair"
          description: Current user credentials. `update` only (required).
        newCredentials:
          allOf:
            - $ref: "#/components/schemas/CredentialsPair"
          description: New user credentials. `update` only (required). Must differ from
            `oldCredentials`.
        overrideDetails:
          type:
            - boolean
            - string
          enum:
            - true
            - false
            - "true"
            - "false"
          default: false
          description: "`patch` only. When false (default), only fields that are empty on
            the merchant are filled in. Fields that already have a value are
            skipped and listed in `skippedFields`. When true, existing values
            are overwritten."
        isSyncEnabled:
          type:
            - boolean
            - string
          enum:
            - true
            - false
            - "true"
            - "false"
          default: true
          description: "`patch` only. When true (default), the patched data is synced to
            the payment provider (transfer instrument, legal entity and business
            line updates)."
        attachments:
          type: array
          minItems: 1
          maxItems: 5
          description: "`uploadDocuments` only (required). At most one attachment per
            `documentTypeId`. File names must not repeat, and the decoded total
            must be 25 MB or less."
          items:
            $ref: "#/components/schemas/MerchantUploadAttachment"
        bankDetails:
          description: 'Bank account details. Required on `create`, optional on `patch`.
            May be sent encrypted as `{ "encryptedData": "..." }`.'
          oneOf:
            - $ref: "#/components/schemas/MerchantBankDetails"
            - $ref: "#/components/schemas/EncryptedBankDetails"
        businessDetails:
          allOf:
            - $ref: "#/components/schemas/MerchantBusinessDetails"
          description: Business details. Required on `create`, optional on `patch`.
            `businessType`, `organisationType` and `trustType` can't be changed
            with `patch`; they are ignored and listed in `ignoredFields`.
        ownerDetails:
          allOf:
            - $ref: "#/components/schemas/MerchantOwnerDetails"
          description: Owner details. Required on `create`, optional on `patch`.
        tradingDetails:
          allOf:
            - $ref: "#/components/schemas/MerchantTradingDetails"
          description: Trading details. Required on `create`, optional on `patch`.
        businessDealDetails:
          allOf:
            - $ref: "#/components/schemas/MerchantBusinessDealDetails"
          description: Commercial terms agreed with the reseller. Required on `create`.
            Validated on `patch` but not stored by it.
    MerchantAddress:
      type: object
      additionalProperties: false
      description: Postal address. On `create`, every key must be present; empty
        strings are allowed except where noted. On `patch` every key is
        optional.
      properties:
        addressLine1:
          type: string
          maxLength: 100
        addressLine2:
          type: string
          maxLength: 100
        state:
          type: string
          maxLength: 100
          description: "For Australia and the United States: required, and must be a valid
            state code. For other countries: free text, may be empty. Required
            in business and owner addresses."
        city:
          type: string
          maxLength: 100
        county:
          type: string
          maxLength: 100
        country:
          type: string
          maxLength: 80
        postCode:
          type: string
          maxLength: 100
    MerchantBankAddress:
      type: object
      description: "On `create` these keys must be present: `addressLine1`,
        `addressLine2`. On `patch` every key is optional."
      additionalProperties: false
      properties:
        addressLine1:
          type: string
          maxLength: 100
        addressLine2:
          type: string
          maxLength: 100
    MerchantBankDetails:
      type: object
      additionalProperties: false
      description: Bank account details. On `create`, every key must be present. Send
        an empty string for fields that don't apply to the merchant's country. A
        value that fails its format check is stored as an empty string instead
        of being rejected. On `patch` every key is optional.
      properties:
        accountName:
          type: string
          maxLength: 100
          description: Account holder name. The server converts it to upper case.
        bankSortCode:
          type: string
          pattern: ^(\d{6})?$
          description: 6-digit sort code (UK, Ireland).
        ibanNumber:
          type: string
          maxLength: 36
          description: IBAN. For Ireland it must be 22 characters (2 letters, 2 digits, 4
            letters, then digits).
        bsbNumber:
          type: string
          pattern: ^(\d{6})?$
          description: 6-digit BSB number (Australia).
        transitNumber:
          type: string
          pattern: ^(\d{5})?$
          description: 5-digit transit number (Canada).
        financialInstitutionNumber:
          type: string
          pattern: ^(\d{3})?$
          description: 3-digit financial institution number (Canada).
        routingNumber:
          type: string
          pattern: ^(\d{9})?$
          description: 9-digit routing number (United States).
        accountNumber:
          type: string
          pattern: ^\d*$
          description: "Account number, digits only. Length rules: UK 8, New Zealand
            15-16, Australia 5-9, United States 3-17, Mexico 18, Canada 7-12,
            other countries up to 30."
        bankName:
          type: string
          maxLength: 100
        address:
          $ref: "#/components/schemas/MerchantBankAddress"
    EncryptedBankDetails:
      type: object
      additionalProperties: false
      required:
        - encryptedData
      properties:
        encryptedData:
          type: string
          description: Encrypted bank details payload. The server decrypts it with the
            partner's encryption key, then validates the result as
            `MerchantBankDetails`.
    MerchantContact:
      type: object
      description: "On `create` these keys must be present: `email`. On `patch` every
        key is optional."
      additionalProperties: false
      properties:
        phoneNumber:
          type: string
          pattern: ^(\+\d{7,15})?$
          description: Phone number in E.164 format, or empty string. Required in
            `ownerDetails.contact`.
        email:
          type: string
          maxLength: 254
          description: Email address, or empty string.
        website:
          type: string
          description: Website URL (http or https), or empty string.
            `businessDetails.contact` only (required there).
    MerchantBusinessDetails:
      type: object
      description: "On `create` these keys must be present: `businessType`,
        `companyRegistrationNumber`, `organisationType`, `trustType`, `address`,
        `contact`. On `patch` every key is optional."
      additionalProperties: false
      properties:
        businessType:
          type: string
          enum:
            - Limited
            - Partnership
            - Sole Trader
            - Individual
            - Trust
            - Other
            - Corporation
          description: Business type. Allowed values depend on `country`.
        companyRegistrationNumber:
          type: string
          maxLength: 30
          pattern: ^\d*$
          description: Company registration number (digits only), or empty string.
        organisationType:
          type: string
          enum:
            - Association Incorporated
            - Governmental Organization
            - Non Profit
            - Partnership Incorporated
            - Private Company
        trustType:
          type: string
          enum:
            - Cash Management Trust
            - Corporate Unit Trust
            - Deceased Estate
            - Discretionary Investment Trust
            - Discretionary Services Management Trust
            - Discretionary Trading Trust
            - First Home Saver Accounts Trust
            - Fixed Trust
            - Fixed Unit Trust
            - Hybrid Trust
            - Listed Public Unit Trust
            - Other Trust
            - Pooled Superannuation Trust
            - Public Trading Trust
            - Unlisted Public Unit Trust
        address:
          $ref: "#/components/schemas/MerchantAddress"
        contact:
          $ref: "#/components/schemas/MerchantContact"
    MerchantOwnerDetails:
      type: object
      additionalProperties: false
      description: Owner details. On `create`, every key must be present. Send an
        empty string for identifiers that don't apply to the merchant's country.
        On `patch` every key is optional.
      properties:
        title:
          type: string
          enum:
            - Mr
            - Miss
            - Mrs
            - Ms
            - ""
        firstName:
          type: string
          maxLength: 80
        lastName:
          type: string
          maxLength: 80
        citizenship:
          type: string
          description: Nationality (e.g. British), from Datman's supported list, or empty
            string.
        dateOfBirth:
          type: string
          pattern: ^(\d{4}-\d{2}-\d{2})?$
          description: Date of birth as YYYY-MM-DD, or empty string.
        abnNumber:
          type: string
          pattern: ^(\d{11})?$
          description: 11-digit ABN (Australia).
        einNumber:
          type: string
          pattern: ^(\d{9})?$
          description: 9-digit EIN (United States).
        ssnNumber:
          type: string
          description: 9-digit SSN (United States).
        personalId:
          type: string
          maxLength: 100
          description: Personal ID, letters and digits only (Mexico).
        ppsNumber:
          type: string
          pattern: ^(\d{7}[A-Z]{1,2})?$
          description: PPS number (Ireland).
        vatNumber:
          type: string
          description: UK VAT number as GB followed by 9 digits, with valid check digits,
            or empty string.
        vatExists:
          type:
            - boolean
            - string
          enum:
            - true
            - false
            - ""
          description: Whether the owner has a VAT number. Boolean or empty string.
        address:
          $ref: "#/components/schemas/MerchantAddress"
        contact:
          $ref: "#/components/schemas/MerchantContact"
    MerchantTradingDetails:
      type: object
      description: "On `create` these keys must be present: `name`, `address`. On
        `patch` every key is optional."
      additionalProperties: false
      properties:
        name:
          type: string
          maxLength: 80
          description: Trading name.
        address:
          $ref: "#/components/schemas/MerchantAddress"
    MerchantBusinessDealDetails:
      type: object
      additionalProperties: false
      description: All values are decimal strings. Empty strings are allowed. On
        `patch` every key is optional.
      properties:
        setupFee:
          type: string
          pattern: ^(\d+(\.\d*)?|\.\d+)?$
        monthlyRent:
          type: string
          pattern: ^(\d+(\.\d*)?|\.\d+)?$
        contractDurationMonths:
          type: string
          pattern: ^\d*$
        fixedTransactionFee:
          type: string
          pattern: ^(\d(\.\d{1,2})?)?$
          description: Fixed fee per transaction, up to 9.99.
        interchangeRate:
          type: string
          pattern: ^(\d{1,2}(\.\d{1,2})?)?$
          description: Percentage fee, up to 99.99.
    MerchantUploadAttachment:
      type: object
      additionalProperties: false
      required:
        - documentTypeId
        - content
        - filename
      properties:
        documentTypeId:
          type: integer
          minimum: 1
          maximum: 17
          description: Datman document type ID. Front and back sides use separate IDs (3
            front / 17 back for a driving licence, 9 front / 10 back for an
            identity card).
        content:
          type: string
          contentEncoding: base64
          description: Base64-encoded file content, up to 10 MB decoded. The content must
            match the file extension.
        filename:
          type: string
          minLength: 1
          maxLength: 255
          pattern: \.(pdf|jpe?g|png)$
          description: File name ending in .pdf, .jpg, .jpeg or .png (case-insensitive).
    MerchantAssociationV2Response:
      type: object
      description: Result of the action. `create` returns the merchant fields.
        `reactivate` returns `message`. `update` returns `message` and
        `statusCode`. `patch` returns `message`, `merchantId` and optionally the
        skipped and ignored field lists.
      properties:
        message:
          description: Human-readable outcome. For a `patch` that fails validation, this
            is an array of field errors.
          oneOf:
            - type: string
            - type: array
              items:
                $ref: "#/components/schemas/FieldValidationError"
        statusCode:
          type: integer
          description: Datman internal outcome code (not an HTTP status), e.g. 6003
            credentials updated, 4005-4009 update not possible.
        merchantId:
          type:
            - integer
            - string
          description: Datman merchant ID. An integer on `create`, a string on `patch`.
        merchant_status:
          description: Merchant status value stored on the merchant record (`create`).
        account_verification_status:
          type: boolean
          description: Whether the merchant account is verified (`create`).
        bank_verification_status:
          type: boolean
          description: Whether the merchant bank account is verified (`create`).
        email:
          type: string
          format: email
          description: Owner email (`create`).
        responseCode:
          type: integer
          enum:
            - 1001
            - 1002
          description: Onboarding flow indicator (`create`). 1001 = staggered onboarding
            only. 1002 = owner or business details were supplied and will be
            applied after onboarding, so the account might become unverified.
        businessName:
          type: string
          description: Legal business name (`create`).
        tradingName:
          type: string
          description: Trading name (`create`).
        signup_link:
          type: string
          description: Portal link for the new user to complete signup. Only present when
            a new user was created.
        skippedFields:
          type: array
          items:
            type: string
          description: "`patch` only. Dot-notation paths of fields not updated because
            they already have a value and `overrideDetails` was false."
        skippedMessage:
          type: string
          description: "`patch` only. Explains `skippedFields`."
        ignoredFields:
          type: array
          items:
            type: string
          description: "`patch` only. Fields that can't be changed with `patch` and were
            ignored (e.g. `businessDetails.businessType`)."
        ignoredMessage:
          type: string
          description: "`patch` only. Explains `ignoredFields`."
    MerchantUploadDocumentsAccepted:
      type: object
      required:
        - message
        - statusCode
      properties:
        message:
          type: string
        reminder:
          type: string
          description: Present when only one side of a two-sided document was uploaded.
        statusCode:
          type: integer
          enum:
            - 10005
            - 10006
          description: Datman internal code. 10005 = accepted. 10006 = accepted, but the
            other side of the document is still needed.
    FieldValidationError:
      type: object
      properties:
        key:
          type: string
          description: Dot-notation path of the field.
        error:
          type: string
          description: Validation message.
    MerchantAssociationV2Error:
      type: object
      required:
        - message
      properties:
        message:
          description: Error message. When required onboarding fields are missing on
            `create`, this is an array of field errors.
          oneOf:
            - type: string
            - type: array
              items:
                $ref: "#/components/schemas/FieldValidationError"
        statusCode:
          type: integer
          description: Datman internal error code, when available (e.g. 9001 invalid JSON,
            10110 validation failed, 10111 document rejected, 7002 invalid
            reseller ID, 7003 reseller country mismatch).
        merchantId:
          type: integer
          description: Merchant ID, when the store is already associated.
        details:
          type: array
          description: Field-level validation problems (with statusCode 10110).
          items:
            type: object
            properties:
              path:
                type: string
                description: Field path, e.g. `attachments[0].filename`.
              message:
                type: string
    DocumentUploadForm:
      type: object
      required:
        - file
        - documentTypeId
      properties:
        file:
          type: string
          format: binary
          description: The document (JPG, JPEG, PNG or PDF, 100 KB to 10 MB). The part
            must have a Content-Type of image/jpeg, image/png or
            application/pdf. Send exactly one file, in a form field named
            `file`.
        documentTypeId:
          type: integer
          minimum: 1
          maximum: 15
          description: Datman document type ID.
      additionalProperties: false
    MessageError:
      type: object
      properties:
        message:
          type: string
          description: Error message.
    EmbedTokenResponse:
      type: object
      required:
        - token
        - expiresAt
      properties:
        token:
          type: string
          description: Session token (32 hex characters), valid for 10 minutes.
        expiresAt:
          type: integer
          description: Expiry time as a Unix timestamp in seconds.
    EmbedUrlResponse:
      type: object
      required:
        - url
        - expiresAt
      properties:
        url:
          type: string
          format: uri
          description: Embedded dashboard URL for the requested page, with the session
            token as the `token` query parameter.
        expiresAt:
          type: integer
          description: Expiry time as a Unix timestamp in seconds.
    HostedPaymentPayload:
      title: HostedPaymentPayload
      description: The payment details you encrypt into `data`. Keys are case-sensitive.
      type: object
      required:
        - host
        - merchant_id
        - order_id
        - customer_id
        - email
        - provider
        - phone_number
        - amount
        - redirect_url
        - cancel_url
        - webhook_url
        - back_url
        - first_name
        - last_name
      properties:
        host:
          type: string
          description: Your website's host, without `http://` or `https://`.
          example: sandbox.example.com
        merchant_id:
          type: integer
          description: The Datman merchant the payment is for.
          example: 63155480
        order_id:
          type:
            - string
            - integer
          description: Your unique order identifier.
          example: "987654321"
        customer_id:
          type:
            - string
            - integer
          description: Your identifier for the shopper. Saved cards are linked to it and
            can be reused for the same shopper later.
          example: CUST98765
        email:
          type: string
          format: email
          description: The shopper's email address.
          example: john.doe@example.com
        provider:
          type: string
          description: The provider value Datman gave you.
          example: provider_value
        phone_number:
          type: string
          description: The shopper's phone number, in international format.
          example: "+447911123456"
        name:
          type: string
          description: The merchant's business name.
          example: Adam's Kitchen
        amount:
          type: string
          pattern: ^\d+(\.\d{1,2})?$
          description: The amount to charge, in major units, as a string.
          example: "150.75"
        avs_house_number:
          type: string
          description: House number, for address verification.
          example: 221B
        avs_postcode:
          type: string
          description: Postcode, for address verification.
          example: NW16XE
        merchant_reference:
          type: string
          description: Your own reference for the payment.
          example: REF123456
        redirect_url:
          type: string
          format: uri
          description: Where the shopper goes after a successful payment. Use HTTPS.
          example: https://example.com/success
        cancel_url:
          type: string
          format: uri
          description: Where the shopper goes if they cancel. Use HTTPS.
          example: https://example.com/cancel
        webhook_url:
          type: string
          format: uri
          description: Where Datman sends the payment status webhook. Use HTTPS. Treat the
            webhook, not the redirect, as the final status.
          example: https://example.com/webhook
        back_url:
          type: string
          format: uri
          description: Where the shopper goes if they choose to go back to your site.
          example: https://example.com/back
        first_name:
          type: string
          description: The shopper's first name.
          example: John
        last_name:
          type: string
          description: The shopper's last name.
          example: Doe
        flat:
          type: string
          description: Flat or apartment number.
          example: 12A
        address1:
          type: string
          description: Address line 1.
          example: 221B Baker Street
        address2:
          type: string
          description: Address line 2.
          example: London
        statement_descriptor:
          type: string
          maxLength: 22
          description: Text on the shopper's card statement. Unsupported characters are
            removed and it's cut to 22 characters.
          example: ADAMS KITCHEN
        statement_descriptor_address:
          type: string
          maxLength: 20
          description: Second statement line, such as a town. Unsupported characters are
            removed and it's cut to 20 characters.
          example: London
        split_fee:
          type: array
          description: Pay part of the amount to other Datman merchants, for example a
            delivery fee to the delivery partner.
          items:
            $ref: "#/components/schemas/HostedSplitFee"
    HostedSplitFee:
      title: HostedSplitFee
      type: object
      required:
        - partner_merchant_id
        - type_id
        - value
        - value_type
      properties:
        partner_merchant_id:
          type:
            - string
            - integer
          description: The `merchant_id` that receives this part of the payment.
          example: "63155481"
        type_id:
          type:
            - string
            - integer
          description: "Commission type: 1 Food/Goods, 2 Marketplace Fee, 3 Delivery Fee,
            4 Delivery Tip, 5 Restaurant Tip, 6 Service Charge."
          example: "3"
        value:
          type:
            - string
            - number
          description: The amount, or the percentage when `value_type` is `percentage`.
          example: "10.50"
        value_type:
          type: string
          enum:
            - amount
            - percentage
          example: amount
    MessageResponse:
      type: object
      required:
        - message
      properties:
        message:
          type: string
    SplitFeeStatus:
      type: object
      properties:
        outcome:
          type: string
        message:
          type: string
    PaymentStatusWebhook:
      type: object
      properties:
        order_id:
          type: string
          description: Your original order reference.
        amount:
          type: string
          description: Amount in major units with two decimals (e.g. "10.00").
        currency:
          type: string
          description: ISO 4217 currency code.
        customer_id:
          type: string
          description: Your original shopper reference.
        xref:
          type: string
          description: Datman transaction reference in the form
            O{order_id}M{merchant_id}T{payment_id}.
        status:
          type: string
          description: Lower-cased payment event code (e.g. "authorisation", "capture").
        success:
          type: string
          enum:
            - "true"
            - "false"
          description: Whether the event succeeded, as a string.
        date:
          type: string
          description: Event date/time.
        three_ds_authenticated:
          type: string
        three_ds_authenticated_response:
          type: string
        card_bin:
          type: string
        last4_digits:
          type: string
        shopper_ip:
          type: string
        shopper_email:
          type: string
        expiry_date:
          type: string
        avs_result:
          type: string
        cvc_result:
          type: string
        card_type:
          type: string
          description: Card brand / payment method variant.
        reason:
          type: string
          description: Failure reason; present only when `success` is "false".
        split_fee_status:
          $ref: "#/components/schemas/SplitFeeStatus"
          description: Split fee outcome; present only on capture events for orders with
            split fees.
    RefundRequest:
      title: Refund (action=refund)
      type: object
      required:
        - merchant_id
        - order_id
        - amount
      properties:
        merchant_id:
          type:
            - string
            - integer
          description: The merchant that took the payment.
        order_id:
          type:
            - string
            - integer
          description: Your own order reference for the payment, as you sent it when paying.
        amount:
          type: number
          minimum: 0.01
          description: The amount to refund, in major units (e.g. 10.50).
        reason:
          type: string
          description: Why the payment is refunded.
        requested_by:
          type: string
          description: Who asked for the refund, for your records.
        refund_split_fee:
          $ref: "#/components/schemas/RefundSplitFee"
    RefundSplitFee:
      type: array
      description: How much to take back from each merchant that received part of the
        payment.
      items:
        type: object
        required:
          - partner_merchant_id
          - refund_amount
        properties:
          partner_merchant_id:
            type: integer
          refund_amount:
            type: number
            minimum: 0.01
    CaptureOrAdjustmentRequest:
      title: Capture or adjustment (action=capture, action=adjustment)
      type: object
      required:
        - xref
        - merchant_id
        - amount
      properties:
        xref:
          type: string
          pattern: ^O([A-Z]*\d+)M(\d+)T(\d+)$
          description: The payment's reference, `O<order_id>M<merchant_id>T<payment_id>`.
        merchant_id:
          type: string
          description: The merchant that took the payment, as a string.
        amount:
          type: number
          minimum: 0.01
          description: The amount to capture, or the new authorised amount for an
            adjustment, in major units.
        split_fee:
          type:
            - array
            - "null"
          description: Adjustment only. New split fees; when omitted the existing splits
            are kept.
          items:
            $ref: "#/components/schemas/HostedSplitFee"
    AuthReversalRequest:
      title: Auth reversal (action=auth_reversal)
      type: object
      required:
        - xref
        - merchant_id
      properties:
        xref:
          type: string
          pattern: ^O([A-Z]*\d+)M(\d+)T(\d+)$
          description: The payment's reference, `O<order_id>M<merchant_id>T<payment_id>`.
        merchant_id:
          type: string
          description: The merchant that took the payment, as a string.
    RefundResponse:
      type: object
      required:
        - outcome
      properties:
        outcome:
          type: string
          const: success
        message:
          type: string
          description: Present for an uncaptured pre-auth, which is captured first and
            then refunded.
        destination:
          type: object
          description: The amount refunded to each destination, as strings.
          additionalProperties:
            type: string
        transaction_methods:
          type: object
          description: The payment method of the original payment (ECOM, GPAY, APPLEPAY or
            WALLET) and its original total, as strings.
          additionalProperties:
            type: string
    PaymentModificationFailedResponse:
      type: object
      required:
        - outcome
      properties:
        outcome:
          type: string
          const: failed
        message:
          type: string
        code:
          type: integer
          description: An error code, present for some failures.
    PaymentModificationAcceptedResponse:
      type: object
      required:
        - outcome
        - payment_reference
        - status
      properties:
        outcome:
          type: string
          const: success
        payment_reference:
          type: string
          description: The payment provider's reference for the change.
        status:
          type: string
          description: The provider's status, e.g. `received` or `authorised`.
        amount:
          type: number
    PaymentModificationProviderError:
      type: object
      properties:
        outcome:
          type: string
          const: success
          description: Always `success` here; the HTTP status shows the failure.
        request_id:
          type: string
        message:
          type: string
        resultCode:
          type: string
        reason:
          type: string
    InternalTransferRequest:
      type: object
      additionalProperties: false
      required:
        - source_merchant_id
        - destination_merchant_id
        - amount
        - transfer_category_code
        - description
        - reference
        - webhook_url
      properties:
        source_merchant_id:
          type: string
          pattern: ^[0-9]+$
          description: The merchant the funds come from, as a string of digits.
        destination_merchant_id:
          type: string
          pattern: ^[0-9]+$
          description: The merchant the funds go to, as a string of digits.
        amount:
          type: integer
          minimum: 1
          description: The amount in minor units (e.g. 350 is £3.50).
        transfer_category_code:
          type: integer
          minimum: 1
          description: The category of the transfer, as agreed with Datman.
        description:
          type: string
        reference:
          type: string
          description: Your reference for the transfer. It is returned in the webhook.
        webhook_url:
          type: string
          format: uri
          maxLength: 2048
          description: Where Datman sends the transfer result. Use HTTPS.
        order_id:
          type:
            - string
            - integer
          description: The order the transfer relates to, if any.
    InternalTransferAccepted:
      type: object
      required:
        - request_id
        - reference
        - status
      properties:
        request_id:
          type: string
          description: Datman's id for the transfer. It is returned in the webhook.
        reference:
          type: string
        status:
          type: string
          const: processing
    ErrorCodeResponse:
      type: object
      required:
        - message
      properties:
        error_code:
          type: string
          description: Machine-readable error code. Not present on validation errors.
        message:
          type: string
    InternalTransferWebhookBase:
      type: object
      properties:
        request_id:
          type: string
          description: The `request_id` returned when you created the transfer.
        source_merchant_id:
          type:
            - string
            - integer
        destination_merchant_id:
          type:
            - string
            - integer
        amount:
          type: integer
          description: The amount in minor units.
        currency:
          type: string
          description: ISO 4217 currency code. Not present for every transfer.
        transfer_category_code:
          type: integer
        description:
          type: string
        reference:
          type: string
          description: Your reference for the transfer.
        webhook_url:
          type: string
        order_id:
          type:
            - string
            - integer
          description: Present only if you sent it.
    InternalTransferSucceededWebhook:
      allOf:
        - $ref: "#/components/schemas/InternalTransferWebhookBase"
        - type: object
          required:
            - request_id
            - status
          properties:
            status:
              type: string
              const: success
    InternalTransferFailedWebhook:
      allOf:
        - $ref: "#/components/schemas/InternalTransferWebhookBase"
        - type: object
          required:
            - request_id
            - reason
          properties:
            reason:
              type: string
              description: Why the transfer failed, e.g. "Insufficient funds" or "Transfer
                failed".
    SplitCommissionType:
      type: object
      properties:
        id:
          type: integer
        commission_type:
          type: string
        business_provider:
          type:
            - string
            - "null"
          description: Your partner name for custom types; `null` for global types.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    SplitCommissionTypeList:
      type: object
      properties:
        requestId:
          type: string
        outcome:
          type: string
          const: success
        data:
          type: object
          properties:
            custom:
              type: array
              items:
                $ref: "#/components/schemas/SplitCommissionType"
            global:
              type: array
              items:
                $ref: "#/components/schemas/SplitCommissionType"
    SplitCommissionTypeRequest:
      type: object
      required:
        - commission_type
      properties:
        commission_type:
          type: string
          minLength: 1
          description: The name of the commission type.
    SplitCommissionTypeResult:
      type: object
      properties:
        requestId:
          type: string
        outcome:
          type: string
          const: success
        data:
          $ref: "#/components/schemas/SplitCommissionType"
    OutcomeMessageResponse:
      type: object
      properties:
        requestId:
          type: string
        outcome:
          type: string
        message:
          type: string
    OutcomeErrorResponse:
      type: object
      required:
        - outcome
        - message
      properties:
        requestId:
          type: string
        outcome:
          type: string
          const: failed
        message:
          type: string
  responses:
    Unauthorized:
      description: Missing, invalid, expired or revoked credentials.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              code: UNAUTHORIZED
              message: Invalid, expired, or revoked API key
    Forbidden:
      description: The caller may not access this route or reseller (for example the
        API key has no reseller, or the body names a different reseller).
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              code: FORBIDDEN
              message: Reseller not allowed for this caller
    RateLimited:
      description: The per-reseller rate limit was exceeded.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              code: RATE_LIMITED
              message: Rate limit exceeded
    InternalError:
      description: The query or a required configuration failed. Underlying details
        are not returned.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              code: INTERNAL_ERROR
              message: Query failed
    ServiceUnavailable:
      description: The database timed out or closed the connection. Safe to retry.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          example:
            error:
              code: DB_TIMEOUT
              message: The database did not respond in time. Please retry.
    PaymentModificationProviderFailed:
      description: The payment provider returned an error. `outcome` is still
        `success`; read `message`.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/PaymentModificationProviderError"
          examples:
            providerError:
              summary: Provider error
              value:
                outcome: success
                request_id: 5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                message: Unable to process your request at the moment. Please try again later.
    SplitCommissionUnauthorized:
      description: The `api_token` header is missing or invalid.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/OutcomeErrorResponse"
          examples:
            invalidToken:
              summary: Missing or invalid api_token
              value:
                requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                outcome: failed
                message: Token is empty or Invalid token
    SplitCommissionServerError:
      description: Internal server error.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/OutcomeErrorResponse"
          examples:
            serverError:
              summary: Internal server error
              value:
                requestId: reqid_5b0d6f0e-4c1a-4b8e-9a51-3f3a2d1c7e90
                outcome: failed
                message: Internal server error
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: api_key
      description: Partner API key issued by Datman.
    DocumentUploadApiKey:
      type: apiKey
      in: header
      name: api_key
      description: Document upload API key issued by Datman for the document upload
        endpoint. It is a different key from the partner API key.
    ApiTokenAuth:
      type: apiKey
      in: header
      name: api_token
      description: API token issued by Datman.
  parameters:
    DatmanSignature:
      name: X-Datman-Signature
      in: header
      required: true
      description: HMAC-SHA256 of the raw JSON body using your webhook secret, hex-encoded.
      schema:
        type: string
