# Save payment details during payment with Direct API

This guide shows how to **charge now** and **store the card for future charges** in a single server-side call by creating a `PaymentIntent` that includes `payment_method_data` and `setup_future_usage`.


> **PCI-DSS scope notice** 
> Posting PAN/CVC directly to your servers places you in **SAQ D** scope. If you want to minimize PCI burden, use Drop-in or Checkout instead.



# 1. Prerequisites

| Item               | Notes                                                        |
| ------------------ | ------------------------------------------------------------ |
| **Secret key**     | Use **server-side** only.                                    |
| **Customer ID**    | Reuse an existing customer or create one with `POST /v1/customers` (email recommended). |
| **Return** **URL** | A page to receive the user after 3-D Secure (`return_url`).  |
| **Webhooks**       | Expose an HTTPS endpoint. Treat **`payment_intent.succeeded`** as the **authoritative** payment-success signal (and that the card is saved to the customer). |

# 2. Create & confirm a PaymentIntent (pay and save)

[**Create a PaymentIntent**](api-42631218)

*request*

```JSON
{
  "amount": 100,
  "currency": "USD",
  "confirm": true,
  "customer": "cus_1760950869144109056",
  "payment_method_data": {
    "type": "card",
    "card": {
      "exp_month": "01",
      "exp_year": "2027",
      "number": "4111111111111111",
      "cvc": "022",
      "name": "XX XXX"
    }
  },
  "setup_future_usage": "on_session",
  "return_url": "https://yourwebsite.com"
}
```

**Outcomes**

- **Frictionless success** → `status: "succeeded"` (no 3DS).
- **3-D Secure required** → `status: "requires_action"` with a `next_action`.
- **Failure** → `status: "requires_payment_method"` (invalid card, insufficient funds, etc.).

# 3. Complete 3-D Secure (if `requires_action`)

If the response is:

```JSON
{
  "id": "pi_XXXX",
  "status": "requires_action",
  ....
  "next_action": {
    "type": "challenge_redirect",
    "challenge_redirect": {
      "url": "https://jstest.wooshpay.com/v1/3ds/index.html?...",
      "return_url": "https://yourwebsite.com"
    }
  },
  "customer": "cus_1760950869144109056",
  "payment_method": "pm_XXXX",
  .....
}
```

Do this:

1. **Redirect the customer** to `next_action.challenge_redirect.url`.
2. They complete the bank challenge and are returned to your `return_url`.
3. **Do not** assume success solely from the redirect. Your **source of truth** is the webhook in the next section.

> Optional: You may poll `GET /v1/payment_intents/{id}`, but rely on the webhook for final state.

# 4. Handle webhooks

Enable and handle at least:

| **Event**                | **Purpose**                                                  | **What to store**                                            |
| ------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| payment_intent.succeeded | Authoritative indicator that the payment completed and the card was saved to the customer (because setup_future_usage was set and customer supplied). | Persist (customer_id, payment_method_id) for future charges. You can read event.data.object.payment_method. |

Example（abridged）

```JSON
{
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "id": "pi_XXXX",
      "status": "succeeded",
      ....
      "customer": "cus_XXXXXXXXXX",
      "payment_method": "pm_XXXXXXXXXXXX",
      ....
    }
  }
}
```

# 5. Charge the card later

[**Create a PaymentIntent**](api-42631218)

```JSON
{
  "amount": 2500,
  "currency": "USD",
  "confirm": true,
  "off_session": false,          // true if no user present
  "customer": "cus_1953770230215868416",
  "payment_method": "pm_123123123",
  "return_url": "https://example.com/pay/complete"
}
```

| Key point        | Value                                                        |
| ---------------- | ------------------------------------------------------------ |
| `customer`       | ID from Step 1.                                              |
| `payment_method` | Saved card’s ID from webhook or listing API.                 |
| `off_session`    | `false`to attempt and on-session charge(user present now)`true` to attempt an off-session charge (recurring / unsupervised). |

**Status guide (server actions)**

| `payment_intent.status`   | Meaning                         | Your next step                                 |
| ------------------------- | ------------------------------- | ---------------------------------------------- |
| `requires_payment_method` | Card entry/processing failure   | Show error; allow new card.                    |
| `requires_action`         | 3-D Secure step-up required     | Redirect to `next_action.XXXX.XXXX`.           |
| `processing`              | Bank/network is processing      | Wait for webhook; avoid duplicate submissions. |
| `succeeded`               | Paid and card saved to customer | Persist mapping; fulfill the order.            |

# 6. Testing

| **Action**               | **Test card number** | **Notes**                              |
| ------------------------ | -------------------- | -------------------------------------- |
| Successful save + charge | 4111 4111 41111 4111 | Any future date, any CVC               |
| 3-D Secure required      | 4462030000000000     | Checkout will prompt for 3DS challenge |

Use your **test secret key** and point webhooks to your dev endpoint.

# Quick reference

| Task                    | API                                                          |
| ----------------------- | ------------------------------------------------------------ |
| Create customer         | `POST /v1/customers`                                         |
| Pay & save (Direct API) | `POST /v1/payment_intents` (with `payment_method_data` + `setup_future_usage`) |
| Authoritative success   | `payment_intent.succeeded`                                   |
| Charge later            | `POST /v1/payment_intents` (with `customer` + saved `payment_method`) |
