Native Payment API
Use the Native Payment API when you want full control of the client experience (web or mobile) and prefer not to use the Checkout SDK. Your client or backend collects a payment payload and sends it to Ottu to process the payment for a given session_id.
A payment payload can be:
Wallet payment data (e.g., Apple Pay paymentData, Google Pay paymentMethodData) — typically encrypted by the wallet.
Gateway token / network token (card-on-file or one-click use cases) — not necessarily encrypted.
Ottu processes the payload with the configured gateway and returns a normalized callback result.
Apple Pay or Google Pay buttons are rendered and managed by you.
Existing tokenization has already been implemented and needs to be used to charge with a gateway token.
Granular, SDK-less control of the UX is required, while Ottu’s orchestration and gateway integrations are still leveraged.
Send a post request to the payment service endpoint with payment session_id, then the payment service collected token to perform the payment process.
Quick Apple Pay Example (cURL)
curl -X POST "https://sandbox.ottu.net/b/pbl/v2/payment/apple-pay/" \
-H "Authorization: Api-Key GYj5Na8H.29g9hqNjm11nORQMa2WiZwIBQQ49MdAL" \
-H "Content-Type: application/json" \
-d '{
"payload": {
"pg_code": "apple-pay",
"session_id": "str",
"payload": {
"paymentData": {
...
}
} // the apple payment token without modifications
}
}'Ottu securely processes the Apple Pay request and returns a unified success response once the payment is completed.
{
"result": "success",
"message": "successful payment",
"pg_response": {}
}Use the response values to reconcile the payment in your backend and update your order state.
Continue with the sections below to learn more about response fields, error handling, and webhook integration.
Supported Methods
Private API Key (Server-Only)
Public API Key (Client-Safe)
Basic Authentication (Server-Only)
For detailed information on authentication procedures, please refer to the Authentication section.
The Private API Key must never be exposed in any client-side application.
Client → Ottu (Public API Key )
The client collects the wallet or tokenized payment payload and calls the Native Payment API directly using the Public API Key.
The client receives the API callback response.
If the call is made from the client side, the backend must be synchronized with the payment result by ensuring that one of the following actions is performed:
The API response is forwarded to the backend, or
The Payment Status (Inquiry) API is called by the backend after the client confirms that the payment has been completed.

Client → Backend → Ottu (Private API Key– Recommended)
The client sends the payment payload to Backend
Backend calls Ottu native payment API
Backend receive payment response callback
Backend process callback response and notify client side with payment status

