API v1FiatPe Home
FiatPeDocs
SERVER 2 SERVER

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 guide

Supported card networks

FiatPe Server-to-Server card payments support the following card networks, subject to your account configuration and acquiring setup.

Card networkAvailability
VisaSupported
MastercardSupported
American ExpressSupported
BajajSupported
MaestroSupported
RuPaySupported
DinersAvailable only to private limited companies and registered businesses.

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.

Test flowCard numberExpiryCVVExpected action
Native OTP4111 1111 1111 111111/26100otp_submit and resend_otp
Redirect4242 4242 4242 424211/26100redirect
HTML form4000 0000 0000 000211/26100html_form
Test every response flow in UAT before going live.

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.

Process card payments using network tokens
STEP 1

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.

Open the Create Order API reference

Server request example

Use your FiatPe credentials only from a trusted backend environment.

REQUEST

Curl
Copy
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.

200 OK
Copy
{
  "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."
}
STEP 2

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.

Card data requires PCI DSS compliance.

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
Copy
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

FieldRequiredDescription
amountYesPayment amount in the currency’s smallest sub-unit.
currencyYesThree-letter currency code, such as INR.
contactYesCustomer phone number including the country code.
nameYesCustomer’s full name.
emailYesCustomer email address.
order_idYesOrder ID returned in Step 1.
callback_urlNoOptional HTTPS endpoint on your server where FiatPe sends asynchronous payment updates.
descriptionNoDescription associated with the payment.
methodYesSet to card.
card.numberYesCard number without spaces. Never store or log this value.
card.nameYesName printed on the card.
card.expiry_monthYesTwo-digit expiry month.
card.expiry_yearYesTwo-digit expiry year.
card.cvvYesCard verification value. Never store this value.
metadataNoMerchant-defined key-value data associated with the payment.

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.

200 OK
Copy
{
  "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/"
    }
  ]
}
STEP 3

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
Copy
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.

200 OK
Copy
{
  "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.

ScenarioTest OTPExpected result
Payment Failure111111Simulates a failed transaction. The payment status will be marked as failed.
Incorrect OTP222222Simulates an incorrect OTP. OTP verification will fail.
Sandbox only

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.

STEP 4

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
Copy
curl --location --request POST 'https://api.fiatpe.com/v1/payments/FIATPESTCM3YWO15VB1790705241/otp/resend/' \
  --header 'Authorization: Basic <base64(api_key:secret_key)>' \
  --data ''

Response

200 OK
Copy
{
  "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
Copy
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

FieldRequiredDescription
amountYesPayment amount in the currency’s smallest sub-unit.
currencyYesThree-letter currency code, such as INR.
contactYesCustomer phone number including the country code.
nameYesCustomer’s full name.
emailYesCustomer email address.
order_idYesOrder ID returned in Step 1.
return_urlYesHTTPS URL to which the customer is redirected after card authentication completes. By default, the redirect uses the POST method.
callback_urlNoOptional HTTPS endpoint for asynchronous payment updates.
descriptionNoDescription associated with the payment.
methodYesSet to card.
card.numberYesCard number without spaces. Never store or log this value.
card.nameYesName printed on the card.
card.expiry_monthYesTwo-digit expiry month.
card.expiry_yearYesTwo-digit expiry year.
card.cvvYesCard verification value. Never store or log it.
metadataNoMerchant-defined key-value data associated with the payment.
200 OK
Copy
{
  "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
Copy
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

FieldRequiredDescription
amountYesPayment amount in the currency’s smallest sub-unit.
currencyYesThree-letter currency code, such as INR.
contactYesCustomer phone number including the country code.
nameYesCustomer’s full name.
emailYesCustomer email address.
order_idYesOrder ID returned in Step 1.
return_urlYesHTTPS URL to which the customer is redirected after card authentication completes. By default, the redirect uses the POST method.
callback_urlNoOptional HTTPS endpoint for asynchronous payment updates.
descriptionNoDescription associated with the payment.
methodYesSet to card.
card.numberYesCard number without spaces. Never store or log this value.
card.nameYesName printed on the card.
card.expiry_monthYesTwo-digit expiry month.
card.expiry_yearYesTwo-digit expiry year.
card.cvvYesCard verification value. Never store or log it.
metadataNoMerchant-defined key-value data associated with the payment.
200 OK
Copy
{
  "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_submit to submit the customer’s OTP.
  • Use the URL associated with resend_otp only when the customer requests another OTP.
  • For a redirect action, navigate the customer’s browser to the returned URL.
  • For an html_form action, return the HTML document to the browser with a text/html content 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.