Server-to-Server Payments

Available via: API only (private key)

Overview

Server-to-server (S2S) payments let you collect card details on your own frontend and process the payment entirely through the API. This gives you full control over the checkout experience.

Important: S2S card payments require sending card data to https://api-card.inflowpay.com (not the standard API URL). This endpoint handles PCI-compliant card tokenization.

Prerequisites

Server-to-server payments must be enabled on your account before you can use them. If S2S is not enabled, you will receive the error:

"Not authorized to create payment, server to server payment not enabled, please contact support"

Contact [email protected] to request activation.

When to Use S2S

ApproachBest For
Hosted Checkout (payment links)Simple integration, no frontend work needed
SDK (iframe card form)Custom checkout with PCI compliance handled for you
Server-to-ServerFull control, custom UI, PCI-compliant infrastructure

Payment Flow

Step 1: Create the Payment

curl -X POST https://api-card.inflowpay.com/api/server/payment \
  -H "X-Inflow-Api-Key: inflow_priv_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "products": [
      { "name": "Pro Plan", "price": 4999, "quantity": 1 }
    ],
    "currency": "EUR",
    "customerEmail": "[email protected]",
    "billingCountry": "FR",
    "postalCode": "75001",
    "purchasingAsBusiness": false,
    "firstName": "John",
    "lastName": "Doe",
    "autoConfirm": true,
    "pricingMode": "TAX_EXCLUSIVE",
    "threeDsSuccessUrl": "https://yoursite.com/3ds-success",
    "threeDsFailureUrl": "https://yoursite.com/3ds-failure",
    "metadatas": {
      "orderId": "order_12345"
    }
  }'

Request Body

FieldTypeRequiredDescription
productsarrayYesList of products (name, price in cents, quantity)
currencystringYesEUR or USD
customerEmailstringYesCustomer's email address
billingCountrystringYesISO 3166-1 alpha-2 country code (e.g., FR, DE, US)
purchasingAsBusinessbooleanYesWhether the customer is purchasing as a business
postalCodestringIf USBilling postal code (required for US customers)
businessNamestringIf businessBusiness name (required if purchasingAsBusiness is true)
taxIdstringIf businessTax ID (required if purchasingAsBusiness is true)
firstNamestringNoCustomer first name (recommended for 3DS)
lastNamestringNoCustomer last name (recommended for 3DS)
savePaymentMethodbooleanNoSave the card for future use (default: false). See Saving and reusing payment methods below.
useCustomerPaymentMethodbooleanNoUse the customer's last saved payment method (default: false). See Saving and reusing payment methods below.
autoConfirmbooleanNoAuto-confirm if no 3DS required (default: false)
pricingModestringNoTAX_EXCLUSIVE (default) or TAX_INCLUSIVE
threeDsSuccessUrlstringNoRedirect URL after successful 3DS
threeDsFailureUrlstringNoRedirect URL after failed 3DS
metadatasobjectNoCustom metadata

Response

{
  "id": "pay_abc123",
  "amountInCents": 4999,
  "currency": "EUR",
  "status": "INITIATION",
  "customerEmail": "[email protected]",
  "threeDsSessionUrl": null
}

Step 2: Handle 3D Secure (If Required)

If threeDsSessionUrl is not null, the customer's bank requires 3DS authentication:

  1. Redirect the customer to the threeDsSessionUrl.
  2. The customer completes authentication with their bank.
  3. The customer is redirected to your threeDsSuccessUrl or threeDsFailureUrl.

Step 3: Confirm the Payment

After 3DS completion (or if no 3DS was required and autoConfirm is false), you must explicitly confirm the payment. You can check whether confirmation is needed by looking at the depositStatus field — if it shows "requires_confirmation", call:

curl -X POST https://api.inflowpay.xyz/api/server/payment/{paymentId}/confirm \
  -H "X-Inflow-Api-Key: inflow_priv_your_key"

If autoConfirm: true was set and no 3DS was required, the payment is confirmed automatically.

SDK users: If you use the Inflow SDK (iframe card form), the SDK handles confirmation automatically — you do not need to call this endpoint.

Step 4: Verify Payment Status

curl https://api.inflowpay.xyz/api/payment/{paymentId} \
  -H "X-Inflow-Api-Key: inflow_priv_your_key"

Or set up a webhook to receive automatic notifications when the payment status changes.

Saving and Reusing Payment Methods

You can save a customer's card for future purchases and reuse it without asking them to enter their card details again.

How it works

  • savePaymentMethod: true — When the customer pays with a card, that card is saved and linked to their email (customerEmail). Use this on the first payment when you want to allow one-click or faster checkout later.
  • useCustomerPaymentMethod: true — For a returning customer, use their last saved card instead of collecting new card details. The customer must use the same customerEmail as when the card was saved.

You cannot use both parameters in the same request: either you save a new card, or you use an existing one.

Typical flow

  1. First purchase — Customer enters their card. Send savePaymentMethod: true to store it.
  2. Later purchases — Customer returns (same email). Send useCustomerPaymentMethod: true and omit card details. The payment uses the saved card.

Important: last saved card is used

When useCustomerPaymentMethod: true is set, the system charges the last saved card for that customer. If a customer saves multiple cards over time, the most recently saved card becomes the active one.

Selecting a specific card among multiple saved payment methods is not currently supported but is planned. Contact [email protected] for updates.

Customer identification

The saved payment method is tied to customerEmail. For reuse to work, the customer must use the same email address across payments. If they have no saved card yet, useCustomerPaymentMethod: true will fail.

Update a Payment Before Confirmation

You can update a server payment before it's finalized:

curl -X POST https://api.inflowpay.xyz/api/server/payment/{paymentId} \
  -H "X-Inflow-Api-Key: inflow_priv_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "products": [
      { "name": "Updated Product", "price": 5999, "quantity": 1 }
    ]
  }'

Error Handling

If the payment fails, check the lastDepositAttempt field in the payment object:

{
  "lastDepositAttempt": {
    "status": "failed",
    "amount": 4999,
    "paymentMethod": "CARD",
    "error": "card_declined",
    "attemptedAt": "2025-01-15T10:31:00.000Z"
  }
}

See Error Handling for a complete list of error codes.

Minimum Payment Amounts

Each currency has a minimum payment amount. Payments below these thresholds will be rejected:

CurrencyMinimum Amount
EUR€1.50 (150 cents)
GBP£1.00 (100 cents)
USD$2.00 (200 cents)

Tips

  • Always provide firstName and lastName — this significantly improves 3DS authentication success rates.
  • Use autoConfirm: true for a smoother flow when 3DS is not required.
  • Set up webhooks instead of polling for payment status updates.
  • Tax is calculated automatically based on billingCountry.