Skip to main content
This guide compares the HTTP contracts of Midaz v3.8.6 and Midaz v4.x.x. It covers the Ledger, CRM and Fees. It describes Midaz v4.3.0. The text names the version of each behavior that starts after v4.0.0.
Move your integration to the v2 contracts by April 29, 2027. After this date, Lerian removes the v1 contracts of the Ledger.
Do not replace /v1 with /v2 everywhere in your integration. Midaz v3.x.x and Midaz v4.x.x are product versions. v1 and v2 are HTTP contract versions. Midaz v4.x.x serves v1 and v2 contracts side by side, and some v1 routes have no v2 route.

Ledger routes


Replace {organization_id}, {ledger_id} and the other identifiers in the paths with the values of your integration. Organizations, assets, segments, portfolios, account types, ledger settings and metadata indexes also have v2 routes. Keep the method and the scope of each route. Not all of them take an organization and a ledger in the path:
  • /v2/organizations and /v2/organizations/{organization_id}/ledgers take the organization only.
  • /v2/settings/metadata-indexes takes no organization and no ledger.
  • /v2/transactions/direct, /v2/transactions/hold, /v2/transactions/block and /v2/transactions/unblock take no organization and no ledger in the path.
Midaz v4.x.x serves every v1 route of the Midaz v3.x.x Ledger. The API reference marks all of them as deprecated, and Lerian removes them after April 29, 2027. Until then, they keep the v1 error format.

Organization and ledger in the transaction body


When you move a create, block or unblock request to v2, move the organization and the ledger from the path to the body. The v2 path of these routes has no {organization_id} and no {ledger_id}.
The v2 body has no top-level organizationId or ledgerId. Each item names the organization and the ledger of its own account:
This excerpt shows one item only. A complete body also has asset, amount and credits. See the example of a direct transaction. Follow these rules:
  • Send organizationId and ledgerId in every item. Both are required, and both are UUIDs.
  • All items must name the same organization and the same ledger.
  • From v4.1.0, direct and hold accept items in different ledgers when every ledger enables crossLedger.enabled. See cross-Ledger transactions.
  • block and unblock always need one organization and one ledger in all items.
The other transaction routes keep the organization and the ledger in the path: list, read, update, commit, cancel, revert and update an operation. For the full v2 body, see Transaction contract.

Exceptions


These routes need specific handling. Do not apply the tables of this guide to them. Stop using the annotation and asset rate routes by April 29, 2027. After this date, they are not available, and Midaz has no v2 route to replace them.

CRM and Fees in API v2


In Midaz v4.x.x, the Ledger serves CRM and Fees as modules. Update the base URL of CRM and Fees in your environment. Midaz v4.x.x serves the CRM and Fees routes in v2 only. It has no v1 copy of them. Each route keeps its method, unless the table says otherwise.

CRM

The v1 routes below come from CRM in Midaz v3.x.x. CRM in Midaz v3.x.x means the CRM component of Midaz v3.5.0 to v3.8.6 and the standalone CRM plugin. Midaz v4.x.x renames aliases to instruments. The last four rows apply only to the CRM component of Midaz v3.x.x. The standalone CRM plugin does not have these routes.

Fees

The v1 routes below come from the standalone Fees plugin. Midaz v3.x.x has no Fees component.

Scope and permission changes


  • Send the organization in the path. Do not send the X-Organization-Id header.
  • In Fees, send the ledger in the path. Remove ledgerId from the body of packages, estimates, billing packages and billing calculation.
  • The package and billing package lists always cover one ledger. In the plugin, ledgerId was an optional query parameter. To list the packages of a whole organization, call the list once for each ledger.
  • In CRM instruments, keep ledgerId and accountId in the body.
  • Use estimates only to simulate fees. An estimate does not record anything.
Midaz v4.x.x checks permissions in the midaz group. Grant the new permissions in Access Manager before you move traffic. Do not assume that the old grants still apply. New routes do not move your data. Plan the migration of the CRM and Fees data, relationships and identifiers as a separate task. For the history of standalone CRM, see CRM migration history. To move the fee packages of Bank Transfer, see Migrate Bank Transfer fees to Midaz.

Transaction contract


The v2 request body has these fields:
  • asset: the asset code.
  • amount: the total, as a decimal string.
  • debits and credits: arrays with one or more items each.
Each item of debits and credits has these fields: Select the intent with the route. The v2 body has no pending field:
  • Use /v2/transactions/direct to post the transaction at once.
  • Use /v2/transactions/hold to create a pending transaction. Then commit or cancel it.
