Biftpaydocs

Direct debit

With direct debit, a customer gives your business permission (a mandate) to debit their bank account. You then debit it whenever a payment is due: membership dues, school fees, loan repayments. It's for Nigerian bank accounts, in naira.

1. Ask the customer for a mandate#

bash
curl https://sandbox.api.biftpay.com/v1/mandates \
  -H "Authorization: Bearer bp_test_..." \
  -H "Idempotency-Key: mandate-member-17" \
  -H "Content-Type: application/json" \
  -d '{ "customer_email": "ada@example.com", "customer_name": "Ada Obi", "callback_url": "https://example.com/mandate-done" }'

The mandate starts pending, with an authorization_url. Send the customer there (redirect them, or share the link). On that page they choose their bank, confirm who they are and approve debits. Some banks also ask for a small verification transfer. Afterwards they're sent to your callback_url, if you gave one.

2. Wait until it's active#

The customer's bank confirms the mandate, usually within a day. Biftpay checks pending mandates every few minutes; to check one now, call POST /v1/mandates/{id}/refresh.

StatusMeaning
pendingWaiting for the customer to approve it, or for their bank to confirm.
activeYou can debit it. bank_name, account_name and account_number_last4 show which account.
canceledYou canceled it. No more debits.
failedNot approved within 7 days (failure_reason: "expired"), or refused. Ask for a new one.

3. Debit it#

bash
curl https://sandbox.api.biftpay.com/v1/mandates/{id}/charge \
  -H "Authorization: Bearer bp_test_..." \
  -H "Idempotency-Key: dues-member-17-2026-10" \
  -H "Content-Type: application/json" \
  -d '{ "amount": 500000, "currency": "NGN", "description": "October dues" }'

Each debit is a payment: the response is the payment intent, it shows in your payments, and you get payment_intent.successful or payment_intent.failed. The mandate's id is in its metadata.mandate. A bank debit can take a while, so the payment may stay processing before the bank confirms; wait for the webhook rather than the response.

  • You bear the fee: it comes out of the amount, at your direct debit price.
  • Retry safely: the same Idempotency-Key never debits twice.
  • Refunds work as for any payment.

Cancel#

POST /v1/mandates/{id}/cancel stops a mandate. Debits already started still finish. To debit the customer again later, ask for a new mandate.

In the dashboard#

Under Direct debit: ask a customer for a mandate (you get the link to send them), check pending ones, debit active ones and cancel them.

Errors#

CodeMeaning
direct_debit_not_availableDirect debit isn't switched on for your account. Contact Biftpay.
mandate_refusedThe provider refused the request; the message says why.
mandate_not_activeThe mandate is still pending, or was canceled.
no_priceDirect debit isn't priced for your account yet. Contact Biftpay.