---
title: "Update payment"
method: PATCH
path: "/v1/payments/{paymentId}"
tags: ["Payments"]
---

# Update payment

`PATCH /v1/payments/{paymentId}`

## Request

- Base URL: `https://api.tesser.xyz`
- URL: `https://api.tesser.xyz/v1/payments/{paymentId}`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/tesser/apis/tesser-api/docs/v1/payments/:paymentId/patch.ts> (a function with typed inputs; its response is checked against the schema)

Update a payment with accounts.

## Path parameters

- `paymentId` string, required

## Request body

- UpdatePaymentRequest
  - `organization_reference_id` string: Optional external reference ID for tracking.
  - `payment_info` PaymentInfo: Optional caller intent about why a payment is being sent. Both fields optional.
    - `payment_description_wire` string: Free-text description forwarded to the payout provider (max 140 chars); appears on the beneficiary's bank statement.
    - `payment_reason_code` string: Short code classifying the payment's purpose. Stored by Tesser, not forwarded to the provider.
  - `funding_account_id` string, required: ID of the account that ultimately funds the payment, used to identify the originator for Travel Rule purposes. Must belong to a counterparty or tenant; a workspace-owned account is rejected with `payments-3099`.
  - `desired` UpdatePaymentDesiredOverlay, required: Account-only update to the payment's desired overlay (two-step PATCH flow).
    - `from` UpdatePaymentDesiredFromLeg, required: Source side of the payment (account-only update).
      - `account_id` string, required: Source account ID.
    - `to` UpdatePaymentDesiredToLeg, required: Destination side of the payment (account-only update).
      - `account_id` string, required: Destination account ID.

## Response `200`

Payment updated successfully

