Skip to content
BaxPayDevelopers

In-store integration

Fuel forecourt

You don't know the amount until the nozzle stops. So authorize a ceiling, then capture what was actually pumped.

A forecourt controller can't take a fixed amount up front. The customer authenticates for a maximum, fuels, and you capture what they really dispensed — BaxPay releases the difference.

Pre-auth → dispense → capture

Pre-authorize a ceiling

Open a session with type: "PREAUTH" and the ceiling as amountMinor, say €150. The shopper authenticates at the pump terminal and BaxPay holds that amount on their funds.

Release the pump

When the session reads AUTHORIZED (or the payment_session.preauthorized webhook arrives), your controller unlocks the nozzle. The hold reduces the shopper's available balance but has moved no money.

Capture the actual

When fuelling ends, capture the real amount (≤ the ceiling). BaxPay takes that and releases the rest of the hold in the same step.

POST/integration/sessionstype: "PREAUTH"
POST/integration/sessions/{id}/fuel/captureIdempotency-Key required
POST/integration/sessions/{id}/fuel/releaseno fuel taken
curl -X POST https://sandbox-api.baxpay.com/v1/integration/sessions \
  -H "Authorization: Bearer $BAXPAY_CONNECTION" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "saleReferenceId": "site12-pump7-tx88",
    "type": "PREAUTH",
    "amountMinor": 15000,
    "currency": "EUR"
  }'
{
  "success": true,
  "data": { "sessionId": "44e977a5-…", "type": "PREAUTH", "status": "CREATED", "amountMinor": 15000, "final": false }
}

In sandbox, play the shopper approving at the pump:

curl -X POST https://sandbox-api.baxpay.com/v1/integration/sessions/44e977a5-…/simulate \
  -H "Authorization: Bearer $BAXPAY_CONNECTION" \
  -H "Content-Type: application/json" \
  -d '{ "outcome": "APPROVED" }'
{ "success": true, "data": { "status": "AUTHORIZED", "final": false } }

The pump stops at €81.40. Capture that:

curl -X POST https://sandbox-api.baxpay.com/v1/integration/sessions/44e977a5-…/fuel/capture \
  -H "Authorization: Bearer $BAXPAY_CONNECTION" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "finalAmountMinor": 8140 }'
{
  "success": true,
  "data": {
    "sessionId": "44e977a5-…",
    "type": "PREAUTH",
    "status": "CAPTURED",
    "amountMinor": 15000,
    "capturedAmountMinor": 8140,
    "resultCode": "APPROVED",
    "final": true
  }
}

amountMinor stays the ceiling you authorized; capturedAmountMinor is what was charged. The €68.60 difference went back to the shopper with the capture.

No fuel taken

The shopper authorized but drove off, or the nozzle never moved: release the pre-auth. The whole hold goes back at once, the session becomes VOIDED and payment_session.voided fires. Voiding an AUTHORIZED pre-auth (/void) does the same.

# sandbox: a second pre-auth, approved at the pump
SESSION=$(curl -s -X POST https://sandbox-api.baxpay.com/v1/integration/sessions \
  -H "Authorization: Bearer $BAXPAY_CONNECTION" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "saleReferenceId": "site12-pump7-tx89", "type": "PREAUTH", "amountMinor": 15000 }' | jq -r .data.sessionId)
curl -X POST "https://sandbox-api.baxpay.com/v1/integration/sessions/$SESSION/simulate" \
  -H "Authorization: Bearer $BAXPAY_CONNECTION" -H "Content-Type: application/json" \
  -d '{ "outcome": "APPROVED" }'
curl -X POST https://sandbox-api.baxpay.com/v1/integration/sessions/44e977a5-…/fuel/release \
  -H "Authorization: Bearer $BAXPAY_CONNECTION"
{
  "success": true,
  "data": { "status": "VOIDED", "resultCode": "ABORTED", "resultDetail": "Pre-authorization released", "final": true }
}

If you never capture or release, BaxPay releases the hold automatically 2 hours after the pre-auth was approved, with the same payment_session.voided event.

Prefer a release over capturing 0: a zero capture is accepted, but it books a zero sale instead of simply cancelling.

IFSF and OPI estates

Forecourts speaking IFSF or OPI connect through the matching adapter with an IFSF or OPI connection. The adapter maps their messages onto the same pre-auth / capture engine:

ProtocolEndpointMaps to
IFSFPOST /integration/ifsf/reservationMaxAmount (major units) → pre-auth
IFSFPOST /integration/ifsf/completionFinalAmount against POITransactionID → capture
OPIPOST /integration/opi/cardServiceRequestCard service requests → sessions

Edge cases

Pump meter dispute

The captured amount is authoritative for settlement. Reconcile pump totals against the settlement batch, not against the pre-auth ceiling.

Capture retried

Retry with the same Idempotency-Key. A capture on a session that is already CAPTURED answers 409.