Verified against: Public OpenAPI 2.0.0

Hosted payments

Create a checkout

Create checkout from your backend, then redirect the customer to Moneybag's hosted payment experience.

POST/api/v2/payments/checkout
Create a merchant-scoped sandbox checkout.

Generate and persist a unique order_id before calling Moneybag. The reference below is rendered from the reviewed public artifact, including nested customer, shipping, line-item, metadata, and EMI fields.

Rendering diagram…
The merchant backend creates and verifies checkout. The browser only follows hosted redirects and never receives the merchant API key.
Text alternative

The merchant backend creates and verifies checkout. The browser only follows hosted redirects and never receives the merchant API key.

Do not fulfill from the customer redirect. Continue with payment verification.

Collection Dashboard attribution

Add the optional, top-level checkout_source field to identify where a payment originates. The values are case-sensitive:

  • WEBSITE_CHECKOUT → Website Checkout: a customer starts checkout on your website, and your backend creates the session.
  • API_INTEGRATION → API Integration: your application or automated integration workflow initiates checkout, such as a backend billing workflow.

Any other value, including different casing, causes a request validation error. Omit the field if you are unsure which source applies.

All checkout requests still come from your backend. Choose the value for the payment's origin; calling the checkout API does not automatically make a website payment an API Integration payment.

For a native mobile app that starts checkout through your backend, use API_INTEGRATION. If a WebView loads your merchant website and the customer starts checkout there, use WEBSITE_CHECKOUT. Opening Moneybag's hosted payment page in a WebView does not change the original source.

The API Lab checkout preset includes API_INTEGRATION. When adapting it for website payments, change that value to WEBSITE_CHECKOUT; you can also omit the field to keep checkout unclassified.

For example, a website checkout request can include:

{
  "order_id": "ORDER-WEBSITE-10001",
  "currency": "BDT",
  "order_amount": "100.00",
  "order_description": "Website order",
  "checkout_source": "WEBSITE_CHECKOUT",
  "success_url": "https://merchant.example/payments/success",
  "cancel_url": "https://merchant.example/payments/cancel",
  "fail_url": "https://merchant.example/payments/failure",
  "customer": {
    "name": "Sandbox Customer",
    "email": "sandbox@example.com",
    "phone": "+8801700000000"
  }
}

Send checkout_source alongside order_id, not inside metadata. Metadata such as source or platform does not set the dashboard channel.

Existing integrations can omit the field or send null. These payments appear as Unclassified Checkout; their payment method and successful collection amount are still recorded. Adding the field attributes newly created sessions. Older transactions are not relabeled, and a reused session retains its original channel through retries and redirects.

API reference

POST/api/v2/payments/checkout

Checkout

Checkout API This endpoint initiates the payment process for a merchant order. It creates a payment session, processes the initial payment request, and returns a redirect URL to the payment gateway. The merchant must provide a valid API key in the X-Merchant-API-Key header. Args: order_req: Order request data merchant_key: Merchant API key info Returns: CheckoutResponse: Response with checkout details and redirect URL Raises: HTTPException: For any validation or processing errors

Operation ID
checkout_api_v2_payments_checkout_post
Environment
https://sandbox.api.moneybag.com.bd (Moneybag sandbox)
Authentication
X-Merchant-API-Key — Sandbox merchant API key. Live keys are rejected.

Parameters

No path or query parameters.

Request body

Required application/json body using OrderRequest.

