---
title: "Revert a transaction"
method: POST
path: "/v3/{ledgerName}/transactions/{transactionId}/revert"
tags: ["Transactions"]
---

# Revert a transaction

`POST /v3/{ledgerName}/transactions/{transactionId}/revert`

## Request

- Base URL: `http://localhost:9000`
- URL: `http://localhost:9000/v3/{ledgerName}/transactions/{transactionId}/revert`
- Auth: one of:
  - HTTP bearer
  - none

Reverts a transaction by creating a reverse transaction that undoes its effects. Requires `ledger:write` scope.
The body is optional; an absent or empty body uses default options. Supplied
options and metadata are decoded for both known-length and HTTP/1.1 chunked
requests. Malformed or truncated JSON, extra values, trailing non-whitespace
and options of the wrong JSON type (for example `"atEffectiveDate": "true"`
or a non-object `metadata`) return 400 before applying the revert. A JSON
`null` option uses its default. The complete body, including trailing
whitespace, counts towards the 4 MiB limit; exceeding it returns 413.

## Path parameters

- `ledgerName` string, required
- `transactionId` integer, required

## Headers

- `Formance-Bigint-As-String` string
- `Idempotency-Key` string

## Request body

- RevertTransactionRequestBody
  - `force` boolean: Force revert even if accounts don't have sufficient funds
  - `atEffectiveDate` boolean: Set the timestamp of the reverted transaction to the original transaction timestamp
  - `metadata` object: Metadata for the revert transaction (supports typed values). Cluster policy defaults allow 128 entries per entity, 256 bytes per key, 16384 bytes per value, 65536 bytes per entity, and 1048576 bytes per request. Effective ceilings are configurable through the replicated cluster policy.

## Response `201`

Transaction reverted successfully

- RevertedTransactionResponse
  - `data` RevertedTransaction, required
    - `revertedTransactionId` integer: ID of the original transaction that was reverted
    - `revertTransaction` TransactionResponse
      - `postings` PostingResponse[], required
        - `source` string, required
        - `destination` string, required
        - `amount` union, required: Unsigned amount from 0 through 2^256-1. Requests accept JSON integer tokens or canonical decimal strings independently of the response header; the server enforces the bound for both forms. Responses use numbers by default and strings with Formance-Bigint-As-String enabled, as do all response Uint256 values regardless of business meaning.
          - integer
          - string
        - `asset` string, required
        - `color` string, required: Segregation key for "color of money". The empty string means the uncolored bucket. Always present on responses (never omitted); two postings on the same (account, asset) but different colors operate on strictly isolated balances.
      - `metadata` object, required
      - `timestamp` string, date-time: Transaction timestamp (ISO 8601 format)
      - `reference` string
      - `id` integer, required: Transaction ID (assigned by the system)
      - `reverted` boolean, required: Whether this transaction has been reverted
      - `insertedAt` string, date-time: When the transaction was inserted into the ledger
      - `updatedAt` string, date-time: Last update timestamp
      - `revertedAt` string, date-time, nullable: When the transaction was reverted (null if not reverted)
      - `revertedByTransactionId` integer: ID of the transaction that reverted this one (absent when not reverted)
      - `revertsTransactionId` integer: ID of the original transaction this transaction reverts (absent when this is not a revert)
      - `postCommitVolumes` PostCommitVolumes: Post-commit volumes, keyed by account address. Each account maps to a flat array of per-(asset, color) volume tuples. The wire is a plain `{"addr": [{asset, color, input, output}]}` map — the proto `volumesByAccount` / `volumes` wrappers are flattened away by `PostCommitVolumes.MarshalJSON`. This replaces the pre-color `{"addr": {"asset": Volumes}}` map shape, which can no longer key a bucket uniquely once a color dimension exists.

## Other responses

- `400`: Bad request
- `401`: Authentication required (missing or invalid JWT token)
- `403`: Insufficient permissions (missing required scope)
- `404`: Not found
- `405`: Method not allowed
- `409`: Conflict (e.g. transaction already reverted)
- `413`: Request body exceeds the 4 MiB limit
- `429`: Resource exhausted. Write admission can reject with `WRITES_BLOCKED_DISK_FULL` while disk pressure blocks writes; `SEQUENCE_EXHAUSTED` means an authoritative identifier allocator cannot allocate another identifier and is permanent for that allocator. Inspect `errorCode` before deciding whether to retry. No retry interval is supplied, and retrying cannot resolve sequence exhaustion.
- `500`: Internal server error
- `503`: Service unavailable — the server cannot serve the request right now but an immediate retry can succeed. The `errorCode` field discriminates the cause: `NO_LEADER` (no elected Raft leader), `CACHE_HORIZON_EXCEEDED` (admission snapshot too old, retry against a fresh one), `UNAVAILABLE` (an internal forwarded stream was torn down mid-transfer), or the reason of any domain error of the unavailable kind (e.g. `INDEX_BUILDING`).

## Changes

- **2026-11-03** `f5e817eca038`: 1 info
  - api operation id `revertTransaction` removed and replaced with `v3RevertTransaction`
- **2026-10-15** `98fb67e06597`: 1 warning
  - removed the optional property `data/warnings` from the response with the `201` status
- **2026-10-09** `0ed18e459f51`: 3 breaking, 3 info
  - response property `data/revertTransaction/postCommitVolumes/additionalProperties/items/input` list-of-types was widened by adding types `integer` to media type `application/json` of response `201`
  - response property `data/revertTransaction/postCommitVolumes/additionalProperties/items/output` list-of-types was widened by adding types `integer` to media type `application/json` of response `201`
  - response property `data/revertTransaction/postings/items/amount` list-of-types was widened by adding types `string` to media type `application/json` of response `201`
  - added the new optional `header` request parameter `Formance-Bigint-As-String`
  - …2 more
- **2026-10-08** `3da23d327316`: 3 info
  - added the media type `text/plain` for the response with the status `401`
  - added the media type `text/plain` for the response with the status `403`
  - added the non-success response with the status `429`
- …earlier changes not shown

[Operation history](https://skmtc.dev/formancehq/apis/ledger-api/changes/v3/:ledgerName/transactions/:transactionId/revert/post.md)

---

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