payments-ai Public API

The Public Api API from payments-ai — 9 operation(s) for public api.

Operations 13

GET /v1/public-api/me/merchants List merchants #
POST /v1/public-api/me/merchants Create merchant #
GET /v1/public-api/merchants/{merchantId}/balances/summary Summary balance #
GET /v1/public-api/merchants/{merchantId}/discount-codes List codes #
POST /v1/public-api/merchants/{merchantId}/discount-codes Create code #
GET /v1/public-api/merchants/{merchantId}/discount-codes/{id} Get code by id #
PATCH /v1/public-api/merchants/{merchantId}/discount-codes/{id} Update code #
POST /v1/public-api/merchants/{merchantId}/discount-codes/{id}/archive Archive code #
POST /v1/public-api/merchants/{merchantId}/payouts Request payout #
GET /v1/public-api/merchants/{merchantId}/payouts/payout-methods List payout methods #
GET /v1/public-api/merchants/{merchantId}/settings/tax Get api #
PATCH /v1/public-api/merchants/{merchantId}/settings/tax Update api #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/payments-ai:payments-ai-public-api-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

payments-ai-public-api-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Payments AI MoR Merchant Public Public API
  version: 1.0.0
  description: Merchant Public API, partner onboarding, and buyer checkout endpoints. Authenticate every call with a Merchant API Key (pai_test_* / pai_live_*). The same key reaches its own merchant resources and those of any sub-merchant it has onboarded via POST /v1/public-api/merchants.
servers:
- url: https://sandbox.mor.payments.ai/api
  description: Sandbox API
