- Transaction fees apply to the
/v2transactions that the account sends. - Service fees apply when you charge a service to the account, for example a paper statement. You charge them with a fee charge.
Account plans and fee packages
An account plan and a fee package are different entities.
- An account with an active account plan pays the fees of its plan on the
/v2transactions it sends. On those transactions, a fee package never charges that account, also when no fee of the plan matches. Then the account pays no fee. - A fee package does not charge the fee legs that an account plan adds.
Create an account plan
Create a plan with Create an account plan. The plan has these fields:
label: the name of the plan. Two plans of a ledger that are not deleted cannot have the same label (0543).description: optional.enable:truelets you assign the plan to accounts.timezone: the IANA timezone that the plan counts its months in. The default isAmerica/Sao_Paulo.fees: at least one fee, by fee key. A fee key starts with a lowercase letter, followed by ASCII letters and digits only (^[a-z][a-zA-Z0-9]*$).
feeLabel: the name of the fee.trigger: what makes the fee apply. See Triggers.calculationModel:flatFee,percentual, ormaxBetweenTypes, as in a fee package. A service fee accepts onlyflatFee(0555).creditAccount: the alias of the ledger account that receives the fee. Midaz checks that the account exists when you create or update the plan.accounting: thetransactionRoute,operationRouteFrom, andoperationRouteToof the fee. See Accounting routes.freeQuota: the number of free units per month. The default is0.period: onlymonthly, the default.referenceAmount: onlyoriginalAmount, the default.
Triggers
A trigger withtype: transaction takes these fields:
direction: required. The only value issent: the fee applies to the account that sends the transaction.schemes: the transaction schemes that the fee matches, for exampleTEDorPIX.metadata: optional pairs that the transaction metadata must all carry. A pair matches only a string metadata value that is equal to it.
type: service takes only serviceCode, for example PAPER_STATEMENT.
Midaz stores schemes and service codes trimmed and in upper case. Each one has 1 to 50 letters, digits, underscores, or hyphens. One code cannot be the scheme of a fee and the service code of another fee of the plan (0558).
Accounting routes
The rules depend on whether the ledger validates accounting routes (accounting.validateRoutes in the ledger settings):
Two transaction fees of a plan with the same
metadata cannot select the same transactions (0544). On a ledger without route validation, they cannot share a scheme. On a ledger with route validation, they cannot share a transaction route and a scheme, and a fee without schemes takes every scheme of its route. Two service fees cannot share a service code (0544).
If you turn on route validation after you create a plan, give every fee a transaction route and both operation routes first. A fee without a transaction route refuses each transaction that it would match with 0547, and each fee charge that names it.
Versions
The fees of a plan live in versions. A version never changes.
- The create makes version 1, in effect from the instant of the create.
- An update that sends
feesmakes a new version with the full resulting set of fees. effectiveFromsets the instant that the new version applies from, in RFC 3339. The default is the instant of the request. It cannot be before theeffectiveFromof the latest version (0553). Send it only withfees.label,description,enable, andtimezonechange the plan, not a version.
fees of an update:
- An entry with the key of a stored fee changes the fields it sends and keeps the others.
trigger,calculationModel, andaccountingchange as a whole. - An empty entry (
{}) deletes that fee. - An entry with a new key adds a fee, with every required field.
- The new version starts from the fees of the latest version. It keeps at least one fee.
0559 and creates no version. Read the plan again and send the update again.
Get an account plan returns the version in effect at the instant of the request. currentVersion is the highest version created, which can start later. List the versions of an account plan returns every version.
Assign a plan to an account
Assign an account plan to an account sends the
accountPlanId of the plan.
- The plan must belong to the ledger, exist, and be enabled (
0545). - If the account has an active assignment of another plan, it ends at the instant that the new assignment starts, in one step.
- If the account already has the same plan, Midaz returns the active assignment and changes nothing.
- When another assignment of the same account runs at the same time, Midaz can answer
0560and change nothing. Send the request again.
null, and the history of the account. List the accounts assigned to an account plan returns the active assignments of a plan.
End the account plan assignment of an account ends the active assignment. The fee packages then apply to the account again. An account without an active assignment answers 0554.
Disable or delete a plan
- A disabled plan (
enable: false) cannot be assigned. It keeps charging the accounts that it already has. - Midaz refuses to delete a plan that is assigned to an account (
0546). End its assignments first. - When you delete an account, Midaz ends its active assignment. The history of the account stays readable.
How a plan charges a transaction
Midaz applies account plans to these
/v2 transactions: direct, hold, block, unblock, and each item of a batch. A /v1 transaction, an annotation, a revert, and a transaction that skips fees with skip.fees do not use account plans.
Midaz takes one decision for each source account of the transaction that has an active plan, except @external accounts. It takes one decision per account, also when the account sends from several balances.
Matching
The fees of the version in effect are matched against the transaction:- On a ledger without route validation, a transaction fee matches when its
schemescontain theschemeof the transaction. A transaction withoutschemematches no fee. - On a ledger with route validation, a transaction fee matches when its
transactionRouteis therouteIdof the transaction and itsschemesare empty or contain theschemeof the transaction. - In both cases, the transaction metadata must carry every
metadatapair of the fee. - When several fees match, the fee with the most
metadatapairs applies. When two or more fees have that number of pairs, Midaz refuses the transaction with0548.
Outcome
The decision has one of these outcomes:
Midaz calculates a charged fee on the amount that the account sends in the transaction. On a ledger with route validation, the fee legs use the operation routes of the fee.
The create response has
accountPlanFees, with one item for each account that has an active plan: accountId, accountAlias, accountPlanId, accountPlanVersion, feeKey, outcome, unit, freeQuota, and amount. Only the create responses return it. Reads, commits, cancels, and reverts do not. The transaction metadata keys packageAppliedID, feeApplied, and feeExemption describe fee packages only.
Holds, cancels, and reverts
- A hold counts the unit when you create it. The commit counts nothing.
- A cancel or a revert gives the unit back only in the same month of the plan. The revert also reverses the fee legs.
Free quota
A unit is one decision with the outcome
quota or charged, or one service code of a fee charge with the same outcomes.
- Midaz counts units per account, fee key, and calendar month in the plan timezone.
- The count belongs to the account and the fee key, not to the plan. An account that moves to another plan with the same fee key keeps its count for the month.
- A transaction fee counts each scheme separately. On a ledger with route validation, a fee without schemes has one count for every scheme of its route. A service fee has one count.
- When you change a fee, its count stays. A fee with a new key starts at zero.
- The month is the month in which Midaz processes the transaction, not its
transactionDate.
Service fees and fee charges
Charge service fees to an account sends
serviceCodes, with 1 to 100 codes, and an optional description and metadata. The request needs the X-Idempotency header (0552).
Each code in the list is one unit. Its outcome is one of these:
quota: the unit is inside the free quota of its fee. It costs nothing.charged: the unit is past the free quota. It costs the flat amount of the fee.not_covered: the plan of the account has no service fee for the code, or the account has no active plan. It costs nothing and counts no unit.
- No account plan of the ledger has a service fee for a code (
0549). - A code belongs only to transaction fees (
0550). - On a ledger with route validation, the fees of the codes have different transaction routes (
0551), or a fee has no transaction route (0547).
creditAccount of each fee. On a ledger with route validation, the transaction uses the transaction route and the operation routes of the fees. The description and metadata of the charge go to the fee transaction. No fee package, account plan, or Tracer validation applies to the fee transaction. When Midaz refuses the fee transaction, for example for insufficient funds, it refuses the charge with the same error and counts no unit.
A charge without a charged unit has no fee transaction, and its feeTransactionIds is empty. Nothing undoes that charge, and its units stay counted.
- A retry with the same key and the same body returns the recorded charge with the
X-Idempotency-Replayedheader. A different body with the same key answers0084. Keys are unique per account. - To undo a charge, revert its fee transaction. A revert in the same month gives back every unit of the charge.
- The fee transaction has no reference to its charge.
feeTransactionIdson the charge links them.
period (YYYY-MM) filters it. Get a fee charge of an account returns one charge.
Usage
Get the account plan usage of an account returns the units of the account in one month.
period (YYYY-MM, in the plan timezone) selects the month. The default is the current month. A future or malformed period answers 0082, and an account without an active plan answers 0554.
The response has one item for each count of each fee: feeKey, trigger, period, freeQuota, used, remaining, and charged. trigger is a key for the count: read feeKey instead of parsing it. remaining is never negative.
The usage lists the fees and free quotas of the version in effect now, also for a past month. For reconciliation, use the accountPlanFees of the create responses and the fee charges.
Estimates and events
- A fee estimate prices the fee package that you name. It does not read account plan assignments.
- The
fee_charge.appliedevent covers fee packages only. An account plan fee or a fee charge does not emit it.
Permissions
The routes use these Midaz permission resources:
Next steps
Using account plans
Create a plan, assign it, and charge fees step by step.
Midaz error list
See the codes from
0543 to 0560.
