---
title: "Finalize transaction"
method: PATCH
path: "/api/transactions/{transactionId}"
tags: ["Transactions"]
---

# Finalize transaction

`PATCH /api/transactions/{transactionId}`

## Request

- Base URL: `https://api.payware.eu`
- URL: `https://api.payware.eu/api/transactions/{transactionId}`
- Auth: HTTP bearer

Updates transaction status to finalize or cancel the transaction

## Path parameters

- `transactionId` string, required

## Request body

- TransactionStatusUpdateRequest
  - `status` string
  - `statusMessage` string
  - `currency` string
  - `amount` string
  - `fee` string

## Response `200`

Transaction finalized successfully. Repeating a finalize already applied, by the same bank with the same status, status message and amount, returns the stored result without applying it again or sending a second callback.

- TransactionDTO
  - `transactionId` string
  - `initiatingId` string
  - `transactionType` string
  - `initiatedBy` string
  - `payerBIC` string
  - `payerFriendlyName` string
  - `payerAccount` string
  - `payeeBIC` string
  - `payeeFriendlyName` string
  - `payeeAccount` string
  - `currency` string
  - `amount` string: Transaction amount, as a decimal string at the smallest unit `currency` can be paid in. That is not always two decimal places - it follows the currency. Parse it as a decimal, never as a fixed-width string, and do not compare amounts as strings.
  - `fee` string: The fee payware calculated and will enforce at finalize, as a decimal string at the smallest unit `currency` can be paid in - the amount the institution can actually withhold. Echo it back UNCHANGED at finalize: do not recompute it from feeFixed/feeRate and do not re-round it, or the call is rejected with ERR_FEE_MISMATCH. Omitted (not zero) when the transaction carries no recorded fee; absence means unknown, not free.
  - `reasonL1` string
  - `reasonL2` string
  - `created` integer
  - `finalized` integer: Finalization moment, UNIX epoch milliseconds. Omitted for EXPIRED transactions, which are closed by the platform's expiry sweep and carry no finalization moment.
  - `timeToLive` integer
  - `status` 'ACTIVE' | 'CONFIRMED' | 'CANCELLED' | 'DECLINED' | 'FAILED' | 'EXPIRED': Transaction status. ACTIVE = awaiting payment (initial state, only status returned by GET). CONFIRMED = payment completed successfully. CANCELLED = cancelled before completion (requires statusMessage). DECLINED = payment declined by financial institution (requires statusMessage). FAILED = processing failed (requires statusMessage). EXPIRED = TTL exceeded before payment.
  - `statusMessage` string
  - `paymentMethod` 'A2A' | 'CARD_FUNDED' | 'BNPL' | 'INSTANT_CREDIT': Payment method chosen by customer. Used by banks when processing transactions. A2A = direct transfer (lower fee, no rewards). CARD_FUNDED = card-linked account (higher fee, rewards eligible). BNPL = buy now pay later (installments). INSTANT_CREDIT = credit line approved at purchase.
  - `passbackParams` string: Opaque string supplied by the initiating partner at creation and passed back unmodified on every response and callback for this transaction. payware never interprets it.
  - `payeeAmount` string
  - `payeeCurrencyCode` string
  - `payerAmount` string
  - `payerCurrencyCode` string
  - `feeFixed` string: Fixed fee component of the fee configuration stored on this transaction, in the transaction currency, at full stored precision. INFORMATIONAL - for reconciliation and for showing the merchant how the fee arose. Do not compute the fee from it: MAX(feeFixed, amount * feeRate) is the unrounded intermediate, and submitting that value at finalize is rejected with ERR_FEE_MISMATCH. The value to submit is `fee`.
  - `feeRate` string: Variable rate of the fee configuration stored on this transaction, at full stored precision - up to six decimal places, e.g. "0.001250" = 0.125%. Do not assume four: rounding a negotiated rate to four places produces a different fee from the one payware enforces. INFORMATIONAL, same as feeFixed.
  - `product` ProductPresentationDTO: Product presentation block, present only for product-originated transactions.
    - `productId` string: Product reference identifier.
    - `type` string: Product type: ITEM or SERVICE.
    - `name` string: Structured product name.
    - `shortDescription` string: Short product description.
    - `longDescription` string: Long product description.
    - `imageUrl` string: Product image URL to display to the payer. Availability depends on merchant plan. Permitted image types: PNG, JPEG, WebP, GIF.
    - `imageDigest` string: SHA-256 hex digest of the image at imageUrl, pinned by payware. The institution must verify the fetched bytes against this digest before rendering and fall back to a neutral placeholder on mismatch.
    - `imageContentType` string: Content type of the image as observed by payware on fetch (e.g. image/png).
    - `imageBytes` integer: Byte length of the image as observed by payware on fetch.
    - `termsUrl` string: URL of the terms and conditions applying to the purchase. Availability depends on merchant plan.
    - `termsText` string: Inline terms and conditions text applying to the purchase.
    - `regularPrice` string: Product regular (pre-discount) list price, in the Transaction currency. Present only when it is higher than the Transaction amount, i.e. when there is a genuine saving to display; omitted when the amount equals or exceeds the regular price (a price schedule may set the sale price at or above the regular price). The Transaction amount and currency are authoritative and are not repeated here. For display only.
    - `shippable` boolean: Whether the product requires a delivery address.
    - `shopName` string: Merchant outlet (shop) name.
    - `quickPay` boolean: When true, the client application may skip the product detail screen and proceed directly to payment confirmation, provided the minimum transaction information and access to the terms in full remain available to the payer. Intended for high-speed, fixed-price scenarios such as transit gates, event entry, or toll booths. Product preview responses only.
  - `deliveryAddress` DeliveryAddressDTO
    - `country` string
    - `fullName` string
    - `streetAddressLine1` string
    - `streetAddressLine2` string
    - `city` string
    - `region` string
    - `zipCode` string
    - `phoneNumber` string
    - `email` string
  - `recognition` RecognitionDTO: Confidence of a soundbite recognition. Present on answers to soundbite fingerprints; a transaction preview without it is a certain answer.
    - `confidence` 'CERTAIN' | 'PROBABLE': CERTAIN: the ad was recognised. PROBABLE: the ad was probably recognised; ask the shopper to confirm it ("Is this the ad?") before continuing, and report the answer to POST /api/transactions/recognitions/{id}.
    - `id` string: Identifier of this recognition answer (UUID), used to report the shopper's confirmation.

