Dapit Instant Payments API Merchant Documentation

Instant Payments API

Accept instant SEPA payments from your customers with zero chargebacks, no rolling reserves, and same-day settlement. This API lets you create checkout sessions and receive payment confirmations.

Overview

The Dapit Instant Payments API enables merchants to accept EUR payments via SEPA Instant Credit Transfer. Instead of credit cards, your customers pay directly from their bank account (Wise, Revolut, or any EUR-enabled bank). Payments settle in under 10 seconds and are irrevocable — no chargebacks.

Key Benefits:Very low Fees · Zero rolling reserves · Same-day settlement · No chargebacks · No card network dependency · Works worldwide via Wise/Revolut

Base URL:

https://www.maxafi.com/api/gateway/gateway.php

Payment Flow

The customer never leaves your website. When they choose "Pay with Instant Payments" at your checkout, your server talks to our API behind the scenes.

1
Create Session
Your server calls our API with the order amount
2
Display Payment Info
Show the IBAN, beneficiary name, and reference on YOUR checkout page
3
Customer Pays
They open Wise/Revolut, send EUR with the reference number
4
Customer Clicks "I Paid"
Your page calls our API to start payment verification
5
We Verify & Notify
We find the payment in ConnectPay, confirm it, and POST to your webhook
Two integration options:
Option A — API Integration (recommended): Your developer embeds the payment flow directly into your existing checkout page. The customer never leaves your site. You control the look and feel.

Option B — Hosted Checkout: If you don't have a developer, we provide a hosted checkout page. You redirect the customer to our URL and we handle everything. They see your merchant name on a Dapit-branded page.

Authentication

All API requests require your merchant API key. Include it in the request header:

X-Gateway-Key: your_api_key_here

Your API key is provided during merchant onboarding. Keep it secret — it authenticates all requests to our API on your behalf.

Security: Never expose your API key in client-side code. All API calls should be made from your server (backend), not from the browser.

Quick Start — Option A: API Integration

Your developer adds Instant Payments as a payment option on your existing checkout page. The customer never leaves your website.

Step 1: Customer selects "Pay with Instant Payments" on your checkout

Your checkout page already has credit card, ACH, etc. Add an "Instant Payments" button alongside them. When they click it, your server creates a session:

// YOUR SERVER — Create a session when customer chooses Instant Payments
const response = await fetch('https://www.maxafi.com/api/gateway/gateway.php?action=create_session', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Gateway-Key': 'your_api_key_here'
  },
  body: JSON.stringify({
    amount: 49.99,
    currency: 'EUR',
    items: [
      { name: 'Premium Game Credits', qty: 1, price: 49.99, total: 49.99 }
    ],
    callback_url: 'https://yoursite.com/webhooks/dapit'
  })
});

const session = await response.json();
// session.session_token → save this (you'll need it for polling)
// Now call create_invoice to get the payment details...

Step 2: Get payment details and display on YOUR page

// YOUR SERVER — Get the IBAN, beneficiary, and reference number
const invoice = await fetch('https://www.maxafi.com/api/gateway/gateway.php?action=create_invoice', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: session.session_token })
}).then(r => r.json());

// Display these on YOUR checkout page:
// invoice.beneficiary_name → "Longemalle Trustees OU"
// invoice.iban             → "LT913740020058585210"
// invoice.reference_number → "DP-260330-XA6HSX"
// invoice.amount           → 49.99
// invoice.invoice_number   → "INV-260330-04821"
//
// Tell the customer:
// 1. Open your banking app (Wise, Revolut, etc.)
// 2. Send €49.99 to beneficiary "Longemalle Trustees OU"
// 3. IBAN: LT913740020058585210
// 4. Reference: DP-260330-XA6HSX
// 5. Click "I've Sent the Payment" button on your page

Step 3: Customer clicks "I Paid" — start polling

// YOUR PAGE (JavaScript) — When customer clicks "I Paid"

// First, tell our API the customer says they paid
await fetch('https://www.maxafi.com/api/gateway/gateway.php?action=confirm_paid', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: sessionToken })
});