tags:
- name: Public API
paths:
  /v1/public-api/me/merchants:
    get:
      operationId: PublicApiOwnMerchants_list
      description: 'Lists the merchants the signed-in user is an active member of, with the user''s role on each. Auth: user OAuth credential with `merchant:read` · tenant none (the user''s memberships) · no role · 401 `auth.invalid_token` · 403 `auth.insufficient_scope`, `auth.credential_type_forbidden`.'
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiOwnMerchantListResponse'
      tags:
      - Public API
      security:
      - UserOAuthCredentialAuth: []
      summary: List merchants
    post:
      operationId: PublicApiOwnMerchants_create
      description: 'Creates a top-level merchant on this environment with the signed-in user as Owner. Auth: user OAuth credential with `merchant:create` · tenant none · no role (the caller becomes Owner) · 401 `auth.invalid_token` · 403 `auth.insufficient_scope`, `auth.credential_type_forbidden` · 400 `invalid_request` no `email` and none on the user · 409 `merchant.create_conflict` when `merchantId` is reused with different details · 409 `merchant.limit_reached` when the user already owns 50 top-level merchants (idempotent replay of an existing owned `merchantId` still succeeds).'
      parameters: []
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiCreateOwnMerchantResponse'
        '201':
          description: The request has succeeded and a new resource has been created as a result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiCreateOwnMerchantResponse'
      tags:
      - Public API
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicApiCreateOwnMerchantRequest'
      security:
      - UserOAuthCredentialAuth: []
      summary: Create merchant
  /v1/public-api/merchants/{merchantId}/balances/summary:
    get:
      operationId: PublicApiBalances_summary
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiBalanceSummaryResponse'
      tags:
      - Public API
      summary: Summary balance
  /v1/public-api/merchants/{merchantId}/discount-codes:
    get:
      operationId: PublicApiDiscountCodes_list
      description: List the merchant's discount codes, archived ones included unless filtered out.
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      - name: search
        in: query
        required: false
        description: Matches internal name or code.
        schema:
          type: string
        explode: false
      - name: status
        in: query
        required: false
        schema:
          $ref: '#/components/schemas/PublicApiDiscountCodeStatus'
        explode: false
      - name: promoType
        in: query
        required: false
        schema:
          $ref: '#/components/schemas/PublicApiDiscountPromoType'
        explode: false
      - name: billingPeriod
        in: query
        required: false
        schema:
          $ref: '#/components/schemas/PublicApiDiscountBillingPeriod'
        explode: false
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          format: int32
          maximum: 100
          default: 20
        explode: false
      - name: page
        in: query
        required: false
        schema:
          type: integer
          format: int32
          default: 1
        explode: false
      - name: sortBy
        in: query
        required: false
        schema:
          $ref: '#/components/schemas/PublicApiDiscountCodeSortField'
        explode: false
      - name: sortOrder
        in: query
        required: false
        schema:
          type: string
          enum:
          - asc
          - desc
        explode: false
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiDiscountCodeListResponse'
      summary: List codes
      tags:
      - Public API
    post:
      operationId: PublicApiDiscountCodes_create
      description: Create a discount code and sync it to the payment provider. A code that already exists for the merchant returns 409. A repeat with the same Idempotency-Key returns the first code and does not compare the body.
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      - name: idempotency-key
        in: header
        required: false
        description: Optional. Maximum 255 characters.
        schema:
          type: string
          maxLength: 255
      responses:
        '201':
          description: The request has succeeded and a new resource has been created as a result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiDiscountCode'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicApiCreateDiscountCodeRequest'
      summary: Create code
      tags:
      - Public API
  /v1/public-api/merchants/{merchantId}/discount-codes/{id}:
    get:
      operationId: PublicApiDiscountCodes_getById
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiDiscountCode'
      summary: Get code by id
      tags:
      - Public API
    patch:
      operationId: PublicApiDiscountCodes_update
      description: Update a discount code. Archived codes return 409.
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiDiscountCode'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicApiUpdateDiscountCodeRequest'
      summary: Update code
      tags:
      - Public API
  /v1/public-api/merchants/{merchantId}/discount-codes/{id}/archive:
    post:
      operationId: PublicApiDiscountCodes_archive
      description: Archive a discount code. It stays readable but can no longer be redeemed or updated. There is no delete.
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiDiscountCode'
      summary: Archive code
      tags:
      - Public API
  /v1/public-api/merchants/{merchantId}/join-link:
    post:
      operationId: PublicApiMerchantJoinLink_remint
      description: Re-mint an owner-claim join URL for a sub-merchant with no owner attached yet. The caller's key must be allowed to access `merchantId` (your own key for a sub-merchant you created). Each call invalidates the previously issued link, so do not call it to check whether the seller claimed the merchant — read `ownerAttached` from `GET /v1/public-api/merchants/{merchantId}` instead. Returns 409 once an owner has been claimed.
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      responses:
        '201':
          description: The request has succeeded and a new resource has been created as a result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiMerchantJoinLinkResponse'
      tags:
      - Public API
      summary: Remint link
  /v1/public-api/merchants/{merchantId}/payouts:
    post:
      operationId: PublicApiPayouts_requestPayout
      description: 'Request a payout of available funds to a saved payout method. Requires `Idempotency-Key`; retries with the same key and body return the original `withdrawalId`. The key must have been granted the `payouts:write` permission from the dashboard, otherwise the request returns 403. Only the key''s own merchant may request a payout: a parent merchant''s key gets 403 for a sub-merchant.'
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      - name: idempotency-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '201':
          description: The request has succeeded and a new resource has been created as a result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiRequestPayoutResponse'
      tags:
      - Public API
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicApiRequestPayoutBody'
      summary: Request payout
  /v1/public-api/merchants/{merchantId}/payouts/payout-methods:
    get:
      operationId: PublicApiPayouts_listPayoutMethods
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiPayoutMethodsResponse'
      tags:
      - Public API
      summary: List payout methods
  /v1/public-api/merchants/{merchantId}/settings/tax:
    get:
      operationId: PublicApiMerchantTaxSettingsApi_get
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiMerchantTaxSettings'
      tags:
      - Public API
      summary: Get api
    patch:
      operationId: PublicApiMerchantTaxSettingsApi_update
      parameters:
      - name: merchantId
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: The request has succeeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiMerchantTaxSettings'
      tags:
      - Public API
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicApiMerchantTaxSettingsPatch'
      summary: Update api
