Guides
Search documentation... ⌘K
API references

Pre-built forms (popup or embedded)

Embed our secure, pre-built payment forms directly into your existing checkout page. Perfect for customizing your user flow while we handle PCI compliance.

Account setup and configuration

Before you can integrate, you must set up your merchant environment. You’ll need the following:

  • Create a merchant account: Sign up and gain access to your merchant dashboard

  • Create an SDK installation: In your dashboard, under developer settings, create a new SDK installation for each website or mobile application you plan to deploy on. This process involves:

    • Choosing your platform (e.g., Web, iOS, Android).
    • Providing application details like your website domain or app bundle ID.
    • Selecting payment methods you want to offer on that platform (e.g., Card, PromptPay).
    • Configuring customer data to require (e.g., email address, mobile number).
  • Create a new API key: In your dashboard, under developer settings, create a new API key. Keep your API key secret. Your API key is a secret credential. It must only be used on your backend server. Never expose this key in your frontend (client-side) JavaScript, mobile app code, or any public repository.

  • Connect a webhook endpoint (optional): In your dashboard, under developer settings, create a new webhook endpoint and listen to the payment_complete event.

Integration flow overview

A complete transaction involves both your frontend (handling user interaction) and your backend (handling secure API calls).

  1. On the frontend (aka client-side): Your customer interacts with Reservepay pre-built form which captures all necessary payment details and creates a payment_session_id via the onPaymentSessionCreated callback.

  2. On the backend (aka server-side): Your frontend sends the payment_session_id to your server. Your server then securely uses its secret API key to call the Reservepay Merchant API and initiate the actual payment flow.

  3. Back on the frontend: The Reservepay pre-built form automatically displays the payment status and hands back control to you via the onComplete callback.

About payment session IDs

The payment_session_id is a unique identifier that represents a single payment attempt from start to finish. It is the essential "link" between your customer's actions on the frontend (using the SDK) with the secure payment initiation request made by your backend (using your API key). You can think of it as a unique tracking number for the entire transaction lifecycle.

Integration steps

Install the SDK

Example (JS)

Include the SDK script tag in your HTML file. This loads the reservepay object into your application.

To maintain strict PCI compliance and ensure the integrity of sensitive payment information, our library must be loaded directly from our secure servers via a script tag and must not be bundled or imported via a package manager.

<script src="https://sdk.reservepay.com/js/v1/reservepay.js"></script>
// Initialize the sdk
//
// Note that the Reservepay sdk is available in window.Reservepay
const reservepay = window.Reservepay.initReservepay({
  merchantId: "123456789100",
  installationId: "ins_123",
})

Example (Android)

Add the following to your project's build.gradle:

repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.reservepay:reservepay-android:1.0.0'
}

Add ReservepayActivity into AndroidManifest.xml

<activity
    android:name="com.reservepay.ReservepayActivity"
    android:exported="false" />
import com.reservepay.ReservepayCallbacks
import com.reservepay.ReservepaySDKHelper

// Create callback
private val reservepayCallbacks = object : ReservepayCallbacks {
    override fun onPaymentCancelled() {
    }
    override fun onPaymentError(error: String) {
    }
    override fun onPaymentSessionReady(sessionId: String) {
    }
    override fun onPaymentStatus(status: String) {
    }
}

// Initialize the sdk
ReservepaySDK.getInstance().startPayment(
    context,
    "123456789100", // Merchant Id
    "ins_123", // Installation Id
    "1500.50", // Amount
    "THB", // Currency
    reservepayCallbacks // Callbacks
)

Example (iOS)

Using Swift Package Manager

  1. In Xcode, go to File > Add Packages...
  2. Enter the repository URL
  3. Select the version you want to use
  4. Click Add Package
import ReservepaySDK

// Create callback
let callback = ReservepayCallback(
    onPaymentSessionReady: { sessionId in
        print("Payment session ready with ID: \(sessionId)")
    },
    onPaymentCancelled: {
        print("Payment cancelled")
        // Dismiss the view controller
        viewController.dismiss(animated: true)
    }
)

// Initialize the SDK
ReservepaySDKHelper().getInstance().startPayment(
    viewController: viewController,
    merchantId: "123456789100",
    installationId: "ins_123",
    amount: "1000.25",
    currency: "THB",
    callback: callback
)

Attach the SDK

Once the SDK script is loaded, you can initialize the payment form using the window.Reservepay.initReservepayFormUI method. This function takes a configuration object.

The required top-level parameters are:

  • formType: Defines the UI mode. Use "popup" or "embedded".
  • merchantId: Your unique merchant identifier.
  • installationId: The specific installation ID for this integration.
  • formOptions: An object containing configuration specific to the form, such as amount and the necessary event callbacks.

Option A: Popup Form

The popup mode displays the payment form in a modal window that opens when a user clicks a trigger element (like a button).

Step 1: Create the HTML Trigger Element Add an element, such as a <button>, with a unique ID or class to your HTML.

<button id="reservepay-popup-trigger">Pay Now</button>

Step 2: Initialize the SDK for Popup Mode In your JavaScript, call initReservepayFormUI with formType: "popup" and provide the CSS selector for your trigger element in formOptions.popupTriggerSelector.