// Then poll every 7 seconds until payment is confirmed
const pollInterval = setInterval(async () => {
  const check = await fetch('https://www.maxafi.com/api/gateway/gateway.php?action=check_payment', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token: sessionToken })
  }).then(r => r.json());

  if (check.status === 'confirmed') {
    clearInterval(pollInterval);
    // 🎉 Full payment confirmed!
    showPaymentSuccess(check.total_paid, check.invoice_amount);

  } else if (check.status === 'partial') {
    clearInterval(pollInterval);
    // ⚡ Partial payment — show receipt + remaining balance
    showPartialPayment(check.total_paid, check.amount_remaining, check.payments);
    // When customer sends remaining: call confirm_paid again, restart polling

  } else if (check.status === 'overpaid') {
    clearInterval(pollInterval);
    // 💰 Overpayment — order confirmed, refund will be processed
    showOverpaid(check.total_paid, check.overpaid_amount, check.refund_net, check.refund_fee);

  } else if (check.status === 'timeout') {
    clearInterval(pollInterval);
    showPaymentRetry();
  }
  // 'pending' — keep polling
}, 7000);

Step 4: Receive webhook confirmation (your server)

// YOUR SERVER — Webhook endpoint receives POST when payment is confirmed
// Fires for both exact and overpayments (not for partial — only when fully paid)
app.post('/webhooks/dapit', (req, res) => {
  const { event, merchant_order_id, invoice_amount, amount_paid,
          overpaid_amount, refund_amount, refund_fee } = req.body;

  if (event === 'payment.confirmed') {
    // ✅ Payment confirmed! Update your order database.
    console.log(`Order ${merchant_order_id} paid: €${amount_paid} of €${invoice_amount}`);

    if (overpaid_amount > 0) {
      // Customer overpaid — refund of €(overpaid - fee) will be processed
      console.log(`Overpaid by €${overpaid_amount}. Refund: €${refund_amount} (fee: €${refund_fee})`);
    }

    // Mark order as paid, send confirmation email, trigger fulfillment
  }

  res.status(200).json({ received: true });
});

Quick Start — Option B: Hosted Checkout

If you don't have a developer or want the simplest possible integration, use our hosted checkout page. You just create a session and redirect — we handle the entire payment UI.

// YOUR SERVER — Create session and redirect customer to our hosted page
const session = await fetch('https://www.maxafi.com/api/gateway/gateway.php?action=create_session', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Gateway-Key': 'your_api_key_here'
  },
  body: JSON.stringify({
    amount: 49.99,
    currency: 'EUR',
    items: [{ name: 'Premium Game Credits', qty: 1, price: 49.99, total: 49.99 }],
    callback_url: 'https://yoursite.com/webhooks/dapit'
  })
}).then(r => r.json());

// Redirect customer to our hosted checkout
res.redirect('https://www.maxafi.com' + session.checkout_url);
// Customer sees: your merchant name, invoice, IBAN, reference, "I Paid" button
// When confirmed, we POST to your callback_url
Option A vs Option B: Option A gives you full control — the payment form matches your brand and the customer never leaves your site. Option B is faster to set up but sends the customer to a Dapit-branded page. Most merchants with a development team should use Option A.

Create Session

POST ?action=create_session

Creates a new checkout session. Returns a checkout URL to redirect your customer to.

Headers

NameValue
X-Gateway-KeyYour merchant API key REQUIRED
Content-Typeapplication/json

Request Body

ParameterTypeDescription
amountnumberPayment amount in EUR REQUIRED
currencystringCurrency code. Default: EUR OPTIONAL
itemsarrayArray of line items: [{name, qty, price, total}] OPTIONAL
order_idstringYour own order/invoice number (e.g. ORD-12345). Returned in webhook so you can match to your system. OPTIONAL
customer_emailstringCustomer's email address OPTIONAL
customer_namestringCustomer's name OPTIONAL
callback_urlstringURL we POST to when payment is confirmed OPTIONAL
expires_minutesnumberSession expiry in minutes. Default: 60 OPTIONAL

