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

# Record a Payment observation

> Appends immutable payment, refund, or reversal evidence and updates the balance atomically under the Matter lock. A reversal must target one unreversed, non-reversal observation owned by the authenticated Source integration on the same Client and Matter, with an exact amount and currency match.



## OpenAPI

````yaml /openapi/partner-api-v1.yaml put /v1/clients/{clientCode}/matters/by-client-reference/{clientReferenceId}/payment-observations/{externalPaymentId}
openapi: 3.1.0
info:
  title: CasePath IQ Partner API v1
  version: 1.0.0
  summary: Inbound Matter API for approved partner integrations
  license:
    name: Proprietary
    identifier: LicenseRef-Proprietary
  description: >-
    CasePath IQ Partner API v1 for scoped Matter intake, payment observations,
    lifecycle commands and polling. Sandbox callers use a Sandbox Bearer API key
    supplied securely at onboarding; no Microsoft sign-in or IP allowlist setup
    is required for new unrestricted Sandbox keys. Production onboarding is
    separate and is not advertised by this Sandbox specification.


    Every error is `application/problem+json`. Methods a route does not support,
    including `HEAD` and `OPTIONS`, return `405` with an `Allow` header, and
    unknown paths under `/v1` return `404`. Each key is limited to a fixed
    number of requests per minute; `429` and `503` carry `Retry-After`. While
    the platform pauses Partner API writes, every write returns `503
    partner_writes_paused` and reads continue.
servers:
  - url: https://api.sandbox.casepathiq.com
    description: Sandbox testing
security:
  - PartnerKey: []
tags:
  - name: Matters
    description: Place, update, and read partner-owned Matter source data
  - name: Synchronization
    description: Pull minimized current-state changes for one granted Client
  - name: Payments
    description: Record and read immutable external payment evidence
  - name: Lifecycle
    description: Apply explicit, predecessor-bound Matter lifecycle transitions
paths:
  /v1/clients/{clientCode}/matters/by-client-reference/{clientReferenceId}/payment-observations/{externalPaymentId}:
    parameters:
      - $ref: '#/components/parameters/ClientCode'
      - $ref: '#/components/parameters/ClientReferenceId'
      - $ref: '#/components/parameters/ExternalPaymentId'
    put:
      tags:
        - Payments
      summary: Record a Payment observation
      description: >-
        Appends immutable payment, refund, or reversal evidence and updates the
        balance atomically under the Matter lock. A reversal must target one
        unreversed, non-reversal observation owned by the authenticated Source
        integration on the same Client and Matter, with an exact amount and
        currency match.
      operationId: putPaymentObservation
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PaymentObservationRequest'
            example:
              type: payment
              amount: '200.00'
              currency: EUR
              effectiveOn: '2026-08-27'
              channel: direct_to_creditor
              reference: BP-5521
              resultingOutstandingAmount: '1050.00'
      responses:
        '200':
          $ref: '#/components/responses/PaymentSuccess'
        '201':
          $ref: '#/components/responses/PaymentCreated'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '408':
          $ref: '#/components/responses/RequestTimeout'
        '409':
          $ref: '#/components/responses/Conflict'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '415':
          $ref: '#/components/responses/UnsupportedMediaType'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
        default:
          $ref: '#/components/responses/Problem'
