Error Codes
Complete reference for all QPay V2 API error codes, HTTP status codes, and SDK error handling patterns. Use this page to diagnose issues and implement robust error handling in your application.
Error Response Format
When the QPay V2 API returns an error, the response body contains a JSON object with two fields:
{
"error_code": "INVOICE_NOTFOUND",
"message": "Invoice not found"
}The HTTP status code is included in the response headers. Every SDK parses this into a structured error type that exposes:
| Property | Description |
|---|---|
| Status Code | The HTTP status code (e.g., 401, 404, 422) |
| Error Code | The QPay error code string (e.g., INVOICE_NOTFOUND) |
| Message | A human-readable description of the error |
| Raw Body | The full response body as a string, for debugging |
HTTP Status Codes
QPay V2 uses standard HTTP status codes to indicate the result of an API request.
| Status | Meaning | When It Happens |
|---|---|---|
| 200 | OK | Request succeeded |
| 400 | Bad Request | Invalid request body, missing required fields, or invalid field values |
| 401 | Unauthorized | Missing or invalid authentication credentials, expired token |
| 403 | Forbidden | Valid credentials but insufficient permissions for this operation |
| 404 | Not Found | The requested resource (invoice, payment, merchant) does not exist |
| 409 | Conflict | Resource state conflict (e.g., invoice already paid, already cancelled) |
| 422 | Unprocessable Entity | Request is well-formed but contains semantic errors (e.g., invalid amount) |
| 500 | Internal Server Error | Something went wrong on QPay’s side — retry after a short delay |
| 502 | Bad Gateway | QPay upstream service is temporarily unavailable |
| 503 | Service Unavailable | QPay API is temporarily down for maintenance |
SDK Error Handling
Every SDK provides a structured error type and named constants for all QPay error codes. Here is how to handle errors in each language:
Go
import qpay "github.com/qpay-sdk/qpay-go"
invoice, err := client.CreateSimpleInvoice(ctx, req)
if err != nil {
if qErr, ok := qpay.IsQPayError(err); ok {
fmt.Printf("Status: %d\n", qErr.StatusCode)
fmt.Printf("Code: %s\n", qErr.Code)
fmt.Printf("Message: %s\n", qErr.Message)
switch qErr.Code {
case qpay.ErrAuthenticationFailed:
// Handle authentication failure
case qpay.ErrInvoiceCodeInvalid:
// Handle invalid invoice code
case qpay.ErrInvalidAmount:
// Handle invalid amount
default:
// Handle other errors
}
} else {
// Network error, timeout, etc.
fmt.Printf("Error: %v\n", err)
}
}JavaScript / TypeScript
import { QPayError, isQPayError, ERR_INVOICE_NOT_FOUND } from 'qpay-js';
try {
await client.createSimpleInvoice(request);
} catch (err) {
if (isQPayError(err)) {
console.log(err.statusCode); // 404
console.log(err.code); // "INVOICE_NOTFOUND"
console.log(err.message); // Human-readable message
console.log(err.rawBody); // Raw response for debugging
if (err.code === ERR_INVOICE_NOT_FOUND) {
// Handle specific error
}
}
}Python
from qpay import QPayError, ERR_INVOICE_NOT_FOUND
try:
client.create_simple_invoice(request)
except QPayError as e:
print(f"Status: {e.status_code}") # 404
print(f"Code: {e.code}") # "INVOICE_NOTFOUND"
print(f"Message: {e.message}") # Human-readable message
print(f"Raw: {e.raw_body}") # Raw response
if e.code == ERR_INVOICE_NOT_FOUND:
# Handle specific error
passPHP
use QPay\Exceptions\QPayException;
try {
$client->createSimpleInvoice($request);
} catch (QPayException $e) {
echo $e->statusCode; // 404
echo $e->errorCode; // "INVOICE_NOTFOUND"
echo $e->errorMessage; // Human-readable message
echo $e->rawBody; // Raw response
match ($e->errorCode) {
QPayException::INVOICE_NOTFOUND => handleNotFound(),
QPayException::AUTHENTICATION_FAILED => handleAuthError(),
default => handleUnknown($e),
};
}Authentication Errors
These errors occur during token acquisition (POST /v2/auth/token) or when using an expired/invalid token.
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
AUTHENTICATION_FAILED | 401 | Invalid username or password | Verify your QPAY_USERNAME and QPAY_PASSWORD credentials |
NO_CREDENDIALS | 401 | Missing credentials in the request | Ensure the Basic Auth header is present. SDKs handle this automatically |
PERMISSION_DENIED | 403 | Valid credentials but insufficient permissions | Contact QPay support to verify your account permissions |
[!NOTE] All SDKs handle token management automatically. If you receive
AUTHENTICATION_FAILED, the issue is with your merchant credentials, not your code.
Invoice Errors
These errors relate to creating, retrieving, or cancelling invoices.
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
INVOICE_NOTFOUND | 404 | Invoice does not exist | Verify the invoice ID. The invoice may have been deleted |
INVOICE_PAID | 409 | Invoice has already been paid | Paid invoices cannot be cancelled or modified. Create a refund instead |
INVOICE_ALREADY_CANCELED | 409 | Invoice was already cancelled | No action needed — the invoice is already in the desired state |
INVOICE_CODE_INVALID | 400 | Invalid invoice code | Verify your QPAY_INVOICE_CODE. Contact QPay if you need a new code |
INVOICE_CODE_REGISTERED | 409 | Invoice code is already registered | Use your existing invoice code or request a new one from QPay |
INVOICE_LINE_REQUIRED | 400 | Invoice lines are required | Ebarimt invoices must include at least one line item in the lines array |
INVOICE_RECEIVER_DATA_REQUIRED | 400 | Invoice receiver data is missing | Provide receiver data in the invoice request |
INVOICE_RECEIVER_DATA_EMAIL_REQUIRED | 400 | Receiver email is missing | Include the receiver’s email address |
INVOICE_RECEIVER_DATA_PHONE_REQUIRED | 400 | Receiver phone is missing | Include the receiver’s phone number |
INVOICE_RECEIVER_DATA_ADDRESS_REQUIRED | 400 | Receiver address is missing | Include the receiver’s address |
Payment Errors
These errors relate to checking, cancelling, or refunding payments.
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
PAYMENT_NOTFOUND | 404 | Payment does not exist | Verify the payment ID. Use checkPayment with the invoice ID instead |
PAYMENT_NOT_PAID | 409 | Payment has not been completed | The customer has not yet completed the payment. Wait and check again |
PAYMENT_ALREADY_CANCELED | 409 | Payment was already cancelled | No action needed — the payment is already cancelled |
Amount Errors
These errors are returned when the invoice amount is invalid.
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
INVALID_AMOUNT | 422 | Invalid payment amount | Amount must be a positive number. Check for zero, negative, or non-numeric values |
MIN_AMOUNT_ERR | 422 | Amount is below the minimum | Increase the amount to meet QPay’s minimum payment threshold |
MAX_AMOUNT_ERR | 422 | Amount exceeds the maximum | Decrease the amount or split into multiple invoices |
Merchant Errors
These errors relate to merchant account status and registration.
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
MERCHANT_NOTFOUND | 404 | Merchant not found | Verify your credentials. Your account may not exist or may have been removed |
MERCHANT_INACTIVE | 403 | Merchant account is inactive | Contact QPay support to reactivate your account |
MERCHANT_ALREADY_REGISTERED | 409 | Merchant is already registered | Use your existing merchant credentials |
Ebarimt (Tax Receipt) Errors
These errors relate to creating or cancelling electronic tax receipts (ebarimt).
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
EBARIMT_NOT_REGISTERED | 400 | Ebarimt service not registered | Register for ebarimt service with QPay before creating tax receipts |
EBARIMT_CANCEL_NOTSUPPERDED | 400 | Ebarimt cancellation not supported | This specific receipt type cannot be cancelled |
EBARIMT_QR_CODE_INVALID | 400 | Invalid ebarimt QR code | The QR code data is malformed or expired |
Customer Errors
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
CUSTOMER_NOTFOUND | 404 | Customer not found | Verify the customer identifier |
CUSTOMER_DUPLICATE | 409 | Duplicate customer entry | A customer with this identifier already exists |
CUSTOMER_REGISTER_INVALID | 400 | Invalid customer register number | Check the register number format (Mongolian national register) |
Client Errors
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
CLIENT_NOTFOUND | 404 | API client not found | Verify your API client configuration |
CLIENT_USERNAME_DUPLICATED | 409 | Client username already taken | Choose a different username |
Account and Terminal Errors
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
BANK_ACCOUNT_NOTFOUND | 404 | Bank account not found | Verify the bank account is linked to your merchant |
ACCOUNT_BANK_DUPLICATED | 409 | Duplicate bank account | This bank account is already registered |
ACCOUNT_SELECTION_INVALID | 400 | Invalid account selection | Select a valid bank account for the operation |
CARD_TERMINAL_NOTFOUND | 404 | Card terminal not found | Verify the terminal ID |
P2P_TERMINAL_NOTFOUND | 404 | P2P terminal not found | Verify the P2P terminal ID |
QR and Transaction Errors
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
QRCODE_NOTFOUND | 404 | QR code not found | The QR code does not exist or has expired |
QRCODE_USED | 409 | QR code has already been used | Generate a new QR code by creating a new invoice |
QRACCOUNT_NOTFOUND | 404 | QR account not found | Verify the QR account configuration |
QRACCOUNT_INACTIVE | 403 | QR account is inactive | Contact QPay to activate the QR account |
TRANSACTION_NOT_APPROVED | 422 | Transaction was not approved | The payment was declined by the bank. Customer should try again |
TRANSACTION_REQUIRED | 400 | Transaction data is required | Include the required transaction data in the request |
Other Errors
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
OBJECT_DATA_ERROR | 400 | Invalid object data | Check the request body for malformed fields |
INVALID_OBJECT_TYPE | 400 | Invalid object type | Use "INVOICE" for invoice-related queries |
INPUT_NOTFOUND | 404 | Input not found | Verify the input identifier |
INPUT_CODE_REGISTERED | 409 | Input code already registered | Use the existing code or request a new one |
INFORM_NOTFOUND | 404 | Information not found | The requested information does not exist |
SENDER_BRANCH_DATA_REQUIRED | 400 | Sender branch data is missing | Include the sender branch information |
TAX_LINE_REQUIRED | 400 | Tax line items are required | Add at least one line item for tax calculation |
TAX_PRODUCT_CODE_REQUIRED | 400 | Tax product code is missing | Each line item must include a product code |
BANK_MCC_ALREADY_ADDED | 409 | Bank MCC code already added | This MCC code is already associated |
BANK_MCC_NOT_FOUND | 404 | Bank MCC code not found | Verify the MCC code is valid |
MCC_NOTFOUND | 404 | MCC code not found | The MCC (Merchant Category Code) does not exist |
Full Error Code Reference
A complete alphabetical listing of all QPay V2 error codes with their categories.
| Error Code | Category | HTTP Status |
|---|---|---|
ACCOUNT_BANK_DUPLICATED | Account | 409 |
ACCOUNT_SELECTION_INVALID | Account | 400 |
AUTHENTICATION_FAILED | Authentication | 401 |
BANK_ACCOUNT_NOTFOUND | Account | 404 |
BANK_MCC_ALREADY_ADDED | Other | 409 |
BANK_MCC_NOT_FOUND | Other | 404 |
CARD_TERMINAL_NOTFOUND | Terminal | 404 |
CLIENT_NOTFOUND | Client | 404 |
CLIENT_USERNAME_DUPLICATED | Client | 409 |
CUSTOMER_DUPLICATE | Customer | 409 |
CUSTOMER_NOTFOUND | Customer | 404 |
CUSTOMER_REGISTER_INVALID | Customer | 400 |
EBARIMT_CANCEL_NOTSUPPERDED | Ebarimt | 400 |
EBARIMT_NOT_REGISTERED | Ebarimt | 400 |
EBARIMT_QR_CODE_INVALID | Ebarimt | 400 |
INFORM_NOTFOUND | Other | 404 |
INPUT_CODE_REGISTERED | Other | 409 |
INPUT_NOTFOUND | Other | 404 |
INVALID_AMOUNT | Amount | 422 |
INVALID_OBJECT_TYPE | Other | 400 |
INVOICE_ALREADY_CANCELED | Invoice | 409 |
INVOICE_CODE_INVALID | Invoice | 400 |
INVOICE_CODE_REGISTERED | Invoice | 409 |
INVOICE_LINE_REQUIRED | Invoice | 400 |
INVOICE_NOTFOUND | Invoice | 404 |
INVOICE_PAID | Invoice | 409 |
INVOICE_RECEIVER_DATA_ADDRESS_REQUIRED | Invoice | 400 |
INVOICE_RECEIVER_DATA_EMAIL_REQUIRED | Invoice | 400 |
INVOICE_RECEIVER_DATA_PHONE_REQUIRED | Invoice | 400 |
INVOICE_RECEIVER_DATA_REQUIRED | Invoice | 400 |
MAX_AMOUNT_ERR | Amount | 422 |
MCC_NOTFOUND | Other | 404 |
MERCHANT_ALREADY_REGISTERED | Merchant | 409 |
MERCHANT_INACTIVE | Merchant | 403 |
MERCHANT_NOTFOUND | Merchant | 404 |
MIN_AMOUNT_ERR | Amount | 422 |
NO_CREDENDIALS | Authentication | 401 |
OBJECT_DATA_ERROR | Other | 400 |
P2P_TERMINAL_NOTFOUND | Terminal | 404 |
PAYMENT_ALREADY_CANCELED | Payment | 409 |
PAYMENT_NOT_PAID | Payment | 409 |
PAYMENT_NOTFOUND | Payment | 404 |
PERMISSION_DENIED | Authentication | 403 |
QRACCOUNT_INACTIVE | QR | 403 |
QRACCOUNT_NOTFOUND | QR | 404 |
QRCODE_NOTFOUND | QR | 404 |
QRCODE_USED | QR | 409 |
SENDER_BRANCH_DATA_REQUIRED | Other | 400 |
TAX_LINE_REQUIRED | Tax | 400 |
TAX_PRODUCT_CODE_REQUIRED | Tax | 400 |
TRANSACTION_NOT_APPROVED | Transaction | 422 |
TRANSACTION_REQUIRED | Transaction | 400 |
Troubleshooting
”AUTHENTICATION_FAILED” on every request
- Verify
QPAY_USERNAMEandQPAY_PASSWORDare correct. - Make sure you are using the right base URL — sandbox credentials do not work on production, and vice versa.
- Check that your merchant account is active by contacting QPay support.
”INVOICE_CODE_INVALID” when creating invoices
- Confirm your
QPAY_INVOICE_CODEvalue matches exactly what QPay provided. - Invoice codes are case-sensitive.
- If you recently received new credentials, your old invoice code may be invalid.
”INVALID_AMOUNT” errors
- Amount must be a positive number greater than zero.
- Amount must meet QPay’s minimum threshold (varies by merchant configuration).
- Do not send string values for the amount field — use a numeric type.
Timeout or network errors
- Check your internet connection and firewall rules.
- QPay API endpoints must be reachable from your server.
- Consider increasing the HTTP client timeout (default is usually 30 seconds).
- If the error persists, check QPay’s status or contact support.
Token expiration issues
All SDKs handle token refresh automatically. If you are still seeing 401 errors:
- Ensure your SDK is at the latest version.
- Check that your system clock is synchronized (token expiry checks rely on accurate time).
- If using manual token management, call
refreshToken()before the access token expires.
Callback (webhook) not received
- Verify your
QPAY_CALLBACK_URLis a publicly accessible HTTPS URL. - Check that your server returns a 200 status code within a reasonable time.
- Ensure your firewall allows incoming POST requests from QPay’s servers.
- Use
checkPaymentas a fallback — always verify payment status server-side.