Response

{
  "success": true,
  "session_id": 42,
  "session_token": "a1b2c3d4e5f6...",
  "checkout_url": "/checkout/pay.html?session=a1b2c3d4e5f6...",
  "expires_at": "2026-03-30 23:30:00",
  "amount": 49.99,
  "currency": "EUR",
  "merchant_order_id": "ORD-12345"
}

Create Invoice

POST ?action=create_invoice

Generates the invoice, reference number, and returns the IBAN + beneficiary details. Call this after create_session to get the payment information to display on your checkout page. This is the key endpoint for Option A integration.

Request Body

ParameterTypeDescription
tokenstringThe session_token from create_session REQUIRED

Response

{
  "success": true,
  "reference_number": "DP-260330-XA6HSX",
  "invoice_number": "INV-260330-04821",
  "amount": 49.99,
  "currency": "EUR",
  "iban": "LT913740020058585210",
  "beneficiary_name": "Longemalle Trustees OU",
  "account_name": "Dapit Financial Infrastructure",
  "bank_name": "ConnectPay"
}
Display all of these on your checkout page: the beneficiary name, IBAN, and reference number. The customer must enter all three in their banking app exactly as shown.

Confirm Paid

POST ?action=confirm_paid

Call this when the customer clicks "I've Sent the Payment" on your page. This tells our system to start checking ConnectPay for the incoming transfer.

Request Body

ParameterTypeDescription
tokenstringThe session_token REQUIRED

Response

{
  "success": true,
  "status": "polling",
  "reference": "DP-260330-XA6HSX",
  "message": "Payment verification started. We are checking for your transfer."
}

Check Payment (Polling)

POST ?action=check_payment

Poll this endpoint every 5-7 seconds after calling confirm_paid. It checks ConnectPay for incoming transfers matching your reference number. Handles exact payments, partial payments, and overpayments automatically.

Request Body

ParameterTypeDescription
tokenstringThe session_token REQUIRED

Response — Full Payment

{
  "success": true,
  "status": "confirmed",
  "paid_at": "2026-03-31 10:05:12",
  "invoice_amount": 7.00,
  "total_paid": 7.00,
  "payment_count": 1,
  "payments": [{ "amount": 7.00, "debtor_name": "John Smith", "debtor_iban": "DE89370400440532013000" }],
  "amount_match": true
}

Response — Partial Payment

If the customer sends less than the invoice amount, you get a partial status. Show the receipt and remaining balance, then let them send the rest using the same reference number. Call confirm_paid again to restart polling.

{
  "success": true,
  "status": "partial",
  "invoice_amount": 7.00,
  "total_paid": 3.00,
  "amount_remaining": 4.00,
  "payment_count": 1,
  "payments": [{ "amount": 3.00, "debtor_name": "John Smith" }],
  "message": "We received €3.00 of your €7.00 payment. Remaining balance: €4.00."
}

Response — Overpayment

If the customer sends more than the invoice amount, the order is confirmed but we flag the overpayment. A refund will be processed minus a €1.00 processing fee.

{
  "success": true,
  "status": "overpaid",
  "paid_at": "2026-03-31 10:05:12",
  "invoice_amount": 5.00,
  "total_paid": 8.00,
  "overpaid_amount": 3.00,
  "refund_fee": 1.00,
  "refund_net": 2.00,
  "message": "Payment received! You overpaid by €3.00. A refund of €2.00 will be processed (€3.00 minus €1.00 processing fee)."
}

Response — Still Searching

{
  "success": true,
  "status": "pending",
  "message": "Payment not yet detected. Checking again...",
  "poll_count": 5,
  "max_polls": 60
}

Response — Timeout

{
  "success": true,
  "status": "timeout",
  "message": "Payment not detected after maximum attempts. Please contact support."
}
Partial Payment Flow: When you receive status: "partial", display the receipt and remaining balance to the customer. They send the remaining amount with the same reference number, click "I've Sent the Payment" again, and you call confirm_paid then resume polling. The system tracks all payments and confirms when the full amount is received.