A valid session_id obtained from the Checkout API.
A Merchant Gateway ID (MID) with the payment service activated and properly configured in Ottu.
To complete the setup, the Service Setup section for the specific payment service being implemented must be followed, such as:
If multiple gateways are configured, always include the pg_code corresponding to the MID that has the target payment service enabled.
Example:
If a transaction has knet and mpgs pg_code but only knet supports Apple Pay, you must send
pg_code: knet when calling the Apple Pay API.
Apple Pay is configured on the client side (iOS / web).
The encrypted
paymentDataobject is collected from Apple Pay.The payload, along with the session_id, is sent to the Ottu Payment API.
Ottu processes via the configured Apple Pay gateway and returns a unified result (
succeeded,failed).
Do not modify the Apple Pay payload. Any change invalidates token decryption.
Include pg_code if multiple gateways are configured.
Allows merchants to submit an Apple Pay payment directly via server-to-server integration. This endpoint requires private key authentication and expects a valid Apple Pay token structure in the request payload under payload.
Typical use case: The merchant collects the Apple Pay token on their frontend and sends it to this endpoint along with session and amount information.
The unique pg_code used for this payment instrument.
A unique identifier for the payment transaction (session).
POST /b/pbl/v2/payment/apple-pay/ HTTP/1.1
Host: sandbox.ottu.net
Authorization: Basic username:password
Content-Type: application/json
Accept: */*
Content-Length: 320
{
"payload": {
"paymentData": {
"version": "text",
"data": "text",
"signature": "text",
"header": {
"ephemeralPublicKey": "text",
"wrappedKey": "text",
"publicKeyHash": "text",
"transactionId": "text"
}
},
"paymentMethod": {
"displayName": "text",
"network": "text",
"type": "text"
},
"transactionIdentifier": "text"
},
"pg_code": null,
"session_id": "text"
}{
"pg_params": {
"auth_code": null,
"card_type": null,
"card_holder": null,
"cardholder_email": null,
"card_expiry_month": null,
"card_expiry_year": null,
"full_card_expiry": null,
"card_number": null,
"card_issuer": null,
"ref": null,
"result": null,
"track_id": null,
"post_date": null,
"transaction_id": null,
"payment_id": null,
"pg_message": null,
"receipt_no": null,
"transaction_no": null,
"decision": null,
"card_expiry": null,
"card_details": null,
"dcc_payer_amount": null,
"dcc_payer_currency": null,
"dcc_payer_exchange_rate": null,
"rrn": null
},
"agreement": {
"id": "text",
"amount_variability": "fixed",
"start_date": "2025-11-19",
"expiry_date": "2025-11-19",
"max_amount_per_cycle": "text",
"cycle_interval_days": 1,
"total_cycles": 1,
"frequency": "irregular",
"type": "recurring",
"seller": {
"name": "text",
"short_name": "text",
"category_code": "text"
}
},
"amount": "text",
"amount_details": {
"currency_code": "text",
"amount": "text",
"total": "text",
"fee": "text",
"exchange_rate": "text"
},
"capture_delivery_address": true,
"capture_delivery_location": true,
"card_acceptance_criteria": {
"min_expiry_time": 1
},
"currency_code": "text",
"customer_address_city": "text",
"customer_address_country": "text",
"customer_address_line1": "text",
"customer_address_line2": "text",
"customer_birthdate": null,
"customer_address_postal_code": "text",
"customer_address_state": "text",
"customer_email": "text",
"customer_first_name": "text",
"customer_id": "text",
"customer_last_name": "text",
"customer_phone": "text",
"extra": null,
"fee": "text",
"gateway_account": "text",
"gateway_name": "text",
"gateway_response": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"initiator": {
"id": 1,
"first_name": "text",
"last_name": "text",
"username": "text",
"email": "name@gmail.com",
"phone": "text"
},
"is_sandbox": true,
"message": "text",
"order_no": null,
"paid_amount": 1,
"payment_type": "one_off",
"reference_number": "text",
"refunded_amount": 1,
"remaining_amount": 1,
"result": "pending",
"session_id": "text",
"settled_amount": 1,
"signature": "text",
"state": "text",
"token": {
"brand": null,
"customer_id": "text",
"cvv_required": true,
"expiry_month": "text",
"expiry_year": "text",
"is_expired": true,
"is_preferred": true,
"name_on_card": null,
"number": null,
"pg_code": "text",
"pg_name": "knet",
"token": "text",
"agreements": null
},
"transaction_log_id": null,
"timestamp_utc": "2025-11-19T20:47:23.658Z",
"transactions": [
{
"amount": "text",
"currency_code": "text",
"order_no": null,
"session_id": "text",
"state": "paid"
}
],
"voided_amount": 1
}Google Pay is configured on the client side (Android / web).
The wallet payment payload (
paymentMethodData,email,addresses, etc.) is collected.The payload, along with the session_id, is sent to the Ottu Native Payment API.
Ottu processes through the configured gateway and returns a normalized response.
Do not modify the Google Pay payload. Any change invalidates token decryption.
Include pg_code if multiple gateways are configured.
If the response contains type: "iframe", render it for 3D Secure authentication.Important:
Allows merchants to submit an Google Pay payment directly via server-to-server integration. This endpoint requires private key authentication and expects a valid Google Pay token structure in the request payload under payload.
Typical use case: The merchant collects the Google Pay token on their frontend and sends it to this endpoint along with session and amount information.
The unique pg_code used for this payment instrument.
A unique identifier for the payment transaction (session).
POST /b/pbl/v2/payment/google-pay/ HTTP/1.1
Host: sandbox.ottu.net
Authorization: Basic username:password
Content-Type: application/json
Accept: */*
Content-Length: 326
{
"payload": {
"apiVersion": 1,
"apiVersionMinor": 1,
"paymentMethodData": {
"type": "text",
"description": "text",
"info": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"tokenizationData": {
"ANY_ADDITIONAL_PROPERTY": "anything"
}
},
"email": "name@gmail.com",
"shippingAddress": {
"ANY_ADDITIONAL_PROPERTY": "anything"
}
},
"pg_code": null,
"session_id": "text"
}{
"pg_params": {
"auth_code": null,
"card_type": null,
"card_holder": null,
"cardholder_email": null,
"card_expiry_month": null,
"card_expiry_year": null,
"full_card_expiry": null,
"card_number": null,
"card_issuer": null,
"ref": null,
"result": null,
"track_id": null,
"post_date": null,
"transaction_id": null,
"payment_id": null,
"pg_message": null,
"receipt_no": null,
"transaction_no": null,
"decision": null,
"card_expiry": null,
"card_details": null,
"dcc_payer_amount": null,
"dcc_payer_currency": null,
"dcc_payer_exchange_rate": null,
"rrn": null
},
"agreement": {
"id": "text",
"amount_variability": "fixed",
"start_date": "2025-11-19",
"expiry_date": "2025-11-19",
"max_amount_per_cycle": "text",
"cycle_interval_days": 1,
"total_cycles": 1,
"frequency": "irregular",
"type": "recurring",
"seller": {
"name": "text",
"short_name": "text",
"category_code": "text"
}
},
"amount": "text",
"amount_details": {
"currency_code": "text",
"amount": "text",
"total": "text",
"fee": "text",
"exchange_rate": "text"
},
"capture_delivery_address": true,
"capture_delivery_location": true,
"card_acceptance_criteria": {
"min_expiry_time": 1
},
"currency_code": "text",
"customer_address_city": "text",
"customer_address_country": "text",
"customer_address_line1": "text",
"customer_address_line2": "text",
"customer_birthdate": null,
"customer_address_postal_code": "text",
"customer_address_state": "text",
"customer_email": "text",
"customer_first_name": "text",
"customer_id": "text",
"customer_last_name": "text",
"customer_phone": "text",
"extra": null,
"fee": "text",
"gateway_account": "text",
"gateway_name": "text",
"gateway_response": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"initiator": {
"id": 1,
"first_name": "text",
"last_name": "text",
"username": "text",
"email": "name@gmail.com",
"phone": "text"
},
"is_sandbox": true,
"message": "text",
"order_no": null,
"paid_amount": 1,
"payment_type": "one_off",
"reference_number": "text",
"refunded_amount": 1,
"remaining_amount": 1,
"result": "pending",
"session_id": "text",
"settled_amount": 1,
"signature": "text",
"state": "text",
"token": {
"brand": null,
"customer_id": "text",
"cvv_required": true,
"expiry_month": "text",
"expiry_year": "text",
"is_expired": true,
"is_preferred": true,
"name_on_card": null,
"number": null,
"pg_code": "text",
"pg_name": "knet",
"token": "text",
"agreements": null
},
"transaction_log_id": null,
"timestamp_utc": "2025-11-19T20:47:23.658Z",
"transactions": [
{
"amount": "text",
"currency_code": "text",
"order_no": null,
"session_id": "text",
"state": "paid"
}
],
"voided_amount": 1
}Ensure the token is active and usable for the merchant.
Use an existing session_id created via the Checkout API.
Send the token in the
tokenfield to Ottu.Ottu processes the payment with the configured gateway and returns the callback result.
Supports CIT (Cardholder Initiated) and MIT (Merchant Initiated) transactions.
This endpoint will take a session id and check for it's related payment if it's possible to be auto charged or not. if possible it will charge the payment and return the operation response. 📝 NOTE Optional fields may not be represented in response body.
Private API key to be provided in the format Api-Key <key>.
Api-Key vSUmxsXx.V81oYvOWFMcIywaOu57Utx6VSCmG11loAuto debit serializer should take session_id and consumer payment token then validate if session id is valid if session id is valid then validate if payment gateway supports auto debit if payment gateway supports auto debit then validate if payment gateway has implemented auto debit if payment gateway has implemented auto debit then charge the token and return charge response from client auto_debit method which should be implemented in client
A unique identifier for each payment transaction, used to maintain the session state during the payment process.
Use this field to provide the unique identifier of a saved customer card for processing a payment in the API request.
POST /b/pbl/v2/payment/auto-debit/ HTTP/1.1
Host: sandbox.ottu.net
Authorization: Api-Key vSUmxsXx.V81oYvOWFMcIywaOu57Utx6VSCmG11lo
Content-Type: application/json
Accept: */*
Content-Length: 36
{
"session_id": "text",
"token": "text"
}{
"pg_params": {
"auth_code": null,
"card_type": null,
"card_holder": null,
"cardholder_email": null,
"card_expiry_month": null,
"card_expiry_year": null,
"full_card_expiry": null,
"card_number": null,
"card_issuer": null,
"ref": null,
"result": null,
"track_id": null,
"post_date": null,
"transaction_id": null,
"payment_id": null,
"pg_message": null,
"receipt_no": null,
"transaction_no": null,
"decision": null,
"card_expiry": null,
"card_details": null,
"dcc_payer_amount": null,
"dcc_payer_currency": null,
"dcc_payer_exchange_rate": null,
"rrn": null
},
"agreement": {
"id": "text",
"amount_variability": "fixed",
"start_date": "2025-11-19",
"expiry_date": "2025-11-19",
"max_amount_per_cycle": "text",
"cycle_interval_days": 1,
"total_cycles": 1,
"frequency": "irregular",
"type": "recurring",
"seller": {
"name": "text",
"short_name": "text",
"category_code": "text"
}
},
"amount": "text",
"amount_details": {
"currency_code": "text",
"amount": "text",
"total": "text",
"fee": "text",
"exchange_rate": "text"
},
"capture_delivery_address": true,
"capture_delivery_location": true,
"card_acceptance_criteria": {
"min_expiry_time": 1
},
"currency_code": "text",
"customer_address_city": "text",
"customer_address_country": "text",
"customer_address_line1": "text",
"customer_address_line2": "text",
"customer_birthdate": null,
"customer_address_postal_code": "text",
"customer_address_state": "text",
"customer_email": "text",
"customer_first_name": "text",
"customer_id": "text",
"customer_last_name": "text",
"customer_phone": "text",
"extra": null,
"fee": "text",
"gateway_account": "text",
"gateway_name": "text",
"gateway_response": {
"ANY_ADDITIONAL_PROPERTY": "anything"
},
"initiator": {
"id": 1,
"first_name": "text",
"last_name": "text",
"username": "text",
"email": "name@gmail.com",
"phone": "text"
},
"is_sandbox": true,
"message": "text",
"order_no": null,
"paid_amount": 1,
"payment_type": "one_off",
"reference_number": "text",
"refunded_amount": 1,
"remaining_amount": 1,
"result": "pending",
"session_id": "text",
"settled_amount": 1,
"signature": "text",
"state": "text",
"token": {
"brand": null,
"customer_id": "text",
"cvv_required": true,
"expiry_month": "text",
"expiry_year": "text",
"is_expired": true,
"is_preferred": true,
"name_on_card": null,
"number": null,
"pg_code": "text",
"pg_name": "knet",
"token": "text",
"agreements": null
},
"transaction_log_id": null,
"timestamp_utc": "2025-11-19T20:47:23.658Z",
"transactions": [
{
"amount": "text",
"currency_code": "text",
"order_no": null,
"session_id": "text",
"state": "paid"
}
],
"voided_amount": 1
}1️ Can I call the Native Payment API directly from the client?
Yes, but only with the Public Key, and your backend must remain synchronized.
2️ Which model should I use in production?
Always prefer Client → Backend → Ottu using the Private Key.
3️How do I verify the payment result?
Use the Payment Status (Inquiry) API.
4️What if my transaction has multiple gateway codes?
Include the pg_code for the MID that has the corresponding payment service enabled (e.g., Apple Pay, Google Pay).
5️What happens if I modify wallet data?
The payment will fail — wallet tokens must be sent unmodified.
6️Can I charge saved tokens automatically?
Yes, use the Native Payment API for tokenized or recurring payments.
Last updated