FieldTypeRequiredConstraints and meaning
cancel_urlstringYesmaximum length 255
Callback URL if user cancels the transaction
checkout_sourcestring | nullNoone of WEBSITE_CHECKOUT, API_INTEGRATION
Optional collection attribution for authenticated website or API checkout.
currencystringYes—
Three-letter currency code (e.g., BDT, USD, EUR)
customerCustomerYes—
customer.addressstring | nullNomaximum length 200
Customer's address
customer.citystring | nullNomaximum length 50
Customer's city
customer.countrystring | nullNomaximum length 50
Customer's country
customer.emailstringYesformat email; maximum length 100
Customer's email address
customer.metadataobject | nullNo—
Additional customer-specific data
customer.namestringYesmaximum length 255
Customer's full name
customer.phonestringYes—
Customer's phone number
customer.postcodestring | nullNomaximum length 20
Customer's postal code
customer.statestring | nullNo—
Customer's state/division/province (e.g. 'Dhaka', 'Chattogram'). Optional. Forwarded to processors that require a billing division; supplying a real value improves AVS accuracy and therefore risk and chargeback outcomes.
fail_urlstringYesmaximum length 255
Callback URL if payment failure occurs
ipn_urlstring | nullNo—
Instant Payment Notification URL
metadataobject | nullNo—
Additional order-specific data
order_amountnumber | stringYespattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
Transaction amount between 10.00 and 1000000.00 BDT
order_descriptionstringYesmaximum length 255
Description of the order
order_idstringYesminimum length 10; maximum length 36
Unique transaction ID to identify your order
order_itemsOrderItem[] | nullNo—
List of items in the order
order_items[].convenience_feenumber | string | nullNopattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
Convenience fee (decimal value)
order_items[].discount_amountnumber | string | nullNopattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
Discount amount (decimal value)
order_items[].metadataobject | nullNo—
Additional product-specific data
order_items[].net_amountnumber | string | nullNopattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
Net amount after adding VAT and fees, subtracting discounts
order_items[].product_categorystring | nullNomaximum length 100
Product category (e.g., Electronic, topup)
order_items[].product_namestring | nullNomaximum length 255
Product name
order_items[].quantityinteger | nullNo—
Product quantity
order_items[].skustring | nullNo—
Product SKU
order_items[].unit_pricenumber | string | nullNopattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
Unit price of the product
order_items[].vatnumber | string | nullNopattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
VAT amount (decimal value)
payment_infoPaymentInfo | nullNo—
Payment-related information
payment_info.currency_conversionbooleanNodefault false
Whether currency conversion is applied
payment_info.emi_configuration_idstring | nullNo—
Selected EMI configuration ID (if customer selected specific EMI option)
payment_info.emi_payment_idstring | nullNo—
Selected merchant payment service for EMI payment. Accepts the public UUID.
payment_info.requires_emibooleanNodefault false
Whether EMI payment options should be shown
shippingShipping | nullNo—
Shipping information
shipping.addressstringWhen parent is present—
Shipping address line 1
shipping.citystringWhen parent is present—
Shipping city
shipping.countrystringWhen parent is present—
Shipping country
shipping.metadataobject | nullNo—
Additional shipping-specific data
shipping.namestringWhen parent is present—
Shipping recipient's full name
shipping.postcodestringWhen parent is present—
Shipping postal code
shipping.statestring | nullNo—
Shipping state/province
success_urlstringYesmaximum length 255
Callback URL after successful payment

Sandbox example

Set the merchant key and replace resource identifiers with values created in your sandbox workspace.

curl --request POST "https://sandbox.api.moneybag.com.bd/api/v2/payments/checkout" \
  --header "X-Merchant-API-Key: $MONEYBAG_MERCHANT_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "cancel_url": "https://merchant.example/cancel-url",
    "currency": "BDT",
    "customer": {
      "email": "sandbox.customer@example.com",
      "name": "Sandbox example",
      "phone": "+8801700000000"
    },
    "fail_url": "https://merchant.example/fail-url",
    "order_amount": 100,
    "order_description": "Sandbox API example",
    "order_id": "ORDER-1001",
    "success_url": "https://merchant.example/success-url"
  }'

Run this reviewed operation in the API Lab →

Responses

200 Successful Response

Content type: application/json. Schema: PaymentResponses.

