Saved cards & off-session charges

Save a buyer's card once, then charge it later without the buyer present (off-session) — for renewals, top-ups or one-click purchases. The card number never touches your servers or FastStar's; you only ever hold a FastStar token (pm_xxx) and masked card data.

Server-side sequence

  1. Create a customer

    Customers own saved payment methods. email is required:

    curl https://api.faststarpay.com/api/v1/public/customers \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "email": "[email protected]", "name": "Jane Buyer" }'
  2. Create a SetupIntent

    curl -X POST https://api.faststarpay.com/api/v1/public/customers/cus_xxx/setup-intent \
      -H "X-API-Key: YOUR_API_KEY"

    Response data:

    { "client_secret": "seti_xxx_secret_xxx", "publishable_key": "pk_live_xxx", "setup_intent_id": "seti_xxx" }
  3. Collect the card in the browser

    Hand the SetupIntent result to your front end and open the secure card popup with FastStar.cards.add(session, callbacks). When the buyer saves the card, the card page attaches it by calling:

    curl -X POST https://api.faststarpay.com/api/v1/public/customers/cus_xxx/payment-methods \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "setup_intent_id": "seti_xxx" }'

    Response data is the masked payment method — store its id:

    { "id": "pm_xxx", "brand": "visa", "last4": "4242", "exp_month": 12, "exp_year": 2030 }
  4. Charge the saved card off-session

    curl -X POST https://api.faststarpay.com/api/v1/public/customers/cus_xxx/charge \
      -H "X-API-Key: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "payment_method_id": "pm_xxx",
        "amount": 1999,
        "currency": "USD",
        "off_session": true
      }'

    Response data:

    {
      "payment_intent_id": "pi_xxx",
      "status": "succeeded",
      "amount": 1999,
      "currency": "USD",
      "payment_method_id": "pm_xxx"
    }

Handling SCA: HTTP 402

Some banks require Strong Customer Authentication (e.g. 3-D Secure) even for off-session charges. When the bank demands authentication, the charge endpoint responds with HTTP 402 Payment Required:

{ "success": false, "message": "Payment requires additional authentication" }

How to handle it:

  • The charge has not completed — do not fulfill.
  • Bring the customer back on-session to authenticate: for example, create a Checkout Session and ask them to complete the payment in the hosted checkout, where the 3-D Secure challenge can run.
  • For subscription-style billing, notify the customer (email/in-app) with a link to that on-session flow.

Server-side example (Node)

const BASE = 'https://api.faststarpay.com/api/v1';
const HEADERS = {
  'Content-Type': 'application/json',
  'X-API-Key': process.env.FASTSTAR_API_KEY,
};

// charge a saved card; returns the payment or flags that SCA is needed
async function chargeSavedCard(customerId, paymentMethodId, amount, currency) {
  const r = await fetch(`${BASE}/public/customers/${customerId}/charge`, {
    method: 'POST',
    headers: HEADERS,
    body: JSON.stringify({
      payment_method_id: paymentMethodId,
      amount,                 // smallest currency unit
      currency,
      off_session: true,
    }),
  });

  if (r.status === 402) {
    // SCA required: send the customer to an on-session flow to authenticate
    return { requiresAction: true };
  }

  const { data } = await r.json();
  return { requiresAction: false, payment: data };
}

Related endpoints: list saved cards with GET /public/customers/:id/payment-methods, set a default with POST /public/payment-methods/:id/default, and detach with DELETE /public/payment-methods/:id. See the API reference.