- WooCommerce
- Magento
- Shopify Soon
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:
- Set a primary account: Use
set-primary-contact-bank-accountto specify which account should receive payouts by default. - Find accounts: Use
find-bank-accountto retrieve details of a specific bank account. - Unlink accounts: Use
unlink-bank-accountto remove a bank account from a contact's profile.
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_idandsave_cardto yourinitiate-payment-flowcall. Use this when the customer saves the card at checkout. - On its own: Call
save-cardwhen 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 withrequest-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.savedCardTokensfor pre-built forms, or the selected card'stokenassavedCardTokenfor 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:
- Collect the CVV from the customer.
- Call
rehydrate-cardwith the saved card'stokenand the CVV. It returns the sametoken. - Right after, create the payment session with
select-payment-methodusing thattoken, and have your backend callinitiate-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
tokenmust be rehydrated before you pass it toselect-payment-method. The browser SDK does this for you. If you call the SDK API directly, callrehydrate-cardyourself. If you skip it,select-payment-methodstill 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 withcustomer_id(the contact ID or your own customer ID),customer_email, orcustomer_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.
Dive deeper into these advanced integration topics to unlock Reservepay's full potential with our in-depth guides.
Issue refunds, void transactions before they settle, and reverse authorizations when needed.
Read the guideSeparate authorization from capture to hold funds without charging. Perfect for pre-orders or reservations
Read the guideBuild your own POS, or work with our app by sending commands or using deep links.
Read the guideBuild profiles by attaching customer data. Gain insights, reduce fraud risk, and create experiences that drive loyalty.
Read the guideSend payouts to your primary bank account or to your contacts via bank account, mobile number or national ID.
Read the guideStay informed about payment events with real-time webhooks. Automate your order processing, and more...
Read the guideFilter payments and payouts, export CSVs, read balance holds, and reconcile daily statements.
Read the guideLook up what each Reservepay failure code means when a payment is declined.
Read the guideNo 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.
