Integration guides
Advanced features
Open in Markdown

Customer intelligence

Build profiles by attaching customer data. Gain insights, reduce fraud risk, and create personalized experiences.

Overview

Customer intelligence is a suite of tools that allow you to build detailed profiles for your customers. By attaching customer data to your transactions, you gain valuable insights, reduce fraud risk, and create more personalized experiences.

Reservepay's intelligence engine automatically correlates information across your account. Whether you provide a Customer ID, an email address, or a mobile phone number, we'll correctly identify and link the data to the same customer profile.

Managing contacts

Contacts are the core of customer intelligence in Reservepay. You can create, retrieve, update, and remove contacts using our API. Contacts support both payments and payouts, making it easy to manage the full lifecycle of your customer interactions.

Creating a contact

To create a new contact, use the add-contact endpoint. You must provide either an email address or a mobile number. You can also provide your own external_id to use as a Customer ID from your system.

await fetch('https://api.reservepay.com/merchants/add-contact', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Api-Version': '2025-04-01',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    contact_email: 'customer@example.com',
    contact_name: 'John Doe',
    external_id: 'cust_987654' // Your own Customer ID
  })
})

Linking transactions to contacts

When initiating a payment or a payout, you can link the transaction to a contact. Our system will automatically correlate the information even if you only provide an email or mobile number.

Payments

When initiating a payment flow, you can link the transaction to an existing contact by providing the customer_id (either our ctc_ ID or your external_id), customer_email, or customer_mobile.

await fetch('https://api.reservepay.com/merchants/initiate-payment-flow', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Api-Version': '2025-04-01',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: '10000',
    currency: 'THB',
    customer_email: 'customer@example.com', // We'll automatically correlate this to the right contact
    payment_session_id: 'sess_1234567890',
    capture: true,
    return_url: 'https://example.com/return'
  })
})

Payouts

You can also send payouts to your contacts. Use the send-payout-to-contact endpoint to send funds to a contact's primary bank account or via PromptPay using their mobile number or national ID.

Managing bank accounts for contacts

To send a payout to a contact's bank account, you can first link one or more bank accounts to the contact using the link-bank-account endpoint.

Once a bank account is linked, you can:

Saving cards for future use

You can securely save customer cards for future payments. This is useful for implementing one-click checkouts or subscription billing.

Tokenizing a card

First, tokenize the card details using the tokenize-card endpoint. Set usage: 'MULTIPLE' to create a reusable token. A reusable token can be saved and charged again, but each customer-initiated payment still needs the CVV. See The CVV on saved cards.

Saving the card to a contact

Save a card only after the customer agrees. Each saved card gets a card_id. You can save it in two ways:

  • With the payment: Add customer_id and save_card to your initiate-payment-flow call. Use this when the customer saves the card at checkout.
  • On its own: Call save-card when no payment is in progress.

With the payment

Set save_card to ADD to attach the card to the customer, or DEFAULT to also make it their default card. The card is saved only if the payment's token was created with usage: 'MULTIPLE'.

await fetch('https://api.reservepay.com/merchants/initiate-payment-flow', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Api-Version': '2025-04-01',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: '1000',
    currency: 'THB',
    payment_session_id: 'sess_1234567890',
    capture: true,
    return_url: 'https://example.com/return',
    external_id: 'order_12345',
    customer_id: 'ctc_1234567890',
    save_card: 'ADD'
  })
})

On its own

await fetch('https://api.reservepay.com/merchants/save-card', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Api-Version': '2025-04-01',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    token: 'ABCDEF123456789',
    contact_id: 'ctc_1234567890',
    default: true
  })
})

Only a token created with usage: 'MULTIPLE' can be saved. Saving a single-use token returns NOT_REUSABLE, and a token that was already used returns TOKEN_ALREADY_USED. In both cases, tokenize the card again.

Retrieving saved cards

You don't need to store tokens yourself. Call retrieve-contact to list the contact's cards. Each active card includes:

  • token: The merchant-scoped opaque token you pass to the browser SDK for a saved-card checkout.
  • card_id: The ID your backend uses, for example with request-payment.
const contact = await fetch('https://api.reservepay.com/merchants/retrieve-contact', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Api-Version': '2025-04-01',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ contact_id: 'ctc_1234567890' })
}).then(res => res.json())

const savedCards = contact.default_card
  ? [
      contact.default_card,
      ...contact.cards.filter(
        card => card.card_id !== contact.default_card.card_id
      )
    ]
  : contact.cards

const savedCardTokens = savedCards.map(card => card.token)

The example puts the default card first because the SDK initially selects the first valid token. To look up one card by its ID or token, use find-card.

Charging a saved card

You can charge a saved card in two ways:

