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

# Get payment timeline

> Read the step-by-step settlement record for one payment. Use it for reconciliation and support, not to decide what to do next.

<Note>
  The timeline is for reconciliation and support — a step-by-step record of what happened to a payment. To decide what to do **next** with a payment, read `status` from [payment status](/api-reference/payment-gateway/get-payment-status) instead. See [Reconciliation](/get-started/support/reconciliation).
</Note>


## OpenAPI

````yaml GET /v1/payments/{paymentId}/timeline
openapi: 3.0.3
info:
  title: Atum Payment Gateway API
  description: >
    The Atum Payment Gateway API enables secure, cross-chain payments with
    built-in escrow protection 

    and settlement verification. This API facilitates decentralized payment
    routing across multiple blockchain 

    networks while ensuring transaction atomicity and settlement guarantees.


    ## Supported Blockchains

    - Ethereum and EVM-compatible chains (Arbitrum, Optimism, Base, etc.)

    - Solana

    - Tron


    ## Authentication


    No API key, token, or authorization header is required on any operation.

    A payment carries its own authorization: the `sender_auth` signed messages
    prove

    control of the funding account, and are verified on every submission.
  version: 1.0.0
servers:
  - url: https://payment-gw.production-mainnet.atum.xyz
    description: Mainnet
  - url: https://payment-gw.production-testnet.atum.xyz
    description: Testnet
security: []
tags:
  - name: Payments
    description: >-
      Submit a payment and follow it to settlement, by payment id, by your own
      request id, or step by step.
  - name: Authorizations
    description: Counterparty authorization requested while a payment is being accepted.
  - name: Quote Requests
    description: >-
      The two-phase quote flow - open a quote-request batch, poll it, then award
      one quote.
  - name: Chain Defaults
    description: >-
      The per-chain corridor addresses a client needs before it can build and
      sign a payment.
  - name: Health
    description: Liveness probe for the gateway.
