Pay by Points — Integration Steps
Step-by-step guide to integrate Pay by Points via Seamless Checkout using Pine Labs Online APIs.
Integration Steps — Custom Checkout
Integrate Pay by Points into your custom checkout using Pine Labs Online APIs.
Follow these steps to enable customers to redeem reward points during payment.
- Generate Token
- Check Point Balance
- Create Order
- Create Payment
- Handle Payment
- Capture Order
- Cancel Order
Note:
- Store your Client ID and Secret in your backend securely.
- Integrate APIs on your backend system — never call from the frontend.
- Seamless checkout requires PCI compliance.
1. [Prerequisite] Generate Token
Generate an access token to authenticate all subsequent API calls.
Endpoint: POST /api/auth/v1/token
curl --location 'https://pluraluat.v2.pinepg.in/api/auth/v1/token' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'Request-Timestamp: 2024-07-09T07:57:08.022Z' \
--header 'Request-ID: c17ce30f-f88e-4f81-ada1-c3b4909ed235' \
--data '{
"client_id": "<your_client_id>",
"client_secret": "<your_client_secret>",
"grant_type": "client_credentials"
}'
Refer to the Generate Token API documentation for full request and response details.
2. Check Point Balance
Query the customer's reward points balance before creating a payment.
Endpoint: POST /payment-option
curl --location 'https://pluraluat.v2.pinepg.in/payment-option' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--data '{
"points_card_details": {
"card_last4": "1234",
"card_number": "4111111111111234",
"registered_mobile_number": "9876543210"
},
"order_details": {
"order_amount": {
"value": 5000,
"currency": "INR"
}
}
}'
The response includes:
| Field | Description |
|---|---|
points_balance | Number of reward points available |
inr_equivalent | Converted INR amount |
conversion_rate | Points-to-INR rate |
Customer consent: You must obtain explicit customer consent before proceeding to redeem points. This is mandatory per partner bank requirements.
3. Create Order
Create an order with POINTS included in the allowed payment methods.
Endpoint: POST /api/pay/v1/orders
curl --location 'https://pluraluat.v2.pinepg.in/api/pay/v1/orders' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--header 'Request-ID: c17ce30f-f88e-4f81-ada1-c3b4909ed235' \
--header 'Request-Timestamp: 2024-07-09T07:57:08.022Z' \
--data '{
"merchant_order_reference": "PBP-12345",
"order_amount": {
"value": 4573,
"currency": "INR"
},
"pre_auth": false,
"allowed_payment_methods": [
"CARD",
"POINTS"
],
"notes": "Pay by Points order",
"callback_url": "https://your-domain.com/callback",
"failure_callback_url": "https://your-domain.com/failure",
"purchase_details": {
"customer": {
"email_id": "customer@example.com",
"first_name": "Kevin",
"last_name": "Bob",
"customer_id": "CUST-001",
"mobile_number": "9876543210",
"country_code": "91"
}
}
}'
Include
"POINTS"in theallowed_payment_methodsarray to enable Pay by Points for this order.
Refer to the Create Order API documentation for the full parameter list.
4. Create Payment
Submit a split payment with both CARD and POINTS components. The amounts must total the order value.
Endpoint: POST /api/pay/v1/orders/{order_id}/payments
curl --location 'https://pluraluat.v2.pinepg.in/api/pay/v1/orders/{order_id}/payments' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--header 'Request-ID: c17ce30f-f88e-4f81-ada1-c3b4909ed235' \
--header 'Request-Timestamp: 2024-07-09T07:57:08.022Z' \
--data '{
"payments": [
{
"merchant_payment_reference": "pay-card-ref-001",
"payment_method": "CARD",
"payment_amount": {
"value": 1372,
"currency": "INR"
}
},
{
"merchant_payment_reference": "pay-points-ref-001",
"payment_method": "POINTS",
"payment_amount": {
"value": 3201,
"currency": "INR"
},
"points_card_details": {
"card_last4": "1234",
"card_number": "4111111111111234",
"registered_mobile_number": "9876543210"
}
}
]
}'
Split payment example
| Component | Amount | Description |
|---|---|---|
| Card | ₹13.72 | Paid via credit/debit card |
| Points | ₹32.01 | Redeemed from reward points |
| Total | ₹45.73 | Must match order amount |
Important: The sum of all payment amounts must exactly equal the order amount. Mismatched amounts will cause the payment to fail.
Refer to the Create Payment API documentation for all parameters.
5. Handle Payment
The Create Payment response returns a challenge_url. Redirect the customer to this URL to complete authentication.
Redirect flow
- Redirect the customer to
challenge_url - Customer completes authentication on the bank page
- Bank redirects back to your
callback_urlwith payment details
Callback response
On successful payment:
{
"order_id": "v1-4405071524-aa-qlAtAf",
"payment_status": "AUTHORIZED",
"signature": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
}
Verify signature (mandatory)
Generate a SHA256 HMAC signature on your server and compare it with the returned signature.
Signature string format:
order_id=<order_id>&status=AUTHORIZED
Signature verification (Java):
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class SignatureVerifier {
public static String generateHash(String input, String secretKey) {
try {
byte[] keyBytes = new byte[secretKey.length() / 2];
for (int i = 0; i < secretKey.length() / 2; i++) {
keyBytes[i] = (byte) Integer.parseInt(
secretKey.substring(i * 2, (i * 2) + 2), 16
);
}
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(keySpec);
byte[] hashBytes = mac.doFinal(input.getBytes("UTF-8"));
StringBuilder hash = new StringBuilder();
for (byte b : hashBytes) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) hash.append('0');
hash.append(hex);
}
return hash.toString().toUpperCase();
} catch (Exception e) {
return "";
}
}
}
Security: Always verify the signature before processing the order. This confirms the payment response is authentic and has not been tampered with.
6. Capture Order
After successful payment and signature verification, capture the order to complete the transaction.
Endpoint: PUT /api/pay/v1/orders/{order_id}/capture
curl --location --request PUT \
'https://pluraluat.v2.pinepg.in/api/pay/v1/orders/{order_id}/capture' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--header 'Request-ID: c17ce30f-f88e-4f81-ada1-c3b4909ed235' \
--header 'Request-Timestamp: 2024-07-09T07:57:08.022Z'
Capture is only available when the order status is
AUTHORIZED.
7. Cancel Order (optional)
Cancel an authorized order if you do not wish to capture the payment.
Endpoint: PUT /api/pay/v1/orders/{order_id}/cancel
curl --location --request PUT \
'https://pluraluat.v2.pinepg.in/api/pay/v1/orders/{order_id}/cancel' \
--header 'Authorization: Bearer <access_token>' \
--header 'Content-Type: application/json' \
--header 'Request-ID: c17ce30f-f88e-4f81-ada1-c3b4909ed235' \
--header 'Request-Timestamp: 2024-07-09T07:57:08.022Z'
Cancel is only available when the order status is
AUTHORIZED.
Best Practices
| Practice | Detail |
|---|---|
| Verify signature | Always verify the callback signature using SHA256 HMAC — this is mandatory |
| Fetch order status | Use Get Order API from your backend to confirm the order status |
| Configure webhooks | Set up webhooks for real-time payment notifications |
| Flexible JSON parsing | Do not fail on unknown fields — new fields may be added without notice |
| Avoid hardcoding | Do not hardcode field values, response structures, or error codes |
| TLS 1.2+ | All API calls must use TLS 1.2 or higher |
| Sanity testing | Test the complete flow on UAT before going live |