- PaymentResponse
  - `data` Payment, required
    - `id` string, required: Unique payment identifier
    - `workspace_id` string, required: Workspace ID the payment belongs to
    - `organization_reference_id` string, nullable: External reference ID for tracking.
    - `payment_info` PaymentInfo: Optional caller intent about why a payment is being sent. Both fields optional.
      - `payment_description_wire` string: Free-text description forwarded to the payout provider (max 140 chars); appears on the beneficiary's bank statement.
      - `payment_reason_code` string: Short code classifying the payment's purpose. Stored by Tesser, not forwarded to the provider.
    - `direction` 'inbound' | 'outbound' | 'rebalance', required: Payment direction.
    - `funding_account_id` string, nullable, required: Funding account ID. Payment-only field. Top-level (not part of any overlay).
    - `desired` PaymentDesiredOverlay, required: Caller's stated intent at creation. Frozen except by the two-step PATCH flow which fills account IDs.
      - `from` PaymentDesiredFromLegResponse, required: Source side.
        - `account_id` string, nullable, required: Account ID.
        - `amount` string, nullable, required: Amount.
        - `currency` string, nullable, required: Currency code.
        - `network` string, nullable, required: Blockchain network.
      - `to` PaymentDesiredToLegResponse, required: Destination side.
        - `account_id` string, nullable, required: Account ID.
        - `amount` string, nullable, required: Amount.
        - `currency` string, nullable, required: Currency code.
        - `network` string, nullable, required: Blockchain network.
    - `estimated` PaymentEstimatedOverlay, required: Tesser's projection for how the payment will proceed.
      - `from` PaymentEstimatedFromLeg, required: Source side.
        - `account_id` string, nullable, required: Account ID.
        - `amount` string, nullable, required: Amount.
        - `currency` string, nullable, required: Currency code.
        - `network` string, nullable, required: Blockchain network.
      - `to` PaymentEstimatedToLeg, required: Destination side.
        - `account_id` string, nullable, required: Account ID.
        - `amount` string, nullable, required: Amount.
        - `currency` string, nullable, required: Currency code.
        - `network` string, nullable, required: Blockchain network.
    - `actual` PaymentActualOverlay, required: What actually settled. Populated once at least one step has `status: completed`.
      - `from` PaymentActualFromLeg, required: Source side.
        - `account_id` string, nullable, required: Account ID.
        - `amount` string, nullable, required: Amount.
        - `currency` string, nullable, required: Currency code.
        - `network` string, nullable, required: Blockchain network.
      - `to` PaymentActualToLeg, required: Destination side.
        - `account_id` string, nullable, required: Account ID.
        - `amount` string, nullable, required: Amount.
        - `currency` string, nullable, required: Currency code.
        - `network` string, nullable, required: Blockchain network.
    - `risk_status` 'unchecked' | 'awaiting_decision' | 'automatically_approved' | 'manually_approved' | 'automatically_rejected' | 'manually_rejected' | 'null', nullable, required: Risk assessment status. Cross-ramp payments are not risk-screened: `null` when no status is stored, otherwise the stored status.
    - `risk_status_reasons` RiskStatusReason[], required: Reasons `risk_status` was assigned to the specific outcome (`automatically_approved`, `awaiting_decision`, `automatically_rejected`).
      - `risk_status_reason_type` 'ENTITY' | 'ACCOUNT' | 'OWNERSHIP' | 'COUNTERPARTY' | 'INDIRECT' | 'BEHAVIORAL' | 'ERROR', required: Type of risk identified for the screened wallet or wallets it interacted with. `OWNERSHIP`: risk from the screened wallet's own activity. `COUNTERPARTY`: a wallet the screened wallet directly interacted with. `INDIRECT`: wallets the screened wallet had indirect exposure to (two or more hops away). `BEHAVIORAL`: the screened wallet's behavior demonstrates a pattern of money laundering or funds obfuscation. `ENTITY`: risk from the screened wallet's attributed entity, including allowlist and blocklist matches. `ACCOUNT`: the screened wallet address itself matched your allowlist; the reason points at the account holding it. `ERROR`: wallet screening could not be completed.
      - `risk_status_reason_category` string, required: The specific risk category within the type. For `risk_status_reason_type` = `OWNERSHIP`, `COUNTERPARTY`, or `INDIRECT`: one of the [supported risk categories](/overviews/wallet-screening-risk-categories#supported-risk-categories). For `BEHAVIORAL`: one of the [behavioral signatures](/overviews/wallet-screening-risk-categories#behavioral-signatures). For `ENTITY`: one of the supported risk categories when `risk_status_reason_severity` is `Low`, `Medium`, `High`, or `Severe`; the participant role (`ORIGINATOR`, `ORIGINATOR_VASP`, `BENEFICIARY`, `BENEFICIARY_VASP`, `CUSTODY_SERVICE`, or `INTERMEDIARY_VASP`) when `risk_status_reason_severity` is `ALLOWLISTED` or `BLOCKLISTED`. For `ACCOUNT`: the participant role of the screened wallet — `BENEFICIARY` on an outbound payment, `ORIGINATOR` on an inbound one. For `ERROR`: `SCREENING_FAILED` when wallet screening could not be completed, or `Token Contract` when the counterparty is a token contract.
      - `risk_status_reason_participant_id` string, nullable: Links this reason to the corresponding `participants[].resource.id`. Populated on `ENTITY` reasons, on the token-contract `ERROR` reason, and on `ACCOUNT` reasons (the account holding the allowlisted address); otherwise null.
      - `risk_status_reason_message` string, required: Plain-English description of the risk category.
      - `risk_status_reason_severity` 'Low' | 'Medium' | 'High' | 'Severe' | 'ALLOWLISTED' | 'BLOCKLISTED', required: Severity of the signal: `Low`, `Medium`, `High`, or `Severe`. For an `ENTITY` reason recording an allowlist or blocklist match: `ALLOWLISTED` or `BLOCKLISTED`.
      - `risk_status_reason_significance` 'DECISIVE' | 'NON_DECISIVE' | 'SUPERSEDED_BY_ALLOWLIST' | 'SUPERSEDED_BY_BLOCKLIST', nullable: How the reason figured in the `risk_status` outcome. `DECISIVE`: drove the outcome. `NON_DECISIVE`: exceeded a threshold in your risk policy but did not drive the outcome (a more severe reason was identified). `SUPERSEDED_BY_ALLOWLIST` / `SUPERSEDED_BY_BLOCKLIST`: would have been decisive but for an allowlist or blocklist match. Null when not applicable.
      - `volume_usd_percent` string, nullable: Observed share of the wallet's volume for this risk indicator, as a percentage. `OWNERSHIP`, `COUNTERPARTY`, and `INDIRECT` reasons only; otherwise null.
      - `volume_usd_percent_threshold` string, nullable: Configured percentage-of-volume threshold for this risk indicator, if set; otherwise null.
      - `volume_usd_amount` string, nullable: Observed USD volume for this risk indicator. `OWNERSHIP`, `COUNTERPARTY`, `INDIRECT`, and `BEHAVIORAL` reasons only; otherwise null.
      - `volume_usd_amount_threshold` string, nullable: Configured USD-volume threshold for this risk indicator, if set; otherwise null.
      - `confidence_score` 'LOW_CONFIDENCE' | 'LOW_MODERATE_CONFIDENCE' | 'MODERATE_CONFIDENCE' | 'HIGH_MODERATE_CONFIDENCE' | 'HIGH_CONFIDENCE' | 'NEAR_CERTAINTY' | 'CERTAIN' | 'EXACT_MATCH', nullable: The observed confidence level of the entity attribution. Populated for `risk_status_reason_type` = `ENTITY` when `risk_status_reason_severity` = `ALLOWLISTED` or `BLOCKLISTED`, and for `risk_status_reason_type` = `ACCOUNT`. `null` otherwise. The wallet screening provider supplies `LOW_CONFIDENCE` through `NEAR_CERTAINTY`; `CERTAIN` is Tesser-defined and marks an identity supplied through a Travel Rule data provider rather than inferred by the wallet screening provider; `EXACT_MATCH` is Tesser-defined and marks an `ACCOUNT` reason — the screened wallet address itself is on your allowlist, so no attribution was involved.
      - `confidence_score_threshold` 'LOW_CONFIDENCE' | 'LOW_MODERATE_CONFIDENCE' | 'MODERATE_CONFIDENCE' | 'HIGH_MODERATE_CONFIDENCE' | 'HIGH_CONFIDENCE' | 'NEAR_CERTAINTY' | 'CERTAIN', nullable: The confidence level the entity attribution must exceed in order for an entity to be eligible for allowlisting or blocklisting. Populated only for `risk_status_reason_type` = `ENTITY` when `risk_status_reason_severity` = `ALLOWLISTED` or `BLOCKLISTED`. `null` otherwise, including on an `ACCOUNT` reason: an address match has no confidence bar.
    - `provider_metadata` object[], required: Provider-defined responses for the payment, one entry per provider, passed through for analytics and audit. Wallet screening data can reference chains other than the payment network; use the payment's estimated or actual network fields for routing and risk_status, risk_status_reasons, and participants for Tesser's normalized screening outcome.
      - `provider_metadata_type` 'WALLET_RISK_SCREENING' | 'TRAVEL_RULE': What the payload is.
      - `provider_metadata_key` 'TRM_LABS' | 'NOTABENE': The provider that produced it: `TRM_LABS` (wallet screening) or `NOTABENE` (Travel Rule data).
      - `provider_metadata_data` object: The raw provider payload: the wallet screening provider's response (provider internal URL fields removed) or the Notabene transfer record. Wallet screening covers all supported chains on which an address exists, so provider-defined fields such as entities[].entity can reference a chain other than the payment network.
    - `participants` object[], required: Participants Tesser identified in the flow of funds, with the record each was reconciled to.
      - `role` 'ORIGINATOR' | 'ORIGINATOR_VASP' | 'BENEFICIARY' | 'BENEFICIARY_VASP' | 'CUSTODY_SERVICE' | 'INTERMEDIARY_VASP' | 'CONTRACT': The participant's role in the flow of funds.
      - `resource` object: The record the participant was reconciled to and the reconciliation outcome.
        - `resource_type` 'COUNTERPARTY' | 'TENANT' | 'WORKSPACE' | 'ACCOUNT': The kind of record the participant was reconciled to: `COUNTERPARTY` (most common); `TENANT` (the sending or receiving wallet belongs to one of your tenants directly); `WORKSPACE` (one of your organization's own wallets); or `ACCOUNT` (the account holding a wallet address on your allowlist — see `risk_status_reason_type` = `ACCOUNT`).
        - `id` string, nullable: Identifier of the record the participant was reconciled to — a counterparty, tenant, workspace, or account ID, per `resource_type`.
        - `name_match_score` string, nullable: The name-match score, 0–100. Null where no name matching applied.
        - `name_match_threshold` string, nullable: The lowest score that counts as a match; the comparison is inclusive, so a score equal to the threshold matches. Null where no name matching applied.
        - `name_match_comparison_id` string, nullable: ID of the record whose name most closely matched the supplied name — the record the score was computed against. Null where no name matching applied.
        - `resolution` 'EXACT_MATCH' | 'PARTIAL_MATCH' | 'DID_NOT_MATCH' | 'COUNTERPARTY_CREATED' | 'USER_SUPPLIED_ID': The reconciliation outcome.
    - `risk_reviewed_by` string, nullable: User ID who reviewed the risk.
    - `risk_reviewed_at` string, date-time, nullable: Timestamp when risk was reviewed.
    - `risk_review_reason` string, nullable: Reason the reviewer gave when approving or rejecting the payment. Null when none was given or the payment was not manually reviewed.
    - `balance_status` 'unreserved' | 'awaiting_funds' | 'reserved', nullable, required: Balance reservation status.
    - `balance_reserved_at` string, date-time, nullable, required: Timestamp when balance was reserved.
    - `steps` PaymentStep[], required: Payment execution steps.
      - `id` string, required: Unique step identifier
      - `payment_id` string, required: ID of the parent payment
      - `step_sequence` integer, required: Order of this step in the payment flow (1-based)
      - `step_type` 'transfer' | 'swap', required: Type of step
      - `estimated` PaymentStepEstimatedOverlay, required: Planned values for this step.
        - `from` PaymentStepEstimatedFromLeg, required: Source side.
          - `account_id` string, nullable, required: Account ID.
          - `amount` string, nullable, required: Amount.
          - `currency` string, nullable, required: Currency code.
          - `network` string, nullable, required: Blockchain network.
        - `to` PaymentStepEstimatedToLeg, required: Destination side.
          - `account_id` string, nullable, required: Account ID.
          - `amount` string, nullable, required: Amount.
          - `currency` string, nullable, required: Currency code.
          - `network` string, nullable, required: Blockchain network.
      - `actual` PaymentStepActualOverlay, required: Settled values once the step reaches `status: completed`. All-null until then; remains all-null on failure.
        - `from` PaymentStepActualFromLeg, required: Source side.
          - `account_id` string, nullable, required: Account ID.
          - `amount` string, nullable, required: Amount.
          - `currency` string, nullable, required: Currency code.
          - `network` string, nullable, required: Blockchain network.
        - `to` PaymentStepActualToLeg, required: Destination side.
          - `account_id` string, nullable, required: Account ID.
          - `amount` string, nullable, required: Amount.
          - `currency` string, nullable, required: Currency code.
          - `network` string, nullable, required: Blockchain network.
      - `transaction_hash` string, nullable: Blockchain transaction hash
      - `unsigned_transaction` string, nullable: Unsigned transaction bytes for client signing. Present only for Turnkey-signed steps in `signature_requested` status.
      - `fees` StepFee[], required: Fees associated with this step.
        - `fee_amount` string, required: Fee amount.
        - `fee_currency` string, required: Fee currency code.
        - `fee_type` string, required: Fee type (e.g., 'gas', 'provider', 'tesser_fee').
        - `fee_metadata` object: Additional metadata for the fee (JSON object).
      - `provider_key` 'capa' | 'circle_mint' | 'kraken' | 'openfx' | 'turnkey' | 'zuba', nullable: Provider used for this step
      - `status` 'created' | 'signature_requested' | 'signed' | 'submitted' | 'confirmed' | 'completed' | 'failed', required: Current status of this step
      - `status_reasons` StatusReason[], nullable: Reasons for the current status
        - `error_code` string, required
        - `error_message` string, required
      - `created_at` string, date-time, required: Step creation timestamp
      - `updated_at` string, date-time, required: Step last update timestamp
      - `signature_requested_at` string, date-time, nullable: Timestamp when a signature was requested for the step
      - `signed_at` string, date-time, nullable: Timestamp when the step was cryptographically signed
      - `submitted_at` string, date-time, nullable: Timestamp when step was submitted
      - `confirmed_at` string, date-time, nullable: Timestamp when step was confirmed
      - `completed_at` string, date-time, nullable: Timestamp when step completed
      - `failed_at` string, date-time, nullable: Timestamp when step failed
    - `created_at` string, required: ISO 8601 timestamp of creation.
    - `updated_at` string, required: ISO 8601 timestamp of last update.
    - `expires_at` string, date-time, nullable, required: ISO 8601 timestamp when the payment expires.

## Other responses

- `400`: Invalid request data
- `409`: The originator behind `desired.from.account_id` already has a locked cross-ramp awaiting funds (`payments-3088`). Retry once it is funded or expires.

---

[API](https://skmtc.dev/tesser/apis/tesser-api.md) - [All operations](https://skmtc.dev/tesser/apis/tesser-api/llms.txt) - [OpenAPI document](https://skmtc.dev/tesser/apis/tesser-api/revisions/14f951e986b1?raw)