components:
  parameters:
    ClientCode:
      name: clientCode
      in: path
      required: true
      description: Granted Local Authority Client code
      schema:
        $ref: '#/components/schemas/ClientCodeValue'
    ClientReferenceId:
      name: clientReferenceId
      in: path
      required: true
      description: Stable partner Matter key; must not contain personal data
      schema:
        $ref: '#/components/schemas/ClientReferenceIdValue'
    ExternalPaymentId:
      name: externalPaymentId
      in: path
      required: true
      description: Stable Payment observation key; must not contain personal data
      schema:
        $ref: '#/components/schemas/ExternalPaymentIdValue'
  schemas:
    PaymentObservationRequest:
      oneOf:
        - title: Payment or refund
          type: object
          additionalProperties: false
          required:
            - type
            - amount
            - currency
            - effectiveOn
            - channel
            - resultingOutstandingAmount
          properties:
            type:
              type: string
              enum:
                - payment
                - refund
            amount:
              $ref: '#/components/schemas/PositiveMoney'
            currency:
              type: string
              pattern: ^[A-Z]{3}$
            effectiveOn:
              type: string
              format: date
              description: >-
                Real calendar date, 2000-01-01 or later and at most 31 days
                after today (UTC); evidence only.
            channel:
              type: string
              enum:
                - direct_to_creditor
                - bank_transfer
                - card
                - cash
                - other
            reference:
              type: string
              maxLength: 2000
            resultingOutstandingAmount:
              $ref: '#/components/schemas/Money'
        - title: Reversal
          type: object
          additionalProperties: false
          required:
            - type
            - amount
            - currency
            - effectiveOn
            - reversesExternalPaymentId
            - resultingOutstandingAmount
          properties:
            type:
              type: string
              const: reversal
            amount:
              $ref: '#/components/schemas/PositiveMoney'
            currency:
              type: string
              pattern: ^[A-Z]{3}$
            effectiveOn:
              type: string
              format: date
              description: >-
                Real calendar date, 2000-01-01 or later and at most 31 days
                after today (UTC); evidence only.
            reference:
              type: string
              maxLength: 2000
            reversesExternalPaymentId:
              $ref: '#/components/schemas/ExternalPaymentIdValue'
            resultingOutstandingAmount:
              $ref: '#/components/schemas/Money'
    ClientCodeValue:
      type: string
      pattern: ^[A-Z][A-Z0-9]{1,31}$
      example: SDCC
    ClientReferenceIdValue:
      type: string
      pattern: ^(?!\.{1,2}$)[A-Za-z0-9._-]{1,128}$
      description: 1-128 characters; `.` and `..` alone are refused.
      example: SDCC-2026-00482
    ExternalPaymentIdValue:
      type: string
      pattern: ^(?!\.{1,2}$)[A-Za-z0-9._-]{1,128}$
      description: 1-128 characters; `.` and `..` alone are refused.
      example: payobs_01JEXAMPLE
    PositiveMoney:
      type: string
      pattern: ^(0\.(0[1-9]|[1-9][0-9])|[1-9][0-9]*\.[0-9]{2})$
      maxLength: 15
      example: '200.00'
    Money:
      type: string
      pattern: ^(0|[1-9][0-9]*)\.[0-9]{2}$
      maxLength: 15
      example: '1250.00'
    PaymentObservationResponse:
      type: object
      additionalProperties: false
      required:
        - clientCode
        - clientReferenceId
        - externalPaymentId
        - matterId
        - type
        - amount
        - currency
        - effectiveOn
        - resultingOutstandingAmount
        - createdAt
        - updatedAt
      description: >-
        Payment/refund include channel; reversal includes
        reversesExternalPaymentId and omits channel.
      allOf:
        - if:
            properties:
              type:
                enum:
                  - payment
                  - refund
            required:
              - type
          then:
            properties:
              channel: {}
            required:
              - channel
            not:
              properties:
                reversesExternalPaymentId: {}
              required:
                - reversesExternalPaymentId
        - if:
            properties:
              type:
                const: reversal
            required:
              - type
          then:
            properties:
              reversesExternalPaymentId: {}
            required:
              - reversesExternalPaymentId
            not:
              properties:
                channel: {}
              required:
                - channel
      properties:
        clientCode:
          $ref: '#/components/schemas/ClientCodeValue'
        clientReferenceId:
          $ref: '#/components/schemas/ClientReferenceIdValue'
        externalPaymentId:
          $ref: '#/components/schemas/ExternalPaymentIdValue'
        matterId:
          type: string
        type:
          type: string
          enum:
            - payment
            - refund
            - reversal
        amount:
          $ref: '#/components/schemas/PositiveMoney'
        currency:
          type: string
          pattern: ^[A-Z]{3}$
        effectiveOn:
          type: string
          format: date
        channel:
          type: string
          enum:
            - direct_to_creditor
            - bank_transfer
            - card
            - cash
            - other
        reference:
          type: string
          maxLength: 2000
        reversesExternalPaymentId:
          $ref: '#/components/schemas/ExternalPaymentIdValue'
        resultingOutstandingAmount:
          $ref: '#/components/schemas/Money'
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    ProblemDetails:
      type: object
      additionalProperties: false
      required:
        - type
        - title
        - status
        - detail
        - code
      if:
        properties:
          code:
            const: rate_limited
        required:
          - code
      else:
        required:
          - requestId
      properties:
        type:
          type: string
          format: uri-reference
        title:
          type: string
        status:
          type: integer
          minimum: 400
          maximum: 599
        detail:
          type: string
        code:
          type: string
          description: >-
            Stable machine-readable error code. Client software branches on this
            value; it never parses detail. The same codes appear in
            `errors[].code`, where field-level codes such as required_field,
            unknown_field and unsupported_enum point at what to correct.
          enum:
            - balance_mismatch
            - capacity_limited
            - card_number_detected
            - client_not_configured
            - client_scope_denied
            - currency_mismatch
            - effective_date_out_of_range
            - identity_mismatch
            - invalid_credentials
            - invalid_field
            - invalid_page_token
            - invalid_precondition
            - invalid_request
            - invisible_character
            - matter_closed
            - method_not_allowed
            - not_found
            - opening_balance_change_not_allowed
            - partner_writes_paused
            - payload_too_large
            - payment_observation_conflict
            - precondition_failed
            - precondition_required
            - primary_liable_party_required
            - rate_limited
            - recipient_rebind_required
            - request_timeout
            - required_field
            - source_write_conflict
            - stale_lifecycle_precondition
            - stale_lifecycle_retry
            - unavailable
            - unknown_field
            - unprocessable_entity
            - unsupported_enum
            - unsupported_media_type
            - usable_address_required
          example: client_scope_denied
        instance:
          type: string
          format: uri-reference
          description: >-
            Optional server-issued opaque occurrence URI; never contains request
            path or query values, or partner identifiers
        requestId:
          type: string
          description: >-
            Equals the `X-Request-Id` header. Present on every application
            response; absent only on a `rate_limited` response answered by the
            network edge before the request reaches the application.
        errors:
          type: array
          maxItems: 50
          description: At most 50 field-level entries, in the order found.
          items:
            type: object
            additionalProperties: false
            required:
              - pointer
              - code
            properties:
              pointer:
                type: string
              code:
                type: string
      example:
        type: https://api.casepathiq.com/problems/usable_address_required
        title: Usable address required
        status: 400
        detail: >-
          Each Party needs exactly one usable correspondence address that meets
          the letter minimum.
        code: usable_address_required
        requestId: 6f2c1b8e-3a41-4f43-9a55-6b2f0b1b7c10
        errors:
          - pointer: /parties/1/addresses
            code: usable_address_required
  responses:
    PaymentSuccess:
      description: Current immutable Payment observation
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PaymentObservationResponse'
    PaymentCreated:
      description: Payment observation created
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
        Location:
          schema:
            type: string
            format: uri-reference
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PaymentObservationResponse'
    BadRequest:
      description: Validation, schema, enum, money or letter-minimum failure
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    Unauthorized:
      description: >-
        Missing, malformed, expired, revoked or unknown partner key, an invalid
        edge identity, or a network address outside the key's allowed ranges
        (invalid_credentials). The same neutral 401 is returned for every cause.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    Forbidden:
      description: >-
        The key cannot act for this Client code (client_scope_denied). Unknown,
        ungranted and key-restricted Client codes share this response.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    NotFound:
      description: No such Matter or Payment observation in this scope (neutral)
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    RequestTimeout:
      description: >-
        The request body was not received within 10 seconds (request_timeout).
        Nothing was changed.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    Conflict:
      description: Balance, payment, lifecycle or retained Source conflict
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    PayloadTooLarge:
      description: The request body exceeds 256 KiB (payload_too_large).
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    UnsupportedMediaType:
      description: >-
        The Content-Type is not accepted (unsupported_media_type). Use
        `application/json`, or `application/merge-patch+json` for PATCH.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    TooManyRequests:
      description: >-
        Per-key rate limit (rate_limited), per-Matter daily write cap or pilot
        capacity limit (capacity_limited). Wait for Retry-After before retrying.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    ServiceUnavailable:
      description: >-
        Transient or fenced failure (unavailable), or Partner API writes paused
        by the platform (partner_writes_paused; reads still work). Retry
        unchanged content after Retry-After.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
    Problem:
      description: RFC 9457 Problem Details error
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Cache-Control:
          $ref: '#/components/headers/CacheControl'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
  headers:
    RequestId:
      description: CasePath IQ-generated support correlation identifier
      schema:
        type: string
        example: req_01JEXAMPLE
    CacheControl:
      description: Sensitive responses are not cacheable
      schema:
        type: string
        const: no-store
    RetryAfter:
      description: Seconds to wait before retrying this request
      schema:
        type: integer
        minimum: 1
      example: 30
  securitySchemes:
    PartnerKey:
      type: http
      scheme: bearer
      bearerFormat: CasePath IQ partner key
      description: >-
        Environment-specific Integration key. Never paste a live key into
        documentation tooling.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.