When you convert an inflow or an outflow, write both sides. On the side that v1 left out, use @external/ followed by the asset code in upper case, for example @external/BRL.

Example of a direct transaction

POST /v2/transactions/direct. Replace the aliases and the UUIDs with the real values.

Fields that the v2 body does not accept

Midaz refuses a v2 body that has an unknown field, with a 400 response. Review your flow if it sends any of these v1 fields:
  • rate and remaining in an item.
  • metadata in an item. The transaction itself still accepts metadata.
  • transactionDate.
  • balanceKey in an item, on Midaz v4.0.x only. From v4.1.0, each item accepts an optional balanceKey.
Do not copy these fields into the v2 body. Find a supported alternative first.

Responses and errors


Transaction responses

  • source and destination become debit and credit, in the singular.
  • The transaction no longer has route and chartOfAccountsGroupName.
  • The operations inside a transaction no longer have route and chartOfAccounts. They keep routeId, routeCode and routeDescription.
  • The responses of an operation that you read alone do not change.
  • From v4.1.0, a direct or hold that spans ledgers returns a group with groupId and transactions[]. Commit, cancel and revert can also return a group.
The v2 transaction also has fields that v1 does not have. See GET /v2/organizations/{organization_id}/ledgers/{ledger_id}/transactions/{transaction_id} in the API reference.

Errors

The v2 routes return errors in the RFC 9457 format, with Content-Type: application/problem+json. Read these members:
  • type, title, status and detail.
  • code: the Midaz error code. The same error has the same code in v1 and v2.
  • errors[]: the field errors, when the request has them.
For example, a POST /v2/transactions/direct request that still sends the v1 field transactionDate gets this response:
The type URI ends with the error code. Its /v1 segment is the version of the error catalog, not the version of the API. Do not rely on message or fields. They belong to the v1 error format. In v2, only 413 and 504 responses also carry a top-level message. See Error handling and the Midaz error list.

Accounts and rules in API v2


Account routes

The v2 account routes let you do these tasks:
  • Read an account by alias and by external code.
  • Update and delete an account.
  • Count the accounts with HEAD.
Send holderId when you create an account. Read holderId and holderCheckSkipped in the v2 account responses.

Holder rules

  • When accounting.requireHolder is on, each account needs a holder of the organization. Without a holder, Midaz does not create the account.
  • To skip that check, send skip.holder. Midaz accepts it only when overrides.allowHolderSkip is on. Otherwise, Midaz refuses the request with 422 and error 0490.
  • When accounting.requireHolder is off and you send no holder, a non-external account gets the holder of its organization. An external account gets no holder.
  • When accounting.requireHolder is off, Midaz does not check that the holderId you send exists.
  • An account that you create through v1 gets no holder. v1 does not apply these rules.
See Ledger settings.

Fees and Tracer

A v2 transaction runs two steps that v1 does not run:
  • Fees. Midaz charges a fee when a fee package matches the transaction.
  • Tracer. Midaz reserves the transaction in Tracer when the Tracer mode of the ledger is not off.
From v4.1.0, a transaction can skip these steps with skip.fees or skip.tracer. The ledger must turn on overrides.allowFeeSkip or overrides.allowTracerSkip first. Validate your fee packages and your Tracer limits before you move traffic. After the migration, you can see new charges and new refusals. See Midaz and plugin compatibility.

Migration checklist


  • List the routes that you use, the product version and the base URL of each service. Separate the routes with a v2 route from the routes that have none. Plan to stop using the routes that have none by April 29, 2027.
  • For each transaction, select direct or hold. Update debits, credits, the decimal values and the scope of each item.
  • Change CRM aliases to instruments. Move the organization and the ledger of Fees to the path. After the data migration, check the relationships and the identifiers.
  • Grant the midaz permissions. Test the holder rules of the accounts in a staging environment.
  • Update how you read success and error responses. Test removed fields, invalid input, missing resources and denied access.
  • Test each flow that your integration uses: create, read, hold, commit, cancel, revert, block and unblock. Check balances, operations, fees and refusals by Tracer limits.
  • Keep sending X-Idempotency and X-TTL on create requests. Do not send the same transaction through v1 and v2 to compare results. Use controlled data and scenarios in a staging environment.
  • Move traffic in controlled steps. Monitor errors and financial results. Keep a rollback plan that does not send processed transactions again.