paths:
  /v1/payments/{paymentId}/timeline:
    get:
      tags:
        - Payments
      summary: Get step-by-step payment timeline
      description: |
        Returns the settlement timeline for a payment, including every step the
        payment has passed through, per-step durations, chain IDs, transaction
        hashes, and — if the payment has failed — a structured error describing
        where and why it failed.
      operationId: getPaymentTimeline
      parameters:
        - name: paymentId
          in: path
          required: true
          description: The ID of the payment to query
          schema:
            type: string
      responses:
        '200':
          description: Timeline retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaymentTimelineResponse'
        '404':
          description: Payment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    PaymentTimelineResponse:
      type: object
      description: |
        Step-by-step view of a payment's settlement lifecycle. Includes a route
        summary, a list of steps with timings, and if the payment failed, a
        structured error describing where and why.
      required:
        - payment_id
        - status
        - created_at
        - updated_at
        - steps
      properties:
        payment_id:
          type: string
          example: '0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f'
        status:
          $ref: '#/components/schemas/PaymentStatus'
        transactions:
          $ref: '#/components/schemas/PaymentTransactions'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        total_duration_ms:
          type: integer
          format: int64
          description: >-
            Total time from first step to last completed step (only set for
            terminal states)
        summary:
          $ref: '#/components/schemas/PaymentSummary'
        error:
          $ref: '#/components/schemas/PaymentFailure'
        steps:
          type: array
          items:
            $ref: '#/components/schemas/TimelineStep'
    ErrorResponse:
      type: object
      description: >-
        Safe, outward-facing error. Derived from an internal error through the
        shared error catalog. The public code identifies the category and the
        message is a curated, safe description.


        A panic is caught by shared middleware that responds `{"error":
        "Internal server error occurred"}` instead, so a 500 is not guaranteed
        to carry this shape.
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: Public, machine-readable error category in SCREAMING_SNAKE_CASE.
          pattern: ^[A-Z][A-Z0-9_]*$
          example: INVALID_SOURCE_ASSET
        message:
          type: string
          description: Curated, safe, human-readable message.
          maxLength: 500
          example: The source asset identifier is not a valid CAIP-19 asset.
        request_id:
          type: string
          description: >-
            Correlation id to quote to support to locate the internal error
            record.
          example: req_123456789
        payment_id:
          type: string
          description: >-
            The payment this error was raised against. Absent when the error is
            not about a specific payment.
          example: '0xc7108e200d11580e7e75185991084b42a535af588ba8267cd0d1e7df089e5c9c'
        docs_url:
          type: string
          format: uri
          description: Link to the documentation page for this public code.
        domain:
          type: string
          description: Originating service domain.
          example: PAYMENT_GATEWAY
        retry_classification:
          type: string
          description: >-
            What the caller should do next. Absent means the condition has not
            been classified, which is not the same as safe to retry.

            Re-sending the same `request_id` is an idempotent replay and always
            safe. This value is about submitting a new one, which starts a new
            operation. See https://docs.atum.xyz/errors for the value set.
          example: RECONCILE_THEN_DECIDE
        request_id_reusable:
          type: boolean
          description: >-
            Whether the caller may re-send this same request_id. True means no
            payment was created for it, so the id is still free. False means a
            payment exists for it, so the id is spent and re-sending only
            replays this outcome. Absent means undetermined, which a caller
            should read as false. Separate from retry_classification, which
            answers what the caller must change rather than whether the id
            survived.
          example: false
    PaymentStatus:
      type: string
      description: >
        Where your payment is in its lifecycle. One payment reads the same
        however you ask

        about it.


        - `pending`: accepted and in progress. Nothing has reached the recipient
        yet.

        - `finalizing`: the transaction paying your recipient is on chain and is
        accruing
          the confirmations its chain requires. NOT FINAL, see below.
        - `completed`: delivered, with the required confirmations behind it.

        - `failed`: did not complete. Any funds held in escrow are returned, and
        `error`
          describes what went wrong.

        `completed` and `failed` are final and will not change afterwards.
        `pending` and

        `finalizing` will.


        **Do not treat `finalizing` as delivered.** It says the payment has been
        made on

        chain but is not yet irreversible, much as a card authorization is not
        yet a

        settlement. It normally becomes `completed`, and it can still become
        `failed` if

        the transaction never reaches the confirmation depth its chain requires.
        Acting on

        `finalizing` — releasing goods, crediting an account — means accepting
        that risk

        deliberately, at whatever threshold suits you rather than the one we
        wait for.


        `finalizing` is about paying the recipient. While your own funds are
        still being

        committed on the source chain the payment is `pending`, because nothing
        has reached

        the recipient yet.
      enum:
        - pending
        - finalizing
        - completed
        - failed
      example: pending
    PaymentTransactions:
      type: object
      description: >
        The transactions a payment has produced, one entry per stage, added as
        each becomes

        known. A stage absent here has produced no transaction yet.


        These are the two movements that decide whether your payment happened:
        your funds

        being committed, and your recipient being paid. Present on every
        outcome, so a

        payment that did not complete can still be traced on chain.

        `fulfillment_confirmation` is not a substitute: it is written only once
        a payment

        completes, and describes the finished delivery rather than progress
        towards it.


        Where a stage is attempted more than once, the entry describes the
        attempt that

        counts — the one that succeeded, or the last one if none did.
      properties:
        deposit:
          allOf:
            - $ref: '#/components/schemas/PaymentTransaction'
          description: Committing your funds on the source chain.
        fulfillment:
          allOf:
            - $ref: '#/components/schemas/PaymentTransaction'
          description: Paying your recipient on the destination chain.
    PaymentSummary:
      type: object
      description: Top-level context about the payment (parties, assets, amounts)
      properties:
        source_asset:
          type: string
          description: CAIP-19 identifier of the source asset
          example: eip155:1/erc20:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
        source_account:
          type: string
          example: '0x742D35cC6634c0532925a3b844Bc9e7595F41360'
        dest_asset:
          type: string
          example: eip155:42161/erc20:0xaf88d065e77c8cC2239327C5EDb3A432268e5831
        dest_account:
          type: string
          example: '0x892BB2e4F6b14a2B5b82Ba8d33E5925D42D4431F'
        fulfillment_amount:
          type: string
          description: Raw fulfillment amount in smallest token units
          example: '1000000'
        display_amount:
          type: string
          description: >
            Human-readable formatted amount with symbol, e.g. "1.00 USDC".

            Only set when the source asset's decimals are known via the token
            registry.
          example: 1.00 USDC
        max_source_amount:
          type: string
          description: Raw max source amount in smallest token units
          example: '1005000'
        request_id:
          type: string
          example: req_123456789
    PaymentFailure:
      type: object
      description: >
        Why a payment failed. Present only when `status` is `failed`, and
        identical

        however you ask about the payment.


        `code` is the stable, machine-readable identity of the failure — branch
        on it

        rather than on `message`, which is written for a person and may be
        reworded.

        `docs_url` points at the page describing that code.
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: |
            Public error category in SCREAMING_SNAKE_CASE. Common codes:
            - `SETTLEMENT_FAILED`: the settlement could not be completed
            - `NO_QUOTES_RECEIVED`: no quotes arrived within the auction window
            - `INTERNAL_ERROR`: an unexpected error occurred
          example: SETTLEMENT_FAILED
        message:
          type: string
          description: >
            Human-readable description of the failure, for a person reading it.
            Do not

            branch on this text.
          example: No quotes received within the auction window
        domain:
          type: string
          description: |
            Which part of the system reported the failure.
          enum:
            - PAYMENT_GATEWAY
            - SETTLER_GATEWAY
            - SETTLER_AGENT
            - WALLET_ORCHESTRATION
            - VERIFICATION_SERVICE
            - BLOCKCHAIN
            - EXTERNAL_SERVICE
          example: PAYMENT_GATEWAY
        docs_url:
          type: string
          format: uri
          description: Link to the documentation page for this public code.
        retry_classification:
          type: string
          description: >-
            What the caller should do next. Absent means the condition has not
            been classified, which is not the same as safe to retry.

            Re-sending the same `request_id` is an idempotent replay and always
            safe. This value is about submitting a new one, which starts a new
            payment. See https://docs.atum.xyz/errors for the value set.
          example: RECONCILE_THEN_DECIDE
        request_id_reusable:
          type: boolean
          description: >-
            Whether the caller may re-send the `request_id` this payment was
            created under. On this shape it is almost always false, because a
            payment exists by definition, but it is carried rather than assumed
            so a caller reads the same field here as on a synchronous error.
            Absent means undetermined, which a caller should read as false.
          example: false
        blockchain_context:
          $ref: '#/components/schemas/PaymentBlockchainContext'
    TimelineStep:
      type: object
      required:
        - name
        - label
        - status
      properties:
        name:
          type: string
          description: Internal name of the step (matches settlement event type)
          example: BID_AWARDED
        label:
          type: string
          description: Human-readable label
          example: Best Bid Selected
        status:
          type: string
          enum:
            - completed
            - in_progress
            - pending
            - failed
            - skipped
          description: |
            Current status of this step:
            - `completed`: Step finished successfully
            - `in_progress`: Step currently executing
            - `pending`: Step hasn't started yet
            - `failed`: Step errored out
            - `skipped`: Step will never execute because an earlier step failed
        timestamp:
          type: string
          format: date-time
          description: When the step completed (if it has)
        duration_ms:
          type: integer
          format: int64
          description: Time this step took, measured from the previous step
        chain_id:
          type: string
          description: CAIP-2 chain this step happened on (if on-chain)
          example: eip155:1
        transaction_hash:
          type: string
          description: Transaction hash associated with this step (if on-chain)
        details:
          type: object
          description: Additional step-specific data (e.g. block_number, settler, reason)
          additionalProperties: true
    PaymentTransaction:
      type: object
      description: >
        One on-chain transaction belonging to a payment: which chain, which
        transaction, and

        which block it landed in.


        Whether the payment has actually happened is answered by `status`, not
        here. Read this

        to look the transaction up on chain and to verify it yourself.
      required:
        - transaction_hash
        - chain_id
      properties:
        transaction_hash:
          type: string
          description: >
            The transaction's hash on its chain. Hex hashes carry the `0x`
            prefix, including on

            Tron, whose own tooling omits it.
          pattern: ^(0x[a-fA-F0-9]{64}|[1-9A-HJ-NP-Za-km-z]{32,88})$
          example: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
        chain_id:
          type: string
          description: CAIP-2 identifier of the chain the transaction is on.
          pattern: ^[a-z0-9]+:[a-zA-Z0-9_-]+$
          example: eip155:42161
        block_number:
          type: integer
          description: >
            The block the transaction landed in. Absent until it has been mined.


            Provisional while `status` is `finalizing`: on a chain that settles
            against another,

            a reorganization there can move the transaction to a different
            block. Settled once

            `status` is `completed` — keep it as a final record only from then.
          example: 61234567
    PaymentBlockchainContext:
      type: object
      description: >-
        Where on chain a failed payment failed. Present only when the failure
        happened

        on chain — an escrow revert, or a fulfillment that could not be
        delivered — so a

        payment that failed before any transaction was sent carries no context
        here.
      properties:
        chain_id:
          type: string
          description: CAIP-2 chain identifier
          pattern: ^[a-z0-9]+:[a-zA-Z0-9_-]+$
        transaction_hash:
          type: string
          description: Failed transaction hash
          pattern: ^(0x[a-fA-F0-9]{64}|[1-9A-HJ-NP-Za-km-z]{32,88})$
        block_number:
          type: integer
          description: Block number where error occurred
        contract_address:
          type: string
          description: Contract that caused the error
          pattern: ^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44})$
        revert_reason:
          type: string
          description: Smart contract revert reason
        gas_used:
          type: string
          description: Gas consumed before failure
        estimated_gas_needed:
          type: string
          description: Estimated gas needed for success

````