EasyPay / ePay.bg — API Reference¶
ePay.bg / EasyPay — 21 operations across 11 areas, from the official docs (kb.epay.bg). WEB API endpoints take a base64 ENCODED payload + CHECKSUM. Interactive: the API page; full prose docs + diagrams: Full Docs.
Online Payment (1)¶
POST /¶
Card payment via ePay page (credit_paydirect)
POST to https://www.epay.bg/ with PAGE=credit_paydirect. Customer is redirected to ePay's payment page. Payload fields (encoded into ENCODED): see OnlinePaymentPayload model.
Payment via EasyPay (3)¶
GET /ezp/pay_bill.cgi¶
Simulate EasyPay-office payment (demo only) Demo only. Fires STATUS=PAID to the merchant notification URL.
A success token here can settle nothing. Handed an IDN belonging to the OTHER application root, this endpoint returned STATUS=OK IDN= MERCHANT= AMOUNT= DESCR= — success, every field empty, nothing paid (observed 2026-09-08). A caller that reads STATUS=OK and stops will mark an instalment paid against money nobody handed over. Require IDN to come back, and to match the code that was asked about.
Served on the LEGACY root; no counterpart was found under /xdev/web.
| Param | In | Required |
|---|---|---|
ACTION |
query | True |
IDN |
query | True |
GET /ezp/reg_bill.cgi¶
Register EasyPay payment (get 10-digit code)
Returns a 10-digit EasyPay code payable at an EasyPay office or ATM. Payload fields (encoded into ENCODED): see EasyPayBillPayload model.
TWO APPLICATION ROOTS, SEPARATE MERCHANT REGISTRIES. demo.epay.bg runs a legacy application at the bare host and a current one under /xdev/web, each with its own merchant registry (established by live call, 2026-09-08). A merchant registered on one root is UNKNOWN on the other, and the error does not say so: the legacy MIN against the current update endpoint answers EPLG_NO_MERCHANT, which is also what a BAD CHECKSUM answers, so the response does not diagnose the request. The current MIN against legacy /ezp/reg_bill.cgi answers 'EMETHOD: Не е намерен валиден търговец!'. Pick a root and use it for registration, invalidation and the portal alike. NOT VERIFIED: whether production splits the same way between www.epay.bg/ezp/... and www.epay.bg/v3main.
Success is reported in more than one way. The documented token is SYS_CODE=OK; a registration answers with the code itself (IDN=<10 digits>), and the live host answers STATUS=OK from the update endpoint. Accept all three — treating only the documented one as success reads every successful invalidation as a failure.
INVOICE collisions are silent. Re-submitting a consumed INVOICE returns the already-bound IDN — pending or paid — and reports success. On a SHARED merchant record two parties can therefore both believe they registered an obligation when only one did. Partition the INVOICE namespace between parties; do not rely on an error.
| Param | In | Required |
|---|---|---|
ENCODED |
query | True |
CHECKSUM |
query | True |
GET /paylogin/request/update¶
Extend or invalidate a registered payment
Re-registers an existing INVOICE with a new EXP_TIME. A PAST-DATED EXP_TIME invalidates the code — which is how a live code is killed when the loan is settled through another rail.
Served on the CURRENT root only (/xdev/web/paylogin/request/update); the legacy application does not serve it at all.
Errors worth telling apart: EPLG_NO_MERCHANT means wrong root or wrong merchant — and is ALSO what an invalid CHECKSUM returns; BILL_NOT_FOUND means the merchant resolved and the invoice did not, which is good news about the credentials. Success is STATUS=OK.
NOT VERIFIED: whether invalidation is terminal. Re-extending after a past-dated EXP_TIME returned OK; it was not confirmed the code becomes payable again.
| Param | In | Required |
|---|---|---|
ENCODED |
query | True |
CHECKSUM |
query | True |
Preauthorization (1)¶
POST /v3main/¶
Preauthorization: register, finalize or reverse Three phases share this endpoint (distinguished by the ENCODED payload): register (PreauthRegisterPayload), finalize (PreauthFinalizePayload), reverse (PreauthReversePayload).
Change expiring time (1)¶
GET /v3main¶
Change the expiry time of an obligation
Payload fields (encoded into ENCODED): see ChangeExpiryPayload model.
| Param | In | Required |
|---|---|---|
ENCODED |
query | True |
CHECKSUM |
query | True |
Bank transfer (1)¶
GET /send/send_vnbel.cgi¶
Order a bank transfer
Payload fields (encoded into ENCODED): see BankTransferPayload model.
| Param | In | Required |
|---|---|---|
ENCODED |
query | True |
CHECKSUM |
query | True |
Deposit slip (1)¶
GET /ezp/reg_vnbel.cgi¶
Register a deposit-slip payment request
Payload fields (encoded into ENCODED): see DepositSlipPayload model.
| Param | In | Required |
|---|---|---|
ENCODED |
query | True |
CHECKSUM |
query | True |
Money send (3)¶
GET /ezp/pay_money_send.cgi¶
Simulate an EasyPay-office cash payout (demo only)
Demo only. Simulates the recipient collecting the cash transfer at an EasyPay office; fires the STATUS=PAID notification (with STAN/BCODE=000000) to the merchant's registered notification URL, same as a real payout would.
| Param | In | Required |
|---|---|---|
SYS_CODE |
query | True |
GET /ezp/send.cgi¶
Money send via EasyPay (cash pickup)
Order a cash payout collectable by a named recipient at any EasyPay office (loan-disbursement use case). Payload fields (encoded into ENCODED): see MoneySendEasyPayPayload model. On payout, ePay POSTs a notification to your registered URL with STATUS=PAID (or STATUS=EXPIRED if never collected); STAN/BCODE are always 000000 for money-send. Full flow: see the Money Send (disbursement) page. Demo payout simulation: /ezp/pay_money_send.cgi.
| Param | In | Required |
|---|---|---|
ENCODED |
query | True |
CHECKSUM |
query | True |
GET /send/send.cgi¶
Money send via ePay.bg
Payload fields (encoded into ENCODED): see MoneySendEpayPayload model.
| Param | In | Required |
|---|---|---|
ENCODED |
query | True |
CHECKSUM |
query | True |
Payment notification (1)¶
POST /{merchant_notify_url}¶
Payment notification (merchant-hosted)
ePay POSTs here on payment status change. Verify CHECKSUM and the RSA SIGNATURE. Respond with a line per invoice: INVOICE=STATUS (OK/ERR/NO). Payload fields (encoded into ENCODED): see NotificationPayload model.
| Param | In | Required |
|---|---|---|
merchant_notify_url |
path | True |
Billing API (2)¶
GET /pay/confirm¶
Payment / deposit notification (merchant-hosted)
| Param | In | Required |
|---|---|---|
IDN |
query | True |
MERCHANTID |
query | True |
TID |
query | True |
DATE |
query | True |
TOTAL |
query | True |
TYPE |
query | True |
INVOICES |
query | False |
CHECKSUM |
query | True |
GET /pay/init¶
Obligation / deposit check (merchant-hosted) STATUS codes: 00=OK; 13=Invalid amount; 14=Invalid IDN; 62=No obligation; 80=Temporarily unavailable; 93=Invalid checksum; 94=Duplicate; 96=General error
| Param | In | Required |
|---|---|---|
IDN |
query | True |
MERCHANTID |
query | True |
TYPE |
query | True |
TID |
query | False |
TOTAL |
query | False |
CHECKSUM |
query | True |
One Touch API (6)¶
GET /xdev/api/api/code/get¶
Get pairing code / register device
| Param | In | Required |
|---|---|---|
APPID |
query | True |
DEVICEID |
query | True |
KEY |
query | True |
UTYPE |
query | False |
DEVICE_NAME |
query | False |
BRAND |
query | False |
OS |
query | False |
MODEL |
query | False |
OS_VERSION |
query | False |
PHONE |
query | False |
GET /xdev/api/api/token/get¶
Get access token from code
| Param | In | Required |
|---|---|---|
APPID |
query | True |
DEVICEID |
query | True |
CODE |
query | True |
GET /xdev/api/api/token/invalidate¶
Invalidate a token
| Param | In | Required |
|---|---|---|
APPID |
query | True |
DEVICEID |
query | True |
TOKEN |
query | True |
GET /xdev/api/payment/check¶
Check a payment before sending
| Param | In | Required |
|---|---|---|
APPID |
query | True |
DEVICEID |
query | True |
TOKEN |
query | True |
TYPE |
query | True |
ID |
query | True |
AMOUNT |
query | True |
RCPT |
query | True |
RCPT_TYPE |
query | True |
DESCRIPTION |
query | False |
REASON |
query | False |
PINS |
query | False |
SHOW |
query | False |
GET /xdev/api/payment/init¶
Initialize a payment
| Param | In | Required |
|---|---|---|
APPID |
query | True |
DEVICEID |
query | True |
TOKEN |
query | True |
TYPE |
query | True |
EXP |
query | False |
GET /xdev/api/payment/send/status¶
Send payment / get status
| Param | In | Required |
|---|---|---|
APPID |
query | True |
DEVICEID |
query | True |
TOKEN |
query | True |
TYPE |
query | True |
ID |
query | True |
AMOUNT |
query | True |
RCPT |
query | True |
RCPT_TYPE |
query | True |
DESCRIPTION |
query | False |
REASON |
query | False |
PINS |
query | False |
SHOW |
query | False |
One Touch No Reg API (1)¶
GET /xdev/api/api/payment/noreg/send/status¶
No-registration payment / status CHECKSUM = hmac_sha1_hex over the sorted KEY VALUE lines with the app SECRET.
| Param | In | Required |
|---|---|---|
APPID |
query | True |
DEVICEID |
query | True |
ID |
query | True |
AMOUNT |
query | True |
RCPT |
query | True |
RCPT_TYPE |
query | True |
CHECKSUM |
query | True |
DESCRIPTION |
query | False |
REASON |
query | False |
SAVECARD |
query | False |