API Reference

Payment (CP) - Stripe - PayFac API

Card-Present payments done using Stripe terminal/reader hardware and the PayFac API.

Overview

The PayFac API now supports API only requests for card-present (CP) payments without the need to use the Stripe JS SDK. This is now the preferred method for handling CP payments and is also consistent with the rest of the API experience.

Collecting payment

A basic example of collecting payment requires 3 types of API calls:

  • Payment Intent (describes how we intend to collect payment and the initial properties for the payment)
  • Auth (initiates the collection of a card payment from the terminal)
  • Status Get (gets the status of the payment)

Creating the Payment Intent

You will first need to create a payment intent either server side or client-side by calling the Payment CREATE API endpoint (POST /v2/payment/intent).

// POST /v2/payment/intent
{
    "external_account_id": "account_123456",
    "amount": 12.99,
    "payment_method_types": "card_present",
    "capture_method": "automatic",
    "external_payment_id": "transaction_123456"
}

This will return a result that has a payment_id and you'll need this id to authorize the payment.

Collect Payment (asynchronous)

To request a payment from a specific terminal, call the following endpoint (POST /v2/payment/auth). Please note that in this case terminal_id and payment_id are required. Also note that this call is asynchronous. This means the call will return immediately even though the terminal has not collected payment yet. This call will return the payment details with a status of payment_method_requested.

// POST /v2/payment/auth  
{  
    "external_account_id": "account_123456",  
    "payment_id": "pi_12345",  
    "terminal_id": "tmr_12345",
    "external_payment_id": "transaction_123456"
}

Poll Payment Status (asynchronous)

You will need to poll the API for the payment status. We suggest you have a polling cycle of around 1 second for a responsive UI, but if that is not necessary 2 seconds would be nice. This is done through the following endpoint (GET /v2/payment/intent/[ID]) and will return a result like the following:

{
  "external_transaction_id": "transaction_123456",
  "currency": "usd",
  "amount": 12.99,
  "amount_authorized": 0,
  "amount_refunded": 0,
  "amount_cancelled": 0,
  "amount_captured": 0,
  "amount_capturable": 0,
  "amount_refundable": 0,
  "status": "requires_payment_method",
  "date_created": "2025-09-19T21:26:35+00:00",
  "dispute_status": null,
  "card_present": false,
  "payment_method_types": "card_present",
  "notes": "",
  "authorization_code": null,
  "last_payment_error": null,
  "processor": "Stripe",
  "payment_id": "pi_12345",
  "payment": [],
  "payment_method_id": "",
  "request_id": 275350
}

While polling, monitor the status of the payment, the following status values are possible

  • requires_payment_method: This means we are still waiting on the terminal. Keep polling.
  • succeeded: This means the payment has been collected and captured. Stop polling.
  • requires_capture: This means the payment has been collected and authorized. If you had specified manual capture, then you can stop polling, but if you had specified automatic capture, then you will need to continue polling until you get a status of succeeded.