components:
  schemas:
    PublicApiMerchantTaxSettingsPatch:
      type: object
      required:
      - defaultTaxBehavior
      properties:
        defaultTaxBehavior:
          type: string
          enum:
          - exclusive
          - inclusive
    PublicApiOwnMerchantListResponse:
      type: object
      required:
      - data
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PublicApiOwnMerchant'
    PublicApiDiscountCodeListItem:
      type: object
      required:
      - id
      - internalName
      - scopeLabel
      - code
      - status
      - promoType
      - amountOff
      - currency
      - amountDisplay
      - billingPeriod
      - billingPeriodLength
      - billingPeriodUnit
      - billingPeriodLabel
      - expiresAt
      - productId
      - createdAt
      properties:
        id:
          type: string
        internalName:
          type: string
        scopeLabel:
          type: string
        code:
          type: string
        status:
          $ref: '#/components/schemas/PublicApiDiscountCodeStatus'
        promoType:
          $ref: '#/components/schemas/PublicApiDiscountPromoType'
        amountOff:
          type: string
          description: Decimal string. A flat amount uses its currency's minor units, for example "10.00" usd or "500" jpy; a percentage has two decimals, for example "20.00".
        currency:
          type: string
          allOf:
          - $ref: '#/components/schemas/SharedTypes.CurrencyCode'
          nullable: true
        amountDisplay:
          type: string
        billingPeriod:
          $ref: '#/components/schemas/PublicApiDiscountBillingPeriod'
        billingPeriodLength:
          type: integer
          format: int32
          nullable: true
        billingPeriodUnit:
          allOf:
          - $ref: '#/components/schemas/PublicApiDiscountBillingPeriodUnit'
          nullable: true
        billingPeriodLabel:
          type: string
        expiresAt:
          type: string
          format: date-time
          nullable: true
        productId:
          type: string
          nullable: true
        createdAt:
          type: string
          format: date-time
    PublicApiDiscountPromoType:
      type: string
      enum:
      - percentage
      - flat_amount
    PublicApiTeamRole:
      type: string
      enum:
      - owner
      - admin
      - editor
      - viewer
    PublicApiDiscountCodeStatus:
      type: string
      enum:
      - active
      - expired
      - archived
      description: '`expired` is derived from expiresAt. `archived` codes stay readable but cannot be redeemed or updated.'
    PublicApiMerchantJoinLinkResponse:
      type: object
      required:
      - joinUrl
      - joinUrlExpiresAt
      properties:
        joinUrl:
          type: string
          description: Freshly minted owner-claim join URL (7-day TTL). The previously-issued token, if any, is invalidated by this call.
        joinUrlExpiresAt:
          type: string
          format: date-time
    PaginationMeta:
      type: object
      required:
      - totalRecords
      - totalPages
      - currentPage
      - limit
      properties:
        totalRecords:
          type: integer
          format: int32
        totalPages:
          type: integer
          format: int32
        currentPage:
          type: integer
          format: int32
        limit:
          type: integer
          format: int32
    PublicApiCreateDiscountCodeRequest:
      type: object
      required:
      - internalName
      - code
      - promoType
      - amountOff
      - billingPeriod
      properties:
        internalName:
          type: string
          minLength: 1
          maxLength: 255
          description: Name shown to the merchant only.
        code:
          type: string
          minLength: 1
          maxLength: 255
          description: Code the buyer types at checkout. Stored upper case and unique per merchant. Cannot be changed after create.
        promoType:
          $ref: '#/components/schemas/PublicApiDiscountPromoType'
        amountOff:
          anyOf:
          - $ref: '#/components/schemas/PublicApiDiscountAmountOff'
          - $ref: '#/components/schemas/SharedTypes.MoneyAmountValue'
          description: 'For percentage: greater than 0 and at most 100. For flat_amount: money in `currency`, a whole number of that currency''s minor unit (whole yen for jpy, so 500 and not 500.5).'
        currency:
          allOf:
          - $ref: '#/components/schemas/SharedTypes.CurrencyCode'
          description: Required when promoType is flat_amount. Lowercase ISO 4217.
        billingPeriod:
          $ref: '#/components/schemas/PublicApiDiscountBillingPeriod'
        billingPeriodLength:
          type: integer
          format: int32
          minimum: 1
          description: Required when billingPeriod is repeating.
        billingPeriodUnit:
          allOf:
          - $ref: '#/components/schemas/PublicApiDiscountBillingPeriodUnit'
          description: Required when billingPeriod is repeating.
        productId:
          type: string
          nullable: true
          description: Product the code is limited to. Omit or send null for a store-wide code.
        expiresAt:
          type: string
          format: date-time
          description: The code stops applying after this time. Omit for no expiry.
    PublicApiDiscountAmountOff:
      type: string
      description: Decimal string, for example "20" or "10.50". A JSON number is also accepted.
    PublicApiRequestPayoutBody:
      type: object
      required:
      - amount
      - payout_method_id
      properties:
        amount:
          $ref: '#/components/schemas/SharedTypes.MoneyAmountValue'
        currency:
          allOf:
          - $ref: '#/components/schemas/SharedTypes.CurrencyCode'
          description: ISO 4217 currency code. Defaults to `usd` when omitted.
        payout_method_id:
          type: string
    PublicApiRequestPayoutResponse:
      type: object
      required:
      - withdrawalId
      properties:
        withdrawalId:
          type: string
    PublicApiOwnMerchant:
      type: object
      required:
      - merchantId
      - name
      - role
      properties:
        merchantId:
          type: string
        name:
          type: string
          description: Business name as submitted on create, without the stored suffix.
        role:
          allOf:
          - $ref: '#/components/schemas/PublicApiTeamRole'
          description: The signed-in user's team role on this merchant.
    PublicApiDiscountCodeSortField:
      type: string
      enum:
      - internalName
      - expiresAt
    PublicApiBalanceCurrencyBreakdown:
      type: object
      required:
      - currency
      - available
      - pending
      - total
      - isNegative
      properties:
        currency:
          $ref: '#/components/schemas/SharedTypes.CurrencyCode'
        available:
          $ref: '#/components/schemas/SharedTypes.MoneyAmountValue'
        pending:
          $ref: '#/components/schemas/SharedTypes.MoneyAmountValue'
        total:
          $ref: '#/components/schemas/SharedTypes.MoneyAmountValue'
        isNegative:
          type: boolean
    PublicApiPayoutMethodItem:
      type: object
      required:
      - id
      - externalPayoutMethodId
      - currency
      - accountReference
      - institutionName
      - nickname
      - destinationCategory
      - destinationCountryCode
      - destinationName
      - isDefault
      properties:
        id:
          type: string
        externalPayoutMethodId:
          type: string
        currency:
          type: string
        accountReference:
          type: string
          nullable: true
        institutionName:
          type: string
          nullable: true
        nickname:
          type: string
          nullable: true
        destinationCategory:
          type: string
          nullable: true
        destinationCountryCode:
          type: string
          nullable: true
        destinationName:
          type: string
          nullable: true
        isDefault:
          type: boolean
    PublicApiUpdateDiscountCodeRequest:
      type: object
      properties:
        code:
          type: string
          minLength: 1
          maxLength: 255
        internalName:
          type: string
          minLength: 1
          maxLength: 255
        promoType:
          $ref: '#/components/schemas/PublicApiDiscountPromoType'
        amountOff:
          anyOf:
          - $ref: '#/components/schemas/PublicApiDiscountAmountOff'
          - $ref: '#/components/schemas/SharedTypes.MoneyAmountValue'
        currency:
          $ref: '#/components/schemas/SharedTypes.CurrencyCode'
        billingPeriod:
          $ref: '#/components/schemas/PublicApiDiscountBillingPeriod'
        billingPeriodLength:
          type: integer
          format: int32
          nullable: true
          minimum: 1
          description: Required with billingPeriod repeating. Cleared when billingPeriod becomes once or forever.
        billingPeriodUnit:
          allOf:
          - $ref: '#/components/schemas/PublicApiDiscountBillingPeriodUnit'
          nullable: true
          description: Required with billingPeriod repeating. Cleared when billingPeriod becomes once or forever.
        productId:
          type: string
          nullable: true
          description: Send null to make the code store-wide.
        expiresAt:
          type: string
          format: date-time
          nullable: true
          description: Send null to remove the expiry.
      description: Send only the fields to change. `code` may be sent only with its current value.
    PublicApiDiscountBillingPeriodUnit:
      type: string
      enum:
      - day
      - week
      - month
      - year
    PublicApiDiscountBillingPeriod:
      type: string
      enum:
      - once
      - repeating
      - forever
      description: 'How long the discount applies to a subscription: the first payment only (once), a number of billing periods (repeating), or every payment (forever).'
    SharedTypes.MoneyAmountValue:
      type: number
      format: decimal
      description: Decimal money amount for financial values.
    SharedTypes.CurrencyCode:
      type: string
      pattern: ^[a-z]{3}$
      description: ISO 4217 currency code. Always lowercase (e.g. 'usd', 'eur').
    PublicApiDiscountCodeListResponse:
      type: object
      required:
      - data
      - meta
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/PublicApiDiscountCodeListItem'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
    PublicApiCreateOwnMerchantResponse:
      type: object
      required:
      - merchantId
      - created
      properties:
        merchantId:
          type: string
        created:
          type: boolean
          description: True on first create; false when the call returned a merchant that already existed for this user or this `merchantId`.
    PublicApiDiscountCode:
      type: object
      required:
      - id
      - merchantId
      - internalName
      - code
      - promoType
      - amountOff
      - currency
      - billingPeriod
      - billingPeriodLength
      - billingPeriodUnit
      - productId
      - expiresAt
      - status
      - scopeLabel
      - amountDisplay
      - billingPeriodLabel
      - createdAt
      - updatedAt
      properties:
        id:
          type: string
        merchantId:
          type: string
        internalName:
          type: string
        code:
          type: string
        promoType:
          $ref: '#/components/schemas/PublicApiDiscountPromoType'
        amountOff:
          type: string
          description: Decimal string. A flat amount uses its currency's minor units, for example "10.00" usd or "500" jpy; a percentage has two decimals, for example "20.00".
        currency:
          type: string
          allOf:
          - $ref: '#/components/schemas/SharedTypes.CurrencyCode'
          nullable: true
        billingPeriod:
          $ref: '#/components/schemas/PublicApiDiscountBillingPeriod'
        billingPeriodLength:
          type: integer
          format: int32
          nullable: true
        billingPeriodUnit:
          allOf:
          - $ref: '#/components/schemas/PublicApiDiscountBillingPeriodUnit'
          nullable: true
        productId:
          type: string
          nullable: true
          description: Null for a store-wide code.
        expiresAt:
          type: string
          format: date-time
          nullable: true
        status:
          $ref: '#/components/schemas/PublicApiDiscountCodeStatus'
        scopeLabel:
          type: string
          description: All Products, or the scoped product's name.
        amountDisplay:
          type: string
          description: Display text, for example "20% OFF".
        billingPeriodLabel:
          type: string
          description: Display text, for example "Once" or "3 Months".
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    PublicApiPayoutMethodsResponse:
      type: object
      required:
      - payoutMethods
      properties:
        payoutMethods:
          type: array
          items:
            $ref: '#/components/schemas/PublicApiPayoutMethodItem'
    PublicApiCreateOwnMerchantRequest:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          maxLength: 145
          description: Business name displayed to customers. `'s Merchant` is appended when stored. Capped at 145 so the provider company title fits.
        email:
          type: string
          format: email
          description: Optional merchant contact email. Defaults to the signed-in user's email; 400 `invalid_request` when omitted and the user has no email on file. The signed-in user becomes Owner whatever this value is.
        phone:
          type: string
          pattern: ^\+[1-9]\d{1,14}$
          description: Optional E.164 phone. The identity-verification link is sent to it by SMS after go-live; if omitted, the merchant provides it during KYC.
        merchantId:
          type: string
          description: 'Optional client-supplied UUID v7 retry key. Re-submitting the same id with the same details returns the original merchant with `created: false`; the same id with different details returns 409. Without it, a user who already owns a merchant on this environment gets that merchant back with `created: false`.'
    PublicApiBalanceSummaryResponse:
      type: object
      required:
      - needsLedgerAccount
      - balances
      properties:
        needsLedgerAccount:
          type: boolean
        balances:
          type: array
          items:
            $ref: '#/components/schemas/PublicApiBalanceCurrencyBreakdown'
    PublicApiMerchantTaxSettings:
      type: object
      required:
      - defaultTaxBehavior
      properties:
        defaultTaxBehavior:
          type: string
          enum:
          - exclusive
          - inclusive
  securitySchemes:
    UserOAuthCredentialAuth:
      type: http
      scheme: Bearer
      description: 'Signed-in user OAuth credential (`pai_mcp_*`) issued through the dashboard consent screen for this API: the authorization and token requests name the RFC 8707 resource `<API_URL>/v1/public-api` (ADR-0020). Credentials issued for the MCP server, or for no resource, are rejected with 401 `auth.invalid_token` and `WWW-Authenticate: Bearer resource_metadata="<API_URL>/.well-known/oauth-protected-resource/v1/public-api", error="invalid_token"`. Valid on the environment that issued it only. Each operation that accepts it names one required permission; a missing permission is 403 `auth.insufficient_scope` with `WWW-Authenticate: Bearer error="insufficient_scope", scope="<permission>"`. A merchant outside the user''s active memberships is 403 `merchant.access_forbidden`; a team role below the operation''s minimum is 403 `team.role_forbidden`.'
    MerchantApiKeyAuth:
      type: http
      scheme: Bearer
      description: 'Merchant API key from Developer Tools → API Keys. Example: `Authorization: Bearer pai_test_...`. Also accepted for any active sub-merchant this key''s own merchant created.'