Get Session

GET ?action=get_session&token=SESSION_TOKEN

Retrieve details about a checkout session including its current status.

Parameters

ParameterTypeDescription
tokenstringThe session_token from create_session REQUIRED

Response

{
  "success": true,
  "session_id": 42,
  "merchant_name": "Your Store Name",
  "amount": 49.99,
  "currency": "EUR",
  "status": "confirmed",
  "reference_number": "DP-260330-XA6HSX",
  "invoice_number": "INV-260330-04821",
  "paid_at": "2026-03-30 22:05:12"
}

Payment Status

GET ?action=payment_status&reference=DP-XXXXXX-XXXXXX

Check the payment status for a specific reference number. Requires API key authentication.

Headers

NameValue
X-Gateway-KeyYour merchant API key REQUIRED

Parameters

ParameterTypeDescription
referencestringThe reference number (e.g. DP-260330-XA6HSX) REQUIRED*
session_tokenstringOr use the session token instead REQUIRED*

* Provide either reference OR session_token

Response

{
  "success": true,
  "reference_number": "DP-260330-XA6HSX",
  "invoice_number": "INV-260330-04821",
  "amount": 49.99,
  "currency": "EUR",
  "status": "confirmed",
  "confirmed_at": "2026-03-30 22:05:12"
}

List Transactions

GET ?action=list_transactions

List all gateway transactions for your merchant account. Supports filtering by status and pagination.

Headers

NameValue
X-Gateway-KeyYour merchant API key REQUIRED

Parameters

ParameterTypeDescription
statusstringFilter: pending, polling, confirmed, failed, expired OPTIONAL
limitnumberResults per page (max 200). Default: 50 OPTIONAL
offsetnumberPagination offset. Default: 0 OPTIONAL

Response

