Authorization flow
Find a transaction use case — purchases, amount changes, clearing, reversals and matching.
In an integrator-managed program, FINCI sends your backend an authorization request. Check the balance and controls, then approve with HTTP 200 and {"status":"success"}, or decline with HTTP 403 and {"status":"error"}, within 3 seconds. FINCI later confirms the resulting network outcome.
In FINCI-managed programs, FINCI makes the decision. The amount, reference and event-handling rules still apply. Start with Transaction lifecycle, or find a specific use case.
Decision sequence
- The merchant submits an authorization request through Mastercard to FINCI.
- FINCI sends your backend a decision request with empty
response_code. In integrator-managed programs, respond within 3 seconds using the HTTP status and body below. - FINCI returns the resulting decision to Mastercard.
- FINCI sends an outcome confirmation with the same
idand populatedresponse_code. Update that authorization once; the confirmation does not post money.
A timely approval normally confirms Approved. A decline or missing valid response normally confirms an insufficient-funds decline. Preserve the exact received outcome, including Insufficient funds. Handle an absent response_code only where your integration contract allows it.
An authorization advice is identified separately by advice: true; it is not the marker for this repeated-ID confirmation. Use Webhook handling for delivery, retries and idempotency.
Return the decision with the correct HTTP status
For an initial authorization decision, send the HTTP status and JSON body together, within 3 seconds:
| Your decision | HTTP status | JSON body |
|---|---|---|
Approve | 200 OK | {"status":"success"} |
Decline | 403 Forbidden | {"status":"error"} |
A decline requires HTTP 403. Returning HTTP 200 with {"status":"error"} is not a valid decline response. Set the status explicitly in your HTTP handler; changing the JSON body alone is not enough. The optional errors array follows the webhook response schema.
The later outcome confirmation reports what FINCI returned to Mastercard in response_code. Acknowledge a received confirmation with HTTP 200 and {"status":"success"} after durable receipt, even when its outcome is a decline. This acknowledgement confirms receipt; it is not another authorization decision.
Declined purchase
Merchant 8 requests EUR 135.60. The confirmation keeps the same authorization id, reports response_code: "Insufficient funds" and has a zero local account amount. Record the decline and release any provisional hold for this request. No debit is posted.
A EUR 135.60 request is confirmed as declined under the same authorization ID. The confirmation has no local movement.
Complete webhook messages
Download these complete messages (JSON)
Identifiers, merchant names, approval codes, dates and locations are fictional. Financial values, field types and references are preserved.
Advice flag and amount changes
advice: true identifies an authorization advice message. The authorization advice has this value.
The EUR 0.40 additional authorization has advice: false. It is a separate approved authorization linked to the earlier EUR 28.94 authorization, not an advice message.
Read approval from response_code and linkage from original_authorization_id or the supported original-reference fallback. A request's outcome confirmation repeats its id and supplies response_code. The advice flag does not specify whether a later amount is an increment or a replacement total; use the configured rule for that flow.
Amount fields
Reserve using each accounts_local[].account_amount in its account_currency for a debit decision. Use the confirmed outcome to keep or release that reservation; post the local movement only when presentment arrives.
| Amount or rate | What it describes |
|---|---|
amount_transaction / currency_transaction | Original transaction amount and currency. |
amount_settlement / currency_settlement | Amount expressed in settlement currency, for reconciliation. It can differ from the local total. |
accounts_local[].account_amount / accounts_local[].account_currency | Local total and currency to use for the appropriate hold or posting action. |
accounts_local[].fee_amount | Fee component. It is already included in the local total in the FX and ATM examples below. |
rate | Original-to-settlement currency conversion metadata. |
accounts_local[].account_local_rate | Settlement-to-local currency conversion metadata, as described by the schema. |
Read the complete field reference for every exact path, the separate rates, presentment components and 3D Secure amounts. Preserve rates; the public schema does not define a universal formula for recalculating the local total.
FX purchase and included fee
Merchant 2 receives a USD 49.99 purchase. These amounts come from the request, confirmation and presentment for the same purchase.
| Stage | Transaction | Settlement | Local account amount | Fee component |
|---|---|---|---|---|
Initial request | USD +49.99 | EUR +45.00 | EUR +45.00 | EUR +0.22 |
Approved confirmation | USD -49.99 | EUR -44.78 | EUR -45.00 | EUR -0.22 |
Presentment | Transaction component: EUR +44.78 | No top-level amount field | EUR -45.00 | Markup component: EUR -0.22 |
Reserve EUR 45.00 and later post EUR -45.00 once. Reserving EUR 45.22 would count the fee twice. At presentment, do not add the Markup component as another charge on top of the local total.
USD 49.99 purchase: reserve the EUR 45.00 local total, including the EUR 0.22 fee. Confirmation keeps that hold; presentment posts EUR -45.00 once.
Complete webhook messages
Download these complete messages (JSON)
Complete webhook examples. Identifiers, merchant names, approval codes, dates and locations are fictional.
In this purchase, initial amounts are positive and approved confirmation amounts are negative. The confirmation updates an authorization; its negative sign does not create a posted debit. Interpret the amount together with the message stage and authtype.
ATM withdrawal with FX markup and fee
Merchant 12 dispenses CHF 200.00. The local EUR total includes the converted withdrawal and both fee components:
| Component | EUR amount included in the total |
|---|---|
Converted withdrawal ( Transaction) | 215.22 |
ATM fee ( Fee) | 6.88 |
FX markup ( Markup) | 1.08 |
Total to reserve and later post | 223.18 |
On approval, reserve accounts_local[0].account_amount: 223.18. Confirmation keeps that EUR 223.18 hold. At cash presentment, post accounts_local[0].account_amount: -223.18 once and release the full hold.
fee_amount is 7.96 in the request and -7.96 in confirmation and clearing. It includes the EUR 6.88 fee and EUR 1.08 markup. Do not add either component to the local total again. The presentment's Transaction amount is positive, while its fee components are negative: use the supplied local account movement for posting rather than summing those signed components.
For the transaction, settlement and local amounts at each stage, see the ATM amount breakdown.
CHF 200.00 withdrawal: reserve EUR 223.18 including EUR 7.96 in fees. Confirmation keeps that reservation. Cash clearing posts EUR -223.18 once; the EUR 6.88 Fee and EUR 1.08 Markup are included.
Complete webhook messages
Download these complete messages (JSON)
Identifiers, merchant names, approval codes, dates and locations are fictional. Financial values, field types and references are preserved.
Preserve precision
Webhook IDs can exceed JavaScript's safe integer range. The examples use 18-digit JSON numbers. Parse them losslessly, then store and compare them as exact text so they match the string references authorization_id and original_authorization_id. Converting an ID to a string after ordinary JavaScript JSON.parse cannot restore digits already rounded away.
token_id is an opaque string. The examples use 20 decimal digits; the webhook schema allows up to 36 characters. Keep it as a string.
Use decimal arithmetic for money. In Python, json.loads(raw_body, parse_float=Decimal) preserves monetary decimals, and Python integers preserve ID digits.
Related authorizations and matching
Use the same linking procedure for an additional authorization, an authorization advice and a reversal. Each related record has its own id; its original references identify the earlier authorization. An outcome confirmation is different: it repeats the request's id and updates that existing authorization.
FINCI supplies original_authorization_id in related authorization webhooks. Do not construct it from rrn or nrn. If it is empty, preserve that value and store any supported fallback match separately in your records.
| Field | Relationship |
|---|---|
id | Identifier of this authorization record; a request and its outcome confirmation share it. On a reversal, this identifies the reversal itself. |
authtype | Reversal identifies a reversal message; it does not identify the earlier authorization. |
original_authorization_id | String reference from a related authorization to the original authorization. It can be empty. |
original_authorization_nrn | Original authorization's retrieval reference; compare with the earlier nrn. |
rrn | Retrieval Reference Number, documented for finding reversals. |
nrn / tlid | Additional network references to retain for matching and reconciliation. |
Automatically link a related record
- Store the record and its references. Preserve its own
id,token_id,authtype,response_code,adviceand all supplied original references. Keep the original transaction currency and the local account allocations separately. - Find the referenced authorization. Match a non-empty
original_authorization_idto the exact storedidin the same environment, program and card context. If the ID is absent or"", a suppliedoriginal_authorization_nrncan match the earliernrnunder the program's reference-matching rules; require one qualifying record. For a purchase reversal with both original fields absent or"", userrnonly where FINCI has confirmed that fallback for the program. - Join the same purchase. Keep the link to the exact referenced authorization. If that authorization already belongs to a purchase group, add the new record to that group. Follow stored original-reference links with cycle detection; do not assume every reference points directly to the first authorization.
- Apply the appropriate hold change once. Use the message type, reported outcome and the flow's amount-update rule. Linking the records does not itself reserve, release or post money. Make the state change and its idempotency record atomically.
For reference fallbacks, the program configuration must define the supported message types, card/account scope, currency field and matching time window. Keep currency_transaction separate from accounts_local[].account_currency; they are not interchangeable. One candidate in incomplete history does not establish a safe match outside those configured rules.
If an explicit target has not arrived, retain the link as pending and resolve it when that record arrives. Do not fall through to another reference because delivery was out of order. If supplied references conflict, several records qualify or the reference chain contains a cycle, keep the event unresolved for reconciliation. Do not guess from merchant, amount or timestamp alone.
Change the hold after linking
| Related record | Hold action | Worked example |
|---|---|---|
Approved incremental authorization | Add the approved additional local amount once under the flow's increment rule. A declined increment leaves the earlier approval in place. | EUR 28.94 + EUR 0.40: hold becomes EUR 29.34. |
Approved completion advice for an estimated amount | For an open, uncleared reservation, replace the hold with the advised local total. Release the difference if the total is lower; handle any increase under the program's funding policy. | Amount update: EUR 125.00 becomes EUR 29.12; release EUR 95.88 once. |
Confirmed purchase reversal | Release only the affected eligible unposted amount. Keep the reversal's own ID and link to the earlier authorization. | Partial reversal: EUR 10.00 becomes EUR 7.54 after a EUR 2.46 release. |
None of these authorization updates posts a debit or refund. Posting comes from presentment. A presentment closes the whole matched reservation. Do not recreate that hold for a late confirmation, advice or reversal. Before clearing, a partial reversal can leave an open amount for the applicable authorization update.
advice: true identifies the advice message. It does not, by itself, specify an increment or a replacement total. Apply the completion rule when the supported flow supplies a final amount for an earlier estimate; use the agreed rule for other advice flows.
The current rrn and nrn need not stay the same across related messages. Reference relationships can differ across processing routes, so prefer the supplied FINCI original reference and use only the confirmed fallback rules. Mastercard specifies Trace ID, original switch serial number and TLID for network reversal matching; these are not a universal order for the FINCI JSON fields. Retain tlid for reconciliation, and use it as a matching key only where its mapping and scope have been confirmed for your integration. See Mastercard Transaction Processing Rules, sections 2.9 and 2.11.
Keep rrn, nrn and tlid as exact opaque strings, including leading zeros and letter case. Do not parse them as numbers or concatenate them into a guessed authorization ID.
Keep each message's own ID and every relationship. Group connected records under your own purchase key. The examples below link to the first authorization; they do not establish whether a longer chain references its first authorization or a previous increment.
Additional authorization: EUR 28.94 + EUR 0.40
Merchant 3 first authorizes EUR 28.94, then sends an additional EUR 0.40 authorization for the same purchase. The second record has its own id, response_code: "Approved" and original_authorization_id referencing the first authorization. Its advice value is false, exactly as received.
The EUR 0.40 addition and EUR 29.34 presentment both reference the original EUR 28.94 approval.
Complete webhook messages
Download these complete messages (JSON)
Identifiers, merchant names, approval codes, dates and locations are fictional. Financial values, field types and references are preserved.
In this example, the additional authorization's own rrn and nrn differ from the first authorization. Its original_authorization_nrn: "DEMO030000001" matches the first authorization's nrn. Comparing only current network references would miss the link.
The presentment refers to authorization_id: "900300100000000000" and charges EUR 29.34. For this flow, the EUR 0.40 amount is an increment: add it once to the EUR 28.94 reservation. If the additional authorization is declined, keep the earlier approval. Other flows can supply a replacement total instead; use the configured amount-update rule.
Sign note: the confirmed local amounts are EUR -28.94 and EUR -0.40. They describe approved authorizations, not two posted debits. The presentment posts EUR -29.34.
Preauthorization, partial approval and amount updates
A preauthorization approves an estimate before the final price is known. A partial approval approves less than the requested amount. A partial presentment clears only part of an existing approval.
The webhook reply has no field for returning a lower approved amount. The authorization payload also has no dedicated preauthorization classification field.
A partial approval is a decision on the original request. In the amount-update example below, EUR 125.00 is requested and approved; a later advice reports EUR 29.12. The sequence demonstrates an update after approval, rather than an initial approval for less than requested.
Advice that completes an estimated authorization
A merchant can authorize an estimate before the final price is known, then send linked advice with the completed amount. This can occur at a fuel dispenser, with a taxi fare or with another merchant that initially authorizes an estimate. The linking procedure is the same; the merchant category does not determine how the amount is applied.
For the supported completion flow, update the existing hold to the new local total. Keep the earlier approval and the advice as linked records, and apply the update once even if the advice is redelivered. The complete messages below illustrate the amount-update flow. The same handling applies to other merchants using the supported flow.
Authorization amount update: EUR 125.00 to EUR 29.12
For Merchant 4, EUR 125.00 is approved before a later linked Goods authorization reports EUR -29.12, response_code: "Approved" and advice: true. The example stops at authorization advice; it does not show a clearing.
| Message | Signed local amount | Meaning |
|---|---|---|
Initial decision request | EUR +125.00 | Estimated amount before the completed amount is known. |
Approved confirmation | EUR -125.00 | Keep the existing EUR 125.00 reservation. No debit is posted. |
Linked authorization advice | EUR -29.12 | Replace the hold with EUR 29.12 and release EUR 95.88. Keep its own id and original reference. Posted movement remains EUR 0.00. |
Replace the existing hold with the advised local total. The EUR 125.00 hold becomes EUR 29.12, releasing EUR 95.88. Keep the advice's own id and link to the earlier authorization; a retry must not release the difference again. This example contains no presentment, so the posted movement remains EUR 0.00.
Sign note: both the EUR -125.00 confirmation and EUR -29.12 advice are authorization data. Their negative signs do not post charges. A debit is posted only from a presentment.
Initial approval holds EUR 125.00. Linked authorization advice replaces it with EUR 29.12 and releases EUR 95.88 once. No presentment is supplied, so posted movement remains EUR 0.00.
Complete webhook messages
Download these complete messages (JSON)
Identifiers, merchant names, approval codes, dates and locations are fictional. Financial values, field types and references are preserved.
Final outcome codes
A populated response_code reports an authorization outcome. It can appear on a confirmation or a related authorization update; an empty value is not an outcome.
It represents the authorization outcome that FINCI actually returned to Mastercard, including cases where FINCI had to apply the fallback decline outcome.
Store response_code exactly as received and map it to the outcome categories agreed for your integration.
The table below reflects the published webhook enum. Webhooks can also contain human-readable values such as Insufficient funds, which differ from the enum's InsufficientFunds. Preserve the exact received value and use the outcome mapping agreed during integration; do not silently replace the raw value. These values are not decline reasons that the integrator can return in the initial webhook response.
The integrator response contract is success or error. An error normally results in an insufficient-funds decline, confirmed through the raw response_code. More specific integrator-provided decline reasons are not supported by the current response schema.
| Response code | Meaning |
|---|---|
Aborted | Authorization was aborted before a normal business outcome was completed. |
Approved | Authorization approved. |
ArqcAuthFailed | EMV ARQC authentication failed. |
AuthenticationFailed | Authentication check failed. |
CantFindContract | Processing could not resolve the required contract or agreement record. |
CavvAuthFailed | 3DS CAVV authentication failed. |
ContractIsRestricted | The resolved contract exists but is restricted for this usage. |
CustTokenInvalidExp | Customer token or related credential is invalid or expired. |
Cvv2AuthFailed | CVV2 verification failed. |
Cvv2TryExceeded | CVV2 retry limit exceeded. |
CvvAuthFailed | CVV verification failed. |
HighRisk | Declined by fraud or risk controls. |
InsufficientFunds | Insufficient available funds, budget, or spending capacity. |
InvalidCustomer | Customer or cardholder data is not valid for this transaction context. |
InvalidRequest | Request data is malformed, inconsistent, or cannot be processed safely. |
IssuerLimitHasBeenReached | A configured issuer-side limit has already been reached. |
IssuerLimitWillBeExceeded | This authorization would exceed a configured issuer-side limit. |
PayeeTokenIsBlocked | The payee or recipient token is blocked. |
PinAuthFailed | PIN verification failed. |
PinTryExceeded | PIN retry limit exceeded. |
Predeclined | Declined before normal authorization processing completed. |
RecipientTokenNotFound | The recipient token could not be found. |
Rejected | Generic decline where no more specific business code is used. |
RoutingError | Processing or network routing failed. |
SystemError | Processing error. |
TimeoutRevNotMatched | A reversal could not be matched to the original authorization within the expected processing window. |
TokenIsBlocked | Card is blocked from use. |
TokenIsClosed | Card is closed. |
TokenIsCompromised | Card is marked as compromised. |
TokenIsDeactivated | Card is temporarily deactivated or suspended. |
TokenIsLost | Card is marked as lost. |
TokenIsReferral | Card is in referral status; contact between the client and issuer is required. |
TokenIsStolen | Card is marked as stolen. |
TokenNotFound | Card could not be found. |
Keep the original response value for transaction history and support.
Timeout behavior
The integrator must respond to the initial authorization webhook within 3 seconds.
If no valid response is received in that window, the transaction normally receives an insufficient-funds decline. Persist the exact response_code from the resulting confirmation.
The integrator should still expect the follow-up authorization outcome confirmation after that timeout path. It uses the same authorization id and carries the final response_code that FINCI sent to Mastercard.
This timeout should shape the design of the authorization handler and any supporting decision logic.
What the integrator should evaluate
Where integrator-managed decisioning is in scope, the relevant checks depend on the agreed program setup, responsibility model, and control framework.
The account entity still exists even where approval logic is not driven by an account-balance check. Depending on the agreed model, the integrator may evaluate a client-managed balance or budget during the webhook decision, or may ignore balance and apply other policy or control logic instead. The linked account record remains part of the required card and transaction structure in both cases.
Typical decision logic should evaluate both the financial meaning of the message and the operational state behind it.
Depending on the agreed program and operating model, the integrator may need to check:
- confirm whether the webhook represents a debit authorization, credit authorization, reversal, or technical message, and interpret the amount, currency, and
authtypeaccordingly - confirm that the token exists, the card is in a usable status, the linked account is valid, and the transaction is consistent with the current cardholder and account setup
- for debit-side flows, evaluate available balance, remaining budget, hold model, and any configured daily, monthly, or program-specific limits
- apply MCC restrictions, geography restrictions, cardholder or employee policy, merchant controls, and any program-level spend rules
- detect likely duplicate authorization attempts, repeated retries, and patterns that should be treated as suspicious or high risk
- treat
PaymentCreditandReturn(refund) as credit-side flows, treatReversalas an unwind of the earlier authorization effect where applicable, and treatGetContractInfoas a technical message - if required balance or policy checks cannot complete, return
errorwithin the decision window
Authorization types and funds direction
Authorization is not limited to purchase-style debit flows.
The webhook authtype values should be interpreted as follows:
CashDebit authorization.GoodsDebit authorization.PaymentDebitDebit authorization.QuasiCashDebit authorization.PaymentCreditCredit authorization.ReturnCredit authorization, typically representing a return or refund flow.ReversalCancellation of a previous authorization rather than a new debit or credit authorization.GetContractInfoTechnical message.
Reversals use the authorization receiver and are identified by authtype: "Reversal". Read response_code to distinguish a decision request from a received outcome; apply the matched hold-release effect once.
The authorization decision logic should therefore evaluate not only whether a transaction is allowed, but also what financial direction and business effect the authorization represents.
Authorization handler design
The authorization handler should be designed for fast, consistent, and auditable decisioning.
At a minimum:
- keep processing within the 3-second response window
- avoid unnecessary synchronous dependencies in the decision path
- return a single clear
successorerroroutcome for each initial authorization request - record the request, decision, and key identifiers for support and investigation
- treat timeout or decisioning failure as a decline path
Authorization is not final settlement
An approved authorization is not the final booked transaction.
Clearing can happen later and may confirm the same amount or a different final amount, depending on network behavior and merchant processing.