FieldTypeRequiredConstraints and meaning
dataCheckoutResponse | SessionResponse | ProcessResponse | VerificationResponse | InvoiceDetailsResponse | CancelResponse | CheckoutResponse | SessionResponse | ProcessResponse | VerificationResponse | InvoiceDetailsResponse | CancelResponse[] | nullNo—
data<CheckoutResponse>.checkout_urlstringWhen parent is present—
data<CheckoutResponse>.expires_atstringWhen parent is present—
data<CheckoutResponse>.session_idstringWhen parent is present—
data<SessionResponse>.bleedingbooleanNodefault false
Whether merchant pays service charges (bleeding)
data<SessionResponse>.business_namestring | nullNo—
data<SessionResponse>.can_return_to_merchantbooleanNodefault false
Whether the checkout may offer a 'return to merchant' action — true when the merchant's stored return URL passes moneybag.utils.redirect_guard. Deliberately a BOOLEAN, not the URL: this response is fetched by the hosted checkout from the browser, so any URL here would be readable by page scripts, devtools, error reporters and anyone holding the checkout link, and merchant cancel URLs routinely carry order tokens in their query string. The destination itself is never serialised — the checkout links to GET /payments/sessions/{session_id}/return, which resolves and validates it server-side at click time.
data<SessionResponse>.currencystringWhen parent is present—
data<SessionResponse>.customerobject | nullNo—
data<SessionResponse>.emi_checkout_idstring | nullNo—
Selected EMI configuration UUID if pre-selected
data<SessionResponse>.emi_fee_bleedingbooleanNodefault false
Whether merchant pays EMI fees (emi_fee_bleeding)
data<SessionResponse>.emi_payment_optionsobject[] | nullNo—
EMI payment options with calculations
data<SessionResponse>.expires_atstringWhen parent is present—
data<SessionResponse>.merchant_logostring | nullNo—
data<SessionResponse>.order_amountstringWhen parent is presentpattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
data<SessionResponse>.order_descriptionstring | nullNo—
data<SessionResponse>.order_idstringWhen parent is present—
data<SessionResponse>.payment_optionsobject[]When parent is present—
data<SessionResponse>.requires_emibooleanNodefault false
Whether EMI payment options are available
data<SessionResponse>.selected_emi_configurationSelectedEMIConfiguration | nullNo—
Selected EMI configuration with emi_configuration_id and service_id
data<SessionResponse>.selected_emi_configuration.emi_configuration_idstringWhen parent is present—
Selected EMI configuration ID
data<SessionResponse>.selected_emi_configuration.service_idstring | nullNo—
Public merchant payment service UUID, matches payment_options[].service_id
data<SessionResponse>.session_idstringWhen parent is present—
data<SessionResponse>.statusstringWhen parent is present—
data<ProcessResponse>.metaobject | nullNo—
data<ProcessResponse>.redirect_urlstring | nullNoformat uri; minimum length 1
data<ProcessResponse>.transaction_idstringWhen parent is present—
data<VerificationResponse>.amountstringWhen parent is presentpattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
data<VerificationResponse>.charge_amountstringWhen parent is presentpattern ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
data<VerificationResponse>.currencystringWhen parent is present—
data<VerificationResponse>.customerCustomerWhen parent is present—
data<VerificationResponse>.customer.addressstring | nullNomaximum length 200
Customer's address
data<VerificationResponse>.customer.citystring | nullNomaximum length 50
Customer's city
data<VerificationResponse>.customer.countrystring | nullNomaximum length 50
Customer's country
data<VerificationResponse>.customer.emailstringWhen parent is presentformat email; maximum length 100
Customer's email address
data<VerificationResponse>.customer.metadataobject | nullNo—
Additional customer-specific data
data<VerificationResponse>.customer.namestringWhen parent is presentmaximum length 255
Customer's full name
data<VerificationResponse>.customer.phonestringWhen parent is present—
Customer's phone number
data<VerificationResponse>.customer.postcodestring | nullNomaximum length 20
Customer's postal code
data<VerificationResponse>.customer.statestring | nullNo—
Customer's state/division/province (e.g. 'Dhaka', 'Chattogram'). Optional. Forwarded to processors that require a billing division; supplying a real value improves AVS accuracy and therefore risk and chargeback outcomes.
data<VerificationResponse>.order_idstringWhen parent is present—
data<VerificationResponse>.payment_methodstringWhen parent is present—
data<VerificationResponse>.payment_reference_idstringWhen parent is present—
data<VerificationResponse>.statusstringWhen parent is present—
data<VerificationResponse>.transaction_idstringWhen parent is present—
data<VerificationResponse>.verifiedbooleanWhen parent is present—
data<InvoiceDetailsResponse>.all_totalnumberWhen parent is present—
data<InvoiceDetailsResponse>.business_namestringWhen parent is present—
data<InvoiceDetailsResponse>.customerobject | nullWhen parent is present—
data<InvoiceDetailsResponse>.due_datestring | nullWhen parent is present—
data<InvoiceDetailsResponse>.gross_discountnumberWhen parent is present—
data<InvoiceDetailsResponse>.invoice_idstringWhen parent is present—
data<InvoiceDetailsResponse>.invoice_itemsobject[]When parent is present—
data<InvoiceDetailsResponse>.invoice_statusstringWhen parent is present—
data<InvoiceDetailsResponse>.invoice_typestring | nullNo—
data<InvoiceDetailsResponse>.merchant_logostring | nullNo—
data<InvoiceDetailsResponse>.payable_amountnumberWhen parent is present—
data<InvoiceDetailsResponse>.uuidstringWhen parent is present—
data<CancelResponse>.order_idstringWhen parent is present—
data<CancelResponse>.redirect_urlstringWhen parent is present—
data<CancelResponse>.session_idstringWhen parent is present—
data<CancelResponse>.statusstringNodefault "CANCELLED"
messagestring | nullNo—
metaobject | nullNo—
successbooleanYes—

422 Validation Error

Content type: application/json. Schema: HTTPValidationError.

FieldTypeRequiredConstraints and meaning
detailValidationError[]No—
detail[].locstring | integer[]When parent is present—
detail[].msgstringWhen parent is present—
detail[].typestringWhen parent is present—
OpenAPI 2.0.0 · operation checkout_api_v2_payments_checkout_post · contract digest 094720c953e300d050a4861f0c64528522ac5879f954e6c2073a5bca00bfb878