## Other responses

- `400`: Invalid transaction ID or status. Includes ERR_FEE_MISMATCH, which is what a caller gets for recomputing the fee instead of echoing back the `fee` from the process response - the comparison is for exact equality.
- `401`: Unauthenticated - missing, malformed or expired credentials
- `403`: Forbidden - the caller is authenticated but not permitted (plan or capability gate, KYC state, or tenant scope)
- `404`: Transaction not found (ERR_MISSING_TRANSACTION), or it has expired (ERR_TRANSACTION_EXPIRED)
- `409`: ERR_ALREADY_PROCESSED - the transaction has already been finalized. The request was well formed; this is the answer to a duplicate submission, not to a bad one.
- `429`: Too many requests - the caller exceeded its per-partner rate limit. Carries errorCode ERR_RATE_LIMIT_EXCEEDED and a Retry-After header, in seconds. The request was not processed, so the identical request is safe to retry once the window has passed.
- `500`: Internal server error
- `503`: The fee could not be recomputed for validation: no fee configuration exists for the transaction's currency (ERR_FEE_CONFIGURATION_UNAVAILABLE), or no exchange rate was available (ERR_MISSING_EXCHANGE_RATE). payware-side configuration gaps - the request was not applied, so retrying later is correct.

---

[API](https://skmtc.dev/payware/apis/payware-api.md) · [All operations](https://skmtc.dev/payware/apis/payware-api/llms.txt) · [OpenAPI document](https://skmtc.dev/payware/apis/payware-api/revisions/7b3352ca947b?raw)
