S2S Card
Create card payments from your backend using FiatPe’s server-to-server payment flow.
Supported card capabilities
Fetch the card networks, card types, and card subtypes enabled for your account using the Methods API.
Only accept and display card capabilities whose values are true in the response.
Open the Methods API guideSupported card networks
FiatPe Server-to-Server card payments support the following card networks, subject to your account configuration and acquiring setup.
Test cards by authentication flow
Use these card details only in the FiatPe test environment. They are designed to return the indicated next.action flow.
Your integration must successfully handle Native, Redirect, and HTML Form flows in the UAT environment. The flow returned for a transaction can vary based on the configured TID, acquiring bank, issuing bank, payment network, payment method, and other transaction parameters.
Do not hardcode a flow for a card, bank, wallet, or PayLater provider. Always inspect the returned next[].action value and process otp_submit, resend_otp, redirect, or html_form as instructed by the API response.
Create the order on your server
Create a new FiatPe order for each payment attempt. Amounts use the smallest currency sub-unit: for INR, 5000 represents ₹50.00. Store the returned order ID against your internal order before using it in the S2S payment request.
Server request example
Use your FiatPe credentials only from a trusted backend environment.
REQUEST
curl --request POST \
--url https://api.fiatpe.com/v1/orders/ \
--header "Authorization: Basic YOUR_BASE64_CREDENTIALS" \
--header "Content-Type: application/json" \
--data '{
"amount": 5000,
"currency": "INR"
}'Response
Store the returned data.id and pass it as the order_id in Step 2.
{
"data": {
"id": "order_2f40f08f4baa4e5b",
"amount": 5000,
"entity": "order",
"method": null,
"status": "created",
"currency": "INR",
"metadata": {},
"created_at": 1788148983,
"return_url": null,
"amount_paid": 0,
"bank_details": null,
"return_method": "POST",
"amount_pending": 5000
},
"message": "order created successfully."
}Initiate a native card payment
Send the card payment request from your PCI-compliant backend. Generate the Basic authorization value by Base64 encoding api_key:secret_key.
Never log, persist, cache, or expose the full card number or CVV. Use the test card below only in the FiatPe test environment.
REQUEST
curl --location 'https://api.fiatpe.com/v1/payments/s2s/' \
--header 'Authorization: Basic <base64(api_key:secret_key)>' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 5000,
"currency": "INR",
"contact": "+919898989898",
"name": "Aftab Hussain",
"email": "customer@example.com",
"order_id": "order_75db8a5703ba4d3a",
"callback_url": "https://api.example.com/webhooks/fiatpe",
"description": "Test payment",
"method": "card",
"card": {
"number": "4111111111111111",
"name": "Gaurav",
"expiry_month": "11",
"expiry_year": "26",
"cvv": "100"
},
"metadata": {
"note_key": "value1"
}
}'Request fields
Native OTP flow
Native flow: Send OTP
The initial card payment request sends an OTP to the customer for a native OTP payment. Store the returned payment_id. The next array provides the actions required to submit or resend the OTP.
{
"payment_id": "FIATPESTCM3YWO15VB1790705241",
"next": [
{
"action": "otp_submit",
"url": "https://api.fiatpe.com/v1/payments/FIATPESTCM3YWO15VB1790705241/otp/submit/"
},
{
"action": "resend_otp",
"url": "https://api.fiatpe.com/v1/payments/FIATPESTCM3YWO15VB1790705241/otp/resend/"
}
]
}Native flow: Submit OTP
After the customer enters the OTP, submit it from your secure backend using the payment_id returned in Step 2. Never log or persist the OTP.
REQUEST
curl --location 'https://api.fiatpe.com/v1/payments/FIATPESTCM3YWO15VB1790705241/otp/submit/' \
--header 'Authorization: Basic <base64(api_key:secret_key)>' \
--header 'Content-Type: application/json' \
--data '{
"otp": "123456"
}'Successful response
Verify the returned signature on your server before fulfilling the order. Match the payment ID and order ID with your stored records.
{
"payment_id": "FIATPESTCM3YWO15VB1790705241",
"order_id": "order_75db8a5703ba4d3a",
"signature": "223e419c39bc40a8f63a22b82bb44a084b0d2f7462e88799dd8592ae7eed6c5f836f595716fa76c4a07dae9cf00d4096ac4d26d32ef01a6d15b5bce657988881"
}Simulate OTP Scenarios in Sandbox
Use the following test OTP values in the FiatPe Sandbox environment to simulate different payment outcomes. Submit the OTP using the Native OTP Submit API.
These OTP values are intended for testing in the FiatPe Sandbox environment only. They do not apply to live transactions. Always verify the final payment status using the retrieve payment API or webhooks.
Native flow: Resend OTP
If the customer does not receive the OTP, call the resend endpoint using the same payment_id. Trigger this request only after an explicit customer action and prevent repeated rapid requests.
REQUEST
curl --location --request POST 'https://api.fiatpe.com/v1/payments/FIATPESTCM3YWO15VB1790705241/otp/resend/' \
--header 'Authorization: Basic <base64(api_key:secret_key)>' \
--data ''Response
{
"message": "OTP Resend successfully"
}Alternative card flows
Redirect flow
Some cards return next[0].action as redirect. The following test-card example demonstrates this flow.
REQUEST
curl --location 'https://api.fiatpe.com/v1/payments/s2s/' \
--header 'Authorization: Basic <base64(api_key:secret_key)>' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 5000,
"currency": "INR",
"contact": "+919898989898",
"name": "Aftab Hussain",
"email": "customer@example.com",
"order_id": "order_b515d1952d194824",
"return_url": "https://example.com/payment/return",
"callback_url": "https://api.example.com/webhooks/fiatpe",
"description": "Test payment",
"method": "card",
"card": {
"number": "4242424242424242",
"name": "Gaurav",
"expiry_month": "11",
"expiry_year": "26",
"cvv": "100"
},
"metadata": {
"note_key": "value1"
}
}'Request fields
{
"payment_id": "FIATPESTK1CU1FNRXR1790705821",
"next": [
{
"action": "redirect",
"url": "https://api.fiatpe.com/v1/payments/FIATPESTK1CU1FNRXR1790705821/authentication/"
}
]
}Redirect the customer’s browser to next[0].url to complete card authentication. Do not call this URL from your backend.
HTML form flow
A card can also return next[0].action as html_form. The following test-card example demonstrates this response flow.
REQUEST
curl --location 'https://api.fiatpe.com/v1/payments/s2s/' \
--header 'Authorization: Basic <base64(api_key:secret_key)>' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 5000,
"currency": "INR",
"contact": "+919898989898",
"name": "Aftab Hussain",
"email": "customer@example.com",
"order_id": "order_b515d1952d194824",
"return_url": "https://example.com/payment/return",
"callback_url": "https://api.example.com/webhooks/fiatpe",
"description": "Test payment",
"method": "card",
"card": {
"number": "4000000000000002",
"name": "Gaurav",
"expiry_month": "11",
"expiry_year": "26",
"cvv": "100"
},
"metadata": {
"note_key": "value1"
}
}'Request fields
{
"payment_id": "FIATPEST8OJ7CDB2BI1790705845",
"next": [
{
"action": "html_form",
"html_content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Redirecting | FiatPe</title>\n <script src=\"https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js\"></script>\n</head>\n<body>\n <div class=\"redirect-container\">\n <div id=\"lottie-loader\"></div>\n <h1>Redirecting...</h1>\n <p>Please wait while we redirect you securely. Do not close this window.</p>\n <form id=\"payment-form\" method=\"GET\"\n action=\"https://api.fiatpe.com/v1/payments/FIATPEST8OJ7CDB2BI1790705845/authentication/\"\n hidden>\n <input type=\"hidden\" name=\"paymentMode\" value=\"CARD\">\n </form>\n <noscript>\n <button type=\"submit\" form=\"payment-form\">Continue to payment</button>\n </noscript>\n </div>\n <script>\n if (window.lottie) {\n lottie.loadAnimation({\n container: document.getElementById(\"lottie-loader\"),\n renderer: \"svg\",\n loop: true,\n autoplay: true,\n path: \"https://bucket.fiatpe.com/static/animation/lottie/fiatpe_pg_processing_loader.json\"\n });\n }\n window.setTimeout(function () {\n document.getElementById(\"payment-form\").submit();\n }, 1000);\n </script>\n</body>\n</html>"
}
]
}Render the returned html_content as a full HTML document in the customer’s browser. The included form continues the card authentication flow automatically.
Complete card authentication
- Use the URL associated with
otp_submitto submit the customer’s OTP. - Use the URL associated with
resend_otponly when the customer requests another OTP. - For a
redirectaction, navigate the customer’s browser to the returned URL. - For an
html_formaction, return the HTML document to the browser with atext/htmlcontent type. - Never log or persist OTP values.
- Do not treat OTP submission as proof of payment success.
- Confirm the final status on your backend and process webhooks idempotently.