Checkout API
The Checkout endpoint initiates a payment session for a customer order and returns a checkout URL where the customer can complete the payment
Endpoint Details
Endpoint:
POST /payments/checkout
Base URLs:
- Sandbox:
https://sandbox.api.moneybag.com.bd/api/v2 - Production:
https://api.moneybag.com.bd/api/v2
Authentication
All requests require authentication via API key in the header:
X-Merchant-API-Key: <your_merchant_api_key>Payment Flow
Understanding the complete payment flow helps you implement a robust integration:
Integration Steps
- Create Checkout Session - Call
/payments/checkoutwith customer and order details - Redirect Customer - Send customer to the returned
checkout_url - Customer Pays - Customer completes payment on Moneybag's secure payment page
- Handle Redirect - Customer returns to your
success_url,fail_url, orcancel_url - Verify Payment - Always verify using
/payments/verify/{transaction_id}before fulfilling - Fulfill Order - Complete order fulfillment after successful verification
Redirect URLs and Transaction Status
After payment completion, Moneybag redirects the customer to one of your specified URLs based on the transaction outcome.
Redirect URL Format
https://yourdomain.com/payment/{status}?transaction_id={transaction_id}&status={STATUS}&order_id={order_id}Example Redirects
# Successful payment
https://example.com/payment/success?transaction_id=txn0370d893a26a46e4961a833aae4b020f&status=SUCCESS&order_id=30003251021181530
# Failed payment
https://example.com/payment/fail?transaction_id=txn0370d893a26a46e4961a833aae4b020f&status=FAILED&order_id=30003251021181530
# Cancelled payment
https://example.com/payment/cancel?transaction_id=txn0370d893a26a46e4961a833aae4b020f&status=CANCELLED&order_id=30003251021181530Redirect URL Types
| Redirect URL | Transaction Status | Description |
|---|---|---|
success_url | SUCCESS | Customer is redirected here when payment is completed successfully |
fail_url | FAILED | Customer is redirected here when payment fails (e.g., insufficient funds, declined card) |
cancel_url | CANCELLED | Customer is redirected here when they manually cancel the payment process |
Query Parameters
Moneybag appends the following query parameters to your redirect URLs:
| Parameter | Type | Description |
|---|---|---|
transaction_id | string | Unique transaction identifier (e.g., txn0370d893a26a46e4961a833aae4b020f) |
status | string | Transaction status (SUCCESS, FAILED, or CANCELLED) |
order_id | string | Your order ID from the checkout request (e.g., 30003251021181530) |
Important Security Notes
• Never trust redirect URLs alone - always verify payment server-side
• Use /payments/verify/{transaction_id} endpoint to confirm payment status
• Redirect URLs can be manipulated by users - treat them as untrusted input
• Only fulfill orders after successful verification via the API
Request
Headers
| Header | Value | Required |
|---|---|---|
| X-Merchant-API-Key | Your merchant API key | Yes |
| Content-Type | application/json | Yes |
Request Body
{
"order_id": "order123321",
"currency": "BDT",
"order_amount": "1280.00",
"order_description": "Online purchase of electronics",
"success_url": "https://yourdomain.com/payment/success",
"cancel_url": "https://yourdomain.com/payment/cancel",
"fail_url": "https://yourdomain.com/payment/fail",
"ipn_url": "https://yourdomain.com/payment/ipn",
"customer": {
"name": "John Doe",
"email": "john.doe@example.com",
"address": "123 Main Street",
"city": "Dhaka",
"postcode": "1000",
"country": "Bangladesh",
"phone": "+8801700000000"
},
"order_items": [
{
"sku": "PROD001",
"net_amount": "1300.00"
}
],
"shipping": {
"name": "John Doe",
"address": "123 Main Street",
"city": "Dhaka",
"postcode": "1000",
"country": "Bangladesh"
},
"metadata": {
"source": "web",
"session_id": "SESSION12345",
"user_agent": "Mozilla/5.0",
"ip_address": "192.168.1.1",
"platform": "web"
},
"payment_info": {
"is_recurring": false,
"installments": 0,
"currency_conversion": false,
"allowed_payment_methods": ["card", "mobile_banking"],
"requires_emi": false
}
}Request Parameters
Root Level Fields
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
| order_id | string | Yes | Unique transaction ID to identify your order | Max 30 chars |
| currency | string | Yes | Three-letter currency code | Must match ^[A-Z]{3}$ |
| order_amount | decimal | Yes | Transaction amount | Between 10.00 and 500000.00 BDT |
| order_description | string | No | Description of the order | |
| success_url | string | Yes | Callback URL after successful payment | Max 255 chars, must be HTTPS |
| cancel_url | string | Yes | Callback URL if user cancels | Max 255 chars, must be HTTPS |
| fail_url | string | Yes | Callback URL if payment fails | Max 255 chars, must be HTTPS |
| ipn_url | string | No | Instant Payment Notification URL | Must be HTTPS |
| customer | object | Yes | Customer information | See Customer Object |
| shipping | object | No | Shipping information | See Shipping Object |
| order_items | array | No | List of items in the order | See OrderItem Object |
| payment_info | object | No | Payment-related information | See PaymentInfo Object |
| metadata | object | No | Additional order-specific data |
Customer Object
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Customer full name |
| string | Yes | Customer email address | |
| address | string | Yes | Customer address |
| city | string | Yes | Customer city |
| postcode | string | Yes | Customer postal code |
| country | string | Yes | Customer country |
| phone | string | Yes | Customer phone number |
Shipping Object
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Recipient's full name |
| address | string | Yes | Shipping address |
| city | string | Yes | Shipping city |
| state | string | No | Shipping state/province |
| postcode | string | Yes | Shipping postal code |
| country | string | Yes | Shipping country |
| metadata | object | No | Additional shipping data |
OrderItem Object
| Field | Type | Required | Description |
|---|---|---|---|
| sku | string | No | Product SKU |
| product_name | string | No | Product name |
| product_category | string | No | Product category |
| quantity | integer | No | Product quantity |
| unit_price | decimal | No | Unit price of the product |
| vat | decimal | No | VAT amount |
| convenience_fee | decimal | No | Convenience fee |
| discount_amount | decimal | No | Discount amount |
| net_amount | decimal | No | Net amount after calculations |
| metadata | object | No | Additional product data |
PaymentInfo Object
| Field | Type | Required | Description |
|---|---|---|---|
| is_recurring | boolean | No | Whether this is a recurring payment |
| installments | integer | No | Number of installments if applicable |
| currency_conversion | boolean | No | Whether currency conversion is applied |
| allowed_payment_methods | array | Yes | List of allowed payment methods |
| requires_emi | boolean | No | Whether EMI is required |
Response
Success Response
HTTP Status: 200 OK
{
"success": true,
"data": {
"checkout_url": "https://payment.moneybag.com.bd/moneybag-landing?sessionId=ps1234567890",
"session_id": "ps1234567890",
"expires_at": "2025-05-19T15:00:00Z"
},
"message": "Checkout session created"
}Response Fields
| Field | Type | Description |
|---|---|---|
| checkout_url | string | URL to redirect customer for payment |
| session_id | string | Unique session ID for the payment |
| expires_at | datetime | Expiry date/time of the session (ISO format) |
Error Response
HTTP Status: 400/401/403/500
{
"success": false,
"error": {
"code": "INVALID_REQUEST",
"message": "The order_amount must be between 10.00 and 500000.00",
"field": "order_amount"
}
}Try in Playground
Common Issues
Invalid Amount Error
- Ensure amount is between 10.00 and 500000.00 BDT
- Use string format with exactly 2 decimal places
Missing Customer Data
- All customer fields are required
- Phone number can be with or without country code (e.g.,
01700000000or+8801700000000)
URL Validation Failed
- Use HTTPS for all callback URLs
- Ensure URLs are publicly accessible
Verify Payment
After the customer completes payment, you should verify the transaction status before fulfilling the order.
Verify Endpoint
Endpoint:
GET /payments/verify/{transaction_id}
cURL Example:
curl -X GET \
"https://sandbox.api.moneybag.com.bd/api/v2/payments/verify/txn1234567899" \
-H "X-Merchant-API-Key: your_merchant_api_key"Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| transaction_id | string | Yes | The unique transaction ID received from Moneybag after payment processing |
Verify Response
HTTP Status: 200 OK
{
"success": true,
"message": "Payment verification details retrieved",
"data": {
"transaction_id": "txn160725223bbd495baee2b3d581b41c6b",
"order_id": "PLLL1430b34abcb",
"verified": true,
"status": "SUCCESS",
"amount": "5.0000",
"currency": "BDT",
"charge_amount": "0.0750",
"payment_method": "BKASH",
"payment_reference_id": "TR0011HdlhWek1759048979602",
"customer": {
"name": "John Doe",
"email": "john.doe@example.com",
"phone": "+8801700000000",
"address": "123 Main Street",
"city": "Dhaka",
"postcode": "1000",
"country": "Bangladesh",
"metadata": {}
}
},
"meta": {
"timestamp": "2025-11-30T13:36:41.868679",
"status_code": 200
}
}Payment Status Values
| Status | Description |
|---|---|
| SUCCESS | Payment completed successfully |
| FAILED | Payment failed |
| PENDING | Payment is being processed |
| CANCELLED | Payment was cancelled by user |
| EXPIRED | Payment session expired |
| REFUNDED | Payment has been refunded |
When to Verify
1. Immediate Verification
Verify payment immediately after customer returns to your site:
- Capture the
transaction_idfrom the redirect URL query parameters - Call the verify endpoint before showing success page
- Only process order fulfillment after successful verification
- Display appropriate message based on verification result
2. Webhook + Verification
Best practice: Use webhooks with verification for reliability:
- Set up a webhook endpoint to receive payment notifications
- When webhook is triggered, extract the
transaction_id - Always verify the payment status via API before processing
- Respond with 200 OK to acknowledge webhook receipt
- This provides redundancy if customer closes browser before redirect
Verification Best Practices
1. Always Verify Before Fulfillment
Never fulfill orders based solely on redirect URLs:
- ❌ Bad Practice: Trusting redirect URLs directly without verification
- ❌ Bad Practice: Fulfilling orders based on query parameters alone
- ✅ Good Practice: Always call verify API before order fulfillment
- ✅ Good Practice: Check both
verifiedflag andstatusfield in response
2. Handle All Status Types
Properly handle different payment statuses:
- SUCCESS: Fulfill order and send confirmation
- PENDING: Mark order as pending, wait for final status
- FAILED: Cancel order and notify customer
- CANCELLED: Handle user cancellation, restore cart if applicable
- EXPIRED: Payment session timed out
- REFUNDED: Payment has been refunded
3. Implement Idempotency
Prevent duplicate order processing:
- Check if transaction has already been processed before fulfilling
- Store processed transaction IDs in your database
- Return existing result if transaction already processed
- Mark transaction as processed atomically to prevent race conditions
- Use database transactions or locks to ensure single processing
Related Resources
- Webhooks - Real-time notifications
- Subscriptions - Recurring payments