At the center of Flute's payments model is the transaction. A transaction is a record created every time money moves through a merchant's account.
A transaction is created with a single call: POST /v2/transactions
Every transaction carries the same core shape regardless of payment type:
paymentProcessorIdspecifies the processor handling the transaction.baseAmountandcurrencyCodespecify the transaction amount.referenceIdspecifies a value the merchant chooses for their own bookkeeping.transactionDetailsspecifies an object holding either thecardDataorachDatadepending on how the customer is paying.
Each transaction goes through the same endpoint. It comes back with the same response envelope, just populated with different processorResponse details. This includes whether someone is charging a saved card, running a brand-new card number inline, or debiting a bank account through ACH.
Card transactions carry an extra decision point that ACH doesn't: captureMethod. This is set to either Auto or Manual.
Autocapture means the authorization and the capture happen in one step, and the transaction lands in an Approved state immediately, ready to settle.Manualcapture splits it into two steps: the initial call only authorizes the funds and returns a Pending transaction, and a separate call toPOST /v2/transactions/{transactionId}/capturelater finalizes it.
This distinction matters most for merchants who need to confirm inventory or finalize an order total. For example, a restaurant might close a tab with tips added before actually pulling the money. It's why the API treats "money authorized" and "money captured" as two different states rather than collapsing them into one.
Once a transaction is captured or approved, several other endpoints act on it rather than creating a new one.
POST /v2/transactions/{transactionId}/reversalreverses a transaction outright.POST /v2/transactions/{transactionId}/tip-adjustmentlets a merchant amend the tip on an existing charge, common in card-present environments where the tip is added after the initial swipe.POST /v2/transactions/reversalfor pulling money back after settlement.POST /v2/transactions/creditfor issuing money without tying it to a prior reference.POST /v2/transactions/{transactionId}/ach-holdfor placing a hold on a pending ACH transaction.
Every transaction also comes back with a rich amountDetails and processorResponse breakdown rather than just a status code.
amountDetailsseparatesbaseAmountfromtipAmount,tipRate,surchargeAmount, anddiscountAmount. A merchant can see exactly how aprocessedAmountwas assembled instead of just the final total.processorResponsereports which underlying processor ran the transaction, TSYS, for instance, on the card examples in the spec, or a plain ACH label for bank debits, along with a response code and a human-readable message. For card transactions there's also anaddressVerificationServiceResponse, showing whether the billing address and the postal or ZIP code the customer supplied matched what the card issuer has on file. This is one of the signals merchants use to judge fraud risk on a given charge.
The following is an example of a basic transaction. A merchant charges $100 on a saved card with auto-capture, and the customer adds a $15 tip at checkout.
Request POST /v2/transactions
{
"paymentProcessorId": "a2f2c2e7-0b23-4682-8f99-ab7707205461",
"baseAmount": 100.00,
"currencyCode": "USD",
"referenceId": "REF-CARD-SALE-001",
"isCustomerInitiatedTransaction": true,
"pricingType": "Card",
"transactionDetails": {
"cardData": {
"captureMethod": "Auto",
"paymentMethodId": "e397e367-bc4a-4b69-bd78-32e3e12327c2"
}
}
}Because the captureMethod is Auto, Flute authorizes and captures the charge in the same call. The response comes back already settled from the API's perspective:
Response
{
"transactionId": "5f6f782f-37af-44e1-bb18-2bc35e411899",
"transactionStatus": "Approved",
"processedAmount": 115.5,
"currencyCode": "USD",
"amountDetails":
{
"baseAmount": 100.00,
"tipAmount": 15,
"surchargeAmount": 3,
"discountAmount": 2.5
},
"processorResponse":
{
"processorName": "TSYS",
"responseCode": "00",
"responseMessage": "Approved",
"responseDefinition": "Approved and completed"
},
"addressVerificationServiceResponse":
{
"action": "Allow",
"responseCode": "Y",
"description": "Address and ZIP match"
}
}The processedAmount ($115.50) reflects the base charge plus the tip and a surcharge, minus a discount. This is exactly as itemized in amountDetails.
The transaction is done. There is no separate capture call needed. This merchant chose the auto-capture path rather than the authorize-then-capture flow used for something like a restaurant tab.