{
  "success": true,
  "transactions": [
    {
      "reference_number": "DP-260330-XA6HSX",
      "amount": 49.99,
      "status": "confirmed",
      "confirmed_at": "2026-03-30 22:05:12"
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}

Webhook: Payment Confirmed

When a payment is confirmed, we send a POST request to your registered callback_url with the payment details.

Set your callback URL either when creating a session (via callback_url parameter) or contact us to set a default URL for all your sessions.

Webhook Payload

{
  "event": "payment.confirmed",
  "reference_number": "DP-260330-XA6HSX",
  "invoice_number": "INV-260330-04821",
  "merchant_order_id": "ORD-12345",
  "invoice_amount": 7.00,
  "amount_paid": 7.00,
  "amount_remaining": 0,
  "overpaid_amount": 0,
  "refund_amount": 0,
  "refund_fee": 0,
  "currency": "EUR",
  "paid_at": "2026-03-31 10:05:12",
  "session_token": "a1b2c3d4e5f6...",
  "customer_email": "john@example.com",
  "customer_name": "John Smith"
}
Overpayment example: If invoice_amount is 5.00 and amount_paid is 8.00, the webhook will include overpaid_amount: 3.00, refund_fee: 1.00, and refund_amount: 2.00. The order is still confirmed — the refund is handled separately.
merchant_order_id is YOUR order number that you passed when creating the session. Use it to match the payment confirmation back to the order in your system — no need to track our reference numbers if you don't want to.

Expected Response

Return a 200 status code to acknowledge receipt. If we don't get a 200, we'll flag the notification as undelivered.

PHP Example

<?php
$payload = json_decode(file_get_contents('php://input'), true);

if ($payload['event'] === 'payment.confirmed') {
    $orderId = $payload['merchant_order_id'];  // YOUR order number
    $ref     = $payload['reference_number'];   // Our reference (DP-XXXXXX-XXXXXX)
    $amount  = $payload['amount'];
    $paidAt  = $payload['paid_at'];
    $email   = $payload['customer_email'];

    // Match to your order and mark as paid
    $db->query("UPDATE orders SET status = 'paid', paid_at = '$paidAt' WHERE order_id = '$orderId'");

    // Send confirmation email to customer
    // Trigger fulfillment / shipping

    error_log("Order $orderId paid: €$amount (ref: $ref)");
}

http_response_code(200);
echo json_encode(['received' => true]);

Session & Transaction Statuses

StatusDescription
pendingSession created, customer hasn't reached checkout yet
invoicedCustomer is on the checkout page, invoice + reference generated
pollingCustomer clicked "I've Sent the Payment" — we're checking ConnectPay
partialPayment received but less than invoice amount — waiting for remaining balance
confirmedFull payment received and verified ✓
overpaidPayment received but more than invoice amount — refund will be processed (minus €1 fee)
failedPayment not detected after maximum polling attempts
expiredSession expired before payment was made

Error Handling

All errors return a JSON object with success: false and an error message:

{
  "success": false,
  "error": "Missing API key"
}
HTTP CodeMeaning
400Bad request — missing or invalid parameters
401Unauthorized — invalid or missing API key
404Not found — session or transaction doesn't exist

Testing & Environments

Every merchant account starts in staging mode. This lets you integrate and test the full payment flow using ConnectPay's staging environment before going live with real money.

Staging vs Production

FeatureStagingProduction
ConnectPay APIapi-stage.connectpay.comapi.connectpay.com
Real moneyNo — test transactions onlyYes — real EUR transfers
IBANStaging IBAN (provided during onboarding)Production IBAN
API KeySame key — environment is set on your merchant accountSame key
WebhookFires normally — test your endpointFires normally
How it works: Your API key is the same for both environments. When you're onboarded, your merchant account is set to staging. Once you've tested successfully, contact us and we'll flip your account to production. The create_session response includes an environment field so you always know which mode you're in.

Integration Checklist — Staging

Test Accounts for Staging

Use these pre-funded test IBANs to simulate payments in the staging environment. Send EUR from either account to the staging custodial IBAN with the reference number from your checkout session.

Account NameIBANBICCurrencyBalance
Bank Has No Money LT923740020074597273 CNPALT21XXX EUR €100.00
Bank Has Money LT223740020032524104 CNPALT21XXX EUR €10,000.00
How to test: Create a checkout session via the API, then send a SEPA transfer from one of these test accounts to your staging custodial IBAN using the reference number. The system will detect the payment and confirm the session — just like production, but with test money.
Note: Test account balances are shared across all staging merchants. Use small amounts (€1–€5) for testing. Balances reset periodically.

Integration Checklist

Going Live

Demo Store: Visit /checkout/ to see a working example of the full checkout flow — from product selection to payment confirmation. View source to see how it integrates.

Create Refund

Initiate a full or partial refund for a completed payment. A €1 processing fee is deducted automatically.

POST /api/gateway/gateway.php?action=create_refund
ParameterTypeDescription
api_keystring requiredYour merchant API key
referencestring requiredOriginal payment reference number
amountnumber requiredRefund amount (must be ≤ original payment amount)
reasonstring optionalReason for refund

Response:

{
  "success": true,
  "refund_id": 42,
  "reference_number": "R7A3F2B1",
  "amount": 25.00,
  "processing_fee": 1.00,
  "status": "pending"
}

Send Refund

Execute a pending refund via SEPA transfer to the customer's IBAN. Calls ConnectPay's outbound payment API.

POST /api/gateway/gateway.php?action=send_refund
ParameterTypeDescription
api_keystring requiredYour merchant API key
refund_idinteger requiredRefund ID from create_refund
debtor_ibanstring requiredCustomer's IBAN to send refund to
debtor_namestring requiredCustomer's name on the bank account

List Refunds

GET /api/gateway/gateway.php?action=list_refunds&api_key=KEY

Returns all refunds for the authenticated merchant. Optionally filter by reference or status.

Settlement Report

Get an aggregated settlement report for a date range — gross volume, refunds, fees, and net settlement amount with daily breakdown.

POST /api/gateway/gateway.php?action=settlement_report
ParameterTypeDescription
api_keystring requiredYour merchant API key
date_fromstring requiredStart date (YYYY-MM-DD)
date_tostring requiredEnd date (YYYY-MM-DD)

Response includes: gross_volume, total_refunds, total_fees, net_settlement, daily_breakdown array, and transaction_count.

Dashboard

GET /api/gateway/gateway.php?action=dashboard&api_key=KEY

Returns merchant dashboard KPIs: today's volume, this month's volume, all-time volume, success rate, average transaction, 7-day trend, and recent transactions.

Recurring Billing — Overview

The recurring billing system sends periodic payment reminders to customers via SMS and/or email. Each cycle generates a new reference number and a link back to the merchant's checkout page. The customer must voluntarily initiate each payment — this is not a direct debit.

1
Customer opts into recurring at checkout (or merchant creates schedule via API)
2
System stores order: items, amount, frequency, customer contact info
3
Cron job runs every 15 min — finds due schedules, generates new reference
4
Sends SMS (Twilio) and/or email (Gmail SMTP) with payment link
5
Customer clicks link → merchant checkout → pays with new reference
6
System detects payment → marks cycle paid → schedules next cycle

Base URL:

https://www.maxafi.com/api/recurring.php

Authentication: Same gateway merchant API key via X-Api-Key header or api_key parameter.

Create Schedule

POST /api/recurring.php
ParameterTypeDescription
actionstring requiredcreate_schedule
customer_namestring requiredCustomer's full name
customer_emailstringEmail for payment link delivery
customer_phonestringPhone with country code (e.g. +4712345678) for SMS
delivery_methodstringemail, sms, or both (default: email)
frequencystring requiredweekly, biweekly, bimonthly, monthly
amountnumber requiredPayment amount per cycle (before discount)
discount_percentnumberRecurring discount (e.g. 5 for 5% off)
currencystringCurrency code (default: EUR)
order_itemsarrayJSON array of cart items: [{"name":"...", "qty":1, "price":99}]
order_descriptionstringDescription shown to customer
payment_urlstringYour checkout URL — customer is sent here each cycle
start_datestringFirst billing date (YYYY-MM-DD, default: tomorrow)
total_cyclesintegerMax cycles (0 = unlimited)

Example:

curl -X POST https://www.maxafi.com/api/recurring.php \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "create_schedule",
    "customer_name": "John Smith",
    "customer_email": "john@example.com",
    "customer_phone": "+4712345678",
    "delivery_method": "both",
    "frequency": "monthly",
    "amount": 99.00,
    "discount_percent": 5,
    "currency": "EUR",
    "order_items": [{"name": "Premium Plan", "qty": 1, "price": 99}],
    "payment_url": "https://merchant-site.com/pay"
  }'

Response:

{
  "success": true,
  "schedule_id": 7,
  "amount": 94.05,
  "original_amount": 99.00,
  "discount_percent": 5,
  "frequency": "monthly",
  "next_billing_date": "2026-04-03"
}

List Schedules

GET /api/recurring.php?action=list_schedules&api_key=KEY

Returns all recurring schedules for the merchant. Optionally filter by status (active, paused, cancelled, completed).

Update Schedule

POST /api/recurring.php

Update a schedule: pause, resume, cancel, change amount or frequency.

ParameterTypeDescription
actionstringupdate_schedule
schedule_idinteger requiredSchedule to update
statusstringactive, paused, cancelled
amountnumberNew amount per cycle
frequencystringNew frequency
next_billing_datestringOverride next billing date (YYYY-MM-DD)

Recurring — Configuration

Configure Twilio (SMS) and Gmail SMTP (email) credentials for payment notifications. Stored securely in the database.

POST /api/recurring.php
ParameterTypeDescription
actionstringset_config
twilio_sidstringTwilio Account SID
twilio_tokenstringTwilio Auth Token
twilio_phonestringTwilio phone number (platform default)
smtp_userstringGmail address for sending
smtp_passstringGmail App Password
smtp_from_namestringSender display name (default: Dapit Payments)
Per-Merchant Override: Each merchant can have their own SMS phone and email sender configured on their gateway_merchants record via the fields sms_phone, email_from, and email_from_name. If set, these override the platform defaults.