Flow What the customer does Checks Use it for
Customer-initiated payment (CIT) Picks the saved card in your checkout and enters the CVV again. CVV, plus 3D Secure when it applies. Returning customers on your checkout page. See The CVV on saved cards.
Merchant-initiated payment (MIT) Taps pay in your app, or nothing at all. No CVV and no 3D Secure. Your backend charges the card directly. One-tap payments in your own app, such as paying for an EV charging session, and charges without the customer, such as renewals. See Merchant-initiated payments.

Required: For a customer-initiated payment with the browser SDK, return the tokens from your backend and pass them to the SDK: formOptions.savedCardTokens for pre-built forms, or the selected card's token as savedCardToken for your own UI.

The CVV on saved cards

Reservepay never saves the CVV with the card. The CVV entered with tokenize-card covers only the payment made right after it. For any later customer-initiated payment, the saved card's token needs a newly entered CVV, added with rehydrate-card. That's why a saved card can go through when it's charged right after it's saved.

For every customer-initiated payment on a saved card:

  1. Collect the CVV from the customer.
  2. Call rehydrate-card with the saved card's token and the CVV. It returns the same token.
  3. Right after, create the payment session with select-payment-method using that token, and have your backend call initiate-payment-flow.

If the payment fails, ask for the CVV and rehydrate the card again before retrying.

The browser SDK does steps 1 and 2 for you when you pass it saved-card tokens. It shows a CVV field, then calls rehydrate-card: pre-built forms do this before they create the payment session, and in your own UI, instance.tokenize() does it. Call rehydrate-card yourself only when you call the SDK API directly, without the browser SDK.

Required: A saved card's token must be rehydrated before you pass it to select-payment-method. The browser SDK does this for you. If you call the SDK API directly, call rehydrate-card yourself. If you skip it, select-payment-method still creates the payment session, but the payment fails later. usage: 'MULTIPLE' means the card can be saved and reused. It doesn't let a customer-initiated payment skip the CVV. To charge a saved card without the CVV, use a merchant-initiated payment.

Merchant-initiated payments (MIT)

Use request-payment to charge a saved card from your backend, with no payment session, SDK, CVV, or 3D Secure. The customer doesn't have to do anything at payment time, so it works for both:

  • One-tap payments in your app: The customer signed in to your app and saved a card earlier. When they tap pay, for example to pay for an EV charging session, your app tells your backend, and your backend calls request-payment.
  • Charges without the customer: Subscription renewals, or a final charge after a booking or service ends.

  • Pass the contact's card_id, or leave it out to charge the contact's default card.

  • Pass your installation_id, and identify the contact with customer_id (the contact ID or your own customer ID), customer_email, or customer_mobile. The card must belong to that contact.

  • Ask Reservepay support to enable merchant-initiated payments on your card payment method. Until then, the call returns NOT_ALLOWED.

Example

await fetch('https://api.reservepay.com/merchants/request-payment', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Api-Version': '2025-04-01',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    amount: '1000',
    currency: 'THB',
    installation_id: 'ins_1234567890',
    capture: true,
    customer_id: 'ctc_1234567890',
    card_id: 'crd_1234567890' // Omit to charge the default card
  })
})

Since this skips 3D Secure, so they don't get the liability shift a 3D Secure challenge gives, and you carry the chargeback risk. You can still challenge a dispute with evidence. When the customer saves the card, get their permission to charge it this way, and keep a record of it to submit if they dispute a charge. Because your backend makes the charge, your app must confirm that the signed-in customer is the one paying before you call request-payment. See Disputes.

Insights and analytics

By consistently linking payments to contacts, you can unlock powerful insights through our dashboard and API. You can see:

  • Customer lifetime value (CLV): Total amount spent by a customer.
  • Purchase frequency: How often a customer makes a purchase.
  • Preferred payment methods: Which payment methods a customer uses most frequently.
Integrate further

Dive deeper into these advanced integration topics to unlock Reservepay's full potential with our in-depth guides.

Refunds, voids, and reversals

Issue refunds, void transactions before they settle, and reverse authorizations when needed.

Read the guide
Disputes

Find disputed payments, submit evidence, and respond before the deadline.

Read the guide
Authorization and capture

Separate authorization from capture to hold funds without charging. Perfect for pre-orders or reservations

Read the guide
Working with Terminal

Build your own POS, or work with our app by sending commands or using deep links.

Read the guide
Customer intelligence

Build profiles by attaching customer data. Gain insights, reduce fraud risk, and create experiences that drive loyalty.

Read the guide
Sending funds

Send payouts to your primary bank account or to your contacts via bank account, mobile number or national ID.

Read the guide
Real-time notifications

Stay informed about payment events with real-time webhooks. Automate your order processing, and more...

Read the guide
Payment lifecycle

Check payment statuses, available actions, refunds, and disputes.

Read the guide
Reconciliation

Filter payments and payouts, export CSVs, read balance holds, and reconcile daily statements.

Read the guide
Payment failure codes

Look up what each Reservepay failure code means when a payment is declined.

Read the guide

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.