Overview
The Payment Intent API gives you fine-grained control over the payment process. Unlike Checkout sessions that redirect to a hosted page, Payment Intents allow you to build custom payment flows on your own site or mobile app.
When to Use Payment Intents
Use Payment Intents when:
You need a custom payment UI embedded in your application
You're building a mobile app with native payment flows
You need to handle 3D Secure authentication programmatically
You want to save payment methods for future use
Use Checkout when:
You want a quick hosted payment page
You prefer redirect-based flows
You don't want to build custom payment UI
Payment Intent Flow
Your Server SaligPay API Customer
│ │ │
├── POST /payment-intent ────►│ │
│◄── pi_id + clientKey ───────┤ │
│ │ │
├── POST /confirm ───────────►│ │
│◄── requires_action? ────────┤ │
│ │──── 3D Secure auth ───────►│
│◄── succeeded ───────────────┤ │
│◄── Webhook ─────────────────┤ │
Quick Start
Step 1: Create a Payment Intent
import { SaligPay } from "saligpay-node" ;
const saligpay = new SaligPay ({
clientId: process.env. SALIGPAY_CLIENT_ID ! ,
clientSecret: process.env. SALIGPAY_CLIENT_SECRET ! ,
env: "sandbox" ,
});
await saligpay. authenticate ();
const intent = await saligpay.paymentIntents. create ({
amount: 10000 ,
description: "One-time purchase" ,
externalId: "order-456" ,
contact: {
name: "Jane Smith" ,
email: "jane@example.com" ,
phone: "+639123456789" ,
},
returnUrl: "https://yourapp.com/payment/success" ,
webhookUrl: "https://yourapp.com/webhooks/saligpay" ,
});
console. log ( "Intent ID:" , intent.id);
console. log ( "Available Methods:" , intent.paymentMethods);
Step 2: Confirm with a Payment Method
const confirmation = await saligpay.paymentIntents. confirm (intent.id, {
paymentMethod: "pm_gcash_xyz" ,
contact: {
name: "Jane Smith" ,
email: "jane@example.com" ,
},
});
if (confirmation.requiresAction && confirmation.nextAction) {
// Handle 3D Secure redirect
res. redirect (confirmation.nextAction.redirectUrl);
}
Step 3: Check Status
const status = await saligpay.paymentIntents. getStatus (intent.id);
console. log ( "Payment Status:" , status.status);
API Reference
Create Payment Intent
POST /api/payment-intent
POST /api/payment-intent
Authorization: Bearer <access_token>
Content-Type: application/json
{
"amount": 10000,
"description": "One-time purchase",
"externalId": "order-456",
"contact": {
"name": "Jane Smith",
"email": "jane@example.com",
"phone": "+639123456789"
},
"metadata": { "item": "premium_upgrade" },
"returnUrl": "https://yourapp.com/payment/success",
"webhookUrl": "https://yourapp.com/webhooks/saligpay"
}
Response
{
"success" : true ,
"data" : {
"id" : "pi_abc123" ,
"transactionId" : "txn_xyz789" ,
"sessionToken" : "550e8400-e29b-41d4-a716-446655440001" ,
"amount" : 10000 ,
"status" : "pending" ,
"clientKey" : "ck_xxx" ,
"paymentMethods" : [ "gcash" , "grab_pay" , "card" ],
"fee" : 250 ,
"createdAt" : "2025-05-03T12:00:00Z" ,
"updatedAt" : "2025-05-03T12:00:00Z"
}
}
Confirm Payment Intent
POST /api/payment-intent/{intentId}/confirm
POST /api/payment-intent/pi_abc123/confirm
Authorization: Bearer <access_token>
Content-Type: application/json
{
"paymentMethodId": "pm_abc123",
"contact": {
"name": "Jane Smith",
"email": "jane@example.com"
}
}
Get Payment Intent Status
GET /api/payment-intent/{intentId}/status
GET /api/payment-intent/pi_abc123/status
Authorization: Bearer <access_token>
Response
{
"success" : true ,
"data" : {
"id" : "pi_abc123" ,
"transactionId" : "txn_xyz789" ,
"amount" : 10000 ,
"status" : "succeeded" ,
"paymentMethod" : {
"id" : "pm_abc123" ,
"type" : "gcash"
},
"createdAt" : "2025-05-03T12:00:00Z" ,
"updatedAt" : "2025-05-03T12:01:00Z"
}
}
SDK Reference
PaymentIntentResource
create(options)
interface PaymentIntentApiResponse {
id : string ;
transactionId : string ;
sessionToken : string ;
amount : number ;
status : PaymentIntentStatus ;
description : string ;
clientKey : string ;
paymentMethods : string [];
fee : number ;
createdAt : string ;
updatedAt : string ;
}
type PaymentIntentStatus =
| "requires_payment_method"
| "requires_confirmation"
| "requires_action"
| "processing"
| "succeeded"
| "canceled" ;
confirm(intentId, options)
interface PaymentConfirmationApiResponse {
intentId : string ;
status : PaymentIntentStatus ;
redirectUrl ?: string ;
requiresAction : boolean ;
nextAction ?: {
type : "redirect" | "display_details" ;
redirectUrl ?: string ;
};
}
getStatus(intentId)
Returns the current status of a payment intent.
3D Secure Handling
When a payment requires additional authentication:
const confirmation = await saligpay.paymentIntents. confirm (intentId, {
paymentMethod: "pm_card_visa" ,
creditCardDetails: {
cardNumber: "4111111111111111" ,
expMonth: "12" ,
expYear: "2027" ,
cvc: "123" ,
},
});
if (confirmation.requiresAction) {
if (confirmation.nextAction?.type === "redirect" ) {
// Redirect to 3D Secure authentication
res. redirect (confirmation.nextAction.redirectUrl);
}
}
After authentication, the customer is redirected to your returnUrl. Check the payment status:
const status = await saligpay.paymentIntents. getStatus (intentId);
if (status.status === "succeeded" ) {
// Payment successful
}
Error Handling
Error Cause Solution PAYMENT_METHOD_INVALIDInvalid payment method ID Verify payment method exists INSUFFICIENT_FUNDSCustomer has insufficient balance Ask for different payment method 3D_SECURE_REQUIREDAuthentication needed Complete the redirect flow INTENT_ALREADY_CONFIRMEDIntent already processed Check status before confirming
Best Practices
Always check requiresAction after confirmation
Implement polling or webhooks for status updates
Store clientKey securely for client-side operations
Handle payment method selection based on paymentMethods array in the response
Related Guides:
Last modified on May 5, 2026