Skip to content

Bank transfers — Confirming a transfer ​

A payment made by bank transfer is confirmed or rejected once someone has checked the bank statement. Besides the dashboard, that verdict can come over the API. It matters most for platform teams: in a client's project the money lands in the client's account, so you show the payment.awaiting_verification event to your client in your own system and send their answer back here.

Both project tokens and team tokens work; the token needs write (a read token gets 403). The verdict is recorded in the name of the token's user.

Flow ​

Customer clicks "I've transferred"
  │ payment.awaiting_verification webhook (data.object = the payment)
  ▼
Your system shows the reference and amount to your client
  │ the client checks the statement
  ▼
POST .../bank-transfer/confirm  or  .../bank-transfer/reject
  │
  ▼
checkout.completed / invoice.paid  (when confirmed)

In a client's project Byl also emails the client's contact address a time-limited link that needs no login, where the client can answer "Received" / "Not received". The API is for teams that want this in their own UI; whichever path decides first wins, the next gets 409.

The Payment object ​

The response has the same shape as the data.object of the payment.awaiting_verification webhook: id, status (pending, paid, failed), amount, reference, bank_name, account_number, claimed_at, expires_at, payable (type, id, url, status, plus number for invoices), customer_email, phone_number, is_test, created_at.

Confirm ​

POST /v1/projects/:project_id/payments/:payment_id/bank-transfer/confirm
ParameterTypeRequiredDescription
received_amountNumbertrueThe amount that actually arrived.
acknowledge_mismatchBooleanfalsetrue to count the payment as paid although the amounts differ.

Once confirmed the payment is paid and the regular checkout.completed / invoice.paid webhook, notifications and receipt follow.

Example request

shell
BYL_PROJECT_ID="your project ID"
BYL_TOKEN="your API token"

curl -X POST https://byl.mn/api/v1/projects/$BYL_PROJECT_ID/payments/9d2f6c1e-1b1c-4a2e-9c7d-2d1f4a8b9e10/bank-transfer/confirm \
    -H "Authorization: Bearer $BYL_TOKEN" \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json' \
    -d '{ "received_amount": 45000 }'

Example response

json
{
  "data": {
    "id": "9d2f6c1e-1b1c-4a2e-9c7d-2d1f4a8b9e10",
    "project_id": 1,
    "status": "paid",
    "driver": "bank_transfer",
    "amount": 45000,
    "description": "Checkout - 231",
    "reference": "482913",
    "bank_name": "Khan Bank",
    "account_number": "5012345678",
    "claimed_at": "2026-08-27T09:30:00.000000Z",
    "expires_at": "2026-08-30T09:30:00.000000Z",
    "payable": {
      "type": "checkout",
      "id": 231,
      "url": "https://byl.mn/h/checkout/231/…",
      "status": "complete"
    },
    "customer_email": "[email protected]",
    "phone_number": "99112233",
    "is_test": false,
    "created_at": "2026-08-27T09:20:00.000000Z"
  }
}

Reject ​

POST /v1/projects/:project_id/payments/:payment_id/bank-transfer/reject
ParameterTypeRequiredDescription
reasonStringtrueUp to 255 characters. Shown to the customer.

The payment becomes failed and the checkout reopens, so the customer can transfer again with a new reference or pay another way. When we know the customer's email, they are emailed the reason.

Errors ​

StatuserrorMeaning
409already_settledThe transfer was already confirmed, rejected, or has expired.
422not_bank_transferThe payment is not a bank transfer.
422—Validation: a differing amount without acknowledge_mismatch gives errors.acknowledge_mismatch.
403—A read token, or a token of another team or project.
404—The payment is not in this project.