window.Reservepay.initReservepayFormUI({
  formType: "popup",
  merchantId: "123456789100",
  installationId: "ins_123",
  formOptions: {
    popupTriggerSelector: "#reservepay-popup-trigger", // Points to your button
    amount: "100000",
    // ... event handlers (see section 3)
  },
});

Option B: Embedded Form

The embedded mode renders the payment form directly inside a container element on your page. This is useful for seamless integration within your checkout flow.

Step 1: Create the HTML Container Element Add a container element, such as a <div>, with a unique ID or class where you want the form to appear.

<div id="reservepay-mount"></div>

Step 2: Initialize the SDK for Embedded Mode In your JavaScript, call initReservepayFormUI with formType: "embedded" and provide the CSS selector for your container element in formOptions.containerSelector.

window.Reservepay.initReservepayFormUI({
  formType: "embedded",
  merchantId: "123456789100",
  installationId: "ins_123",
  formOptions: {
    containerSelector: "#reservepay-mount", // Points to your div
    amount: "100000",
    // ... event handlers (see section 3)
  },
});

Handle payment callbacks

The formOptions object must include callback functions to handle the different stages of the payment process. These callbacks receive the sessionId as an argument.

Handling the payment_session_id

  • onPaymentSessionReady(sessionId)
    • When it fires: As soon as the SDK successfully initializes and creates a payment session, before the user has submitted any payment details.
    • What to do: This is the most critical callback for your backend. You must send this sessionId to your server and associate it with the user's order or cart in your database. This allows you to track the payment and verify its status later.

Handling Completion Status

  • onPaymentSuccess(sessionId)

    • When it fires: After the user successfully completes the payment flow.
    • What to do: This is the primary way to update your frontend UI. You should:
    • Show a success message to the user.
    • Redirect them to a confirmation page.
    • Trigger any frontend-specific success logic.
    • Note: While this confirms a successful UI flow, final order fulfillment should always be triggered by a secure, server-to-server confirmation (like a webhook) or by verifying the status of the sessionId you saved from onPaymentSessionReady.
  • onPaymentFailed(sessionId)

    • When it fires: If the payment is declined, encounters an error, or is canceled by the user.
    • What to do:
    • Show an appropriate error message to the user.
    • Allow the user to try again (if applicable).

Full Code Examples

Popup example
// Create button element
<button id="reservepay-popup-trigger">Open</button>

// Attach popup to button
window.Reservepay.initReservepayFormUI({
  formType: "popup",
  merchantId: "123456789100",
  installationId: "ins_123",
  formOptions: {
    popupTriggerSelector: "#reservepay-popup-trigger", // Your element selector where you want to open the popup, this could be a button, etc.
    amount: "1234",
    onPaymentSessionReady(sessionId) {
      console.log("Payment session ready", sessionId)
    },
    onPaymentSuccess(sessionId) {
      console.log("Payment successful", sessionId)
    },
    onPaymentFailed(sessionId) {
      console.log("Payment failed", sessionId)
    },
  },
})
Embedded example
// Create div element
<div id="reservepay-mount"></div>

// Attach embedded to div
window.Reservepay.initReservepayFormUI({
  formType: "embedded",
  merchantId: "123456789100",
  installationId: "ins_123",
  formOptions: {
    containerSelector: "#reservepay-mount", // Your elementselector where you want to attach the embedded this could be a div.
    amount: "1234",
    onPaymentSessionReady(sessionId) {
      console.log("Payment session ready", sessionId)
    },
    onPaymentSuccess(sessionId) {
      console.log("Payment successful", sessionId)
    },
    onPaymentFailed(sessionId) {
      console.log("Payment failed", sessionId)
    },
  },
})

Initiate the payment flow

After your frontend sends the payment_session_id, your backend must call the /merchants/initiate-payment-flow endpoint which will return a payment_id. This call must be authenticated using your secret API key as a bearer token in the Authorization header. This "authorizes" the payment session and kicks off the payment flow.

Example

// IMPORTANT: This must be called from your server-side code with your API key
// Never expose your API key (reservepay_xxx) in client-side code
// Make a request from your backend to ReservePay API:
//
await fetch('https://api.reservepay.com/merchants/initiate-payment-flow', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY', // Use your API key here (server-side only!)
    'Api-Version': '2025-04-01',
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: "1000",
    currency: "THB",
    payment_session_id: paymentSessionId,
    capture: true,
    return_url: "https://your-site.com/return-url"
  })
})

Confirming the payment status

To confirm the payment status from your backend call /merchants/find-payment using the payment_id returned by the /merchants/initiate-payment-flow endpoint. This returns the full payment object, including the status field.

Webhooks (optional)

For a more robust integration, we highly recommend using webhooks. Instead of relying only on polling, your server can receive asynchronous notifications. To achieve the same result as the previous step, listen for the payment_complete event.

To verify the signature of incoming events our requests include an X-Webhook-Signature header. You must verify this signature using your webhook endpoint verify key (available in your dashboard) and a libsodium compatible library. This verification is critical to make sure that the request genuinely came from Reservepay and was not forged.

No account yet?

Start integrating all these amazing features into your app or website by creating your own merchant account today. It's free to sign up and only takes a few minutes to get started.