# Payment methods

> Save, retrieve, and detach reusable payment methods.

A payment method stores reusable card or bank details attached to a customer. Save a payment method
once and reference its `pm_` ID on any future payment or subscription — no need to re-collect card
details.

> **Illustrative content.** Hand-authored to demonstrate the Standard/Advanced pattern; the production
> page will be generated from the VINR OpenAPI spec (roadmap item #1). Field names are representative.

## The payment method object

- **id** `string` — Unique identifier for the payment method, e.g. `pm_9bR3`.
- **type** `string` — The instrument type. Currently `card`; additional types (e.g. `sepa_debit`) are roadmap items.
- **card** `object` — Present when `type` is `card`.
  - **brand** `string` — Card network, e.g. `visa`, `mastercard`.
  - **last4** `string` — Last four digits of the card number.
  - **exp\_month** `integer` — Two-digit expiry month.
  - **exp\_year** `integer` — Four-digit expiry year.
- **billing\_details** `object` — Billing contact associated with this payment method.
  - **email** `string` — Billing email address.
  - **name** `string` — Cardholder name as it appears on the card.
- **customer** `object` (expandable) — The customer this payment method is attached to, if any. Expand to retrieve the full object.
  - **id** `string` — Customer identifier, e.g. `cust_8aZ2`.
  - **email** `string` — Email address on the customer record.
- **created** `integer` — Unix timestamp when the payment method was created.

## Create a payment method

Pass `type` and the card credentials. After creating, attach the method to a customer by updating
the customer's `default_payment_method` or referencing the `pm_` ID directly on a payment.

`POST /v1/payment-methods`

```bash
curl -X POST https://api.vinr.com/v1/payment-methods \
-H "X-Api-Key: $VINR_SECRET_KEY" \
-d type=card \
-d "card[number]=4242424242424242" \
-d "card[exp_month]=12" \
-d "card[exp_year]=2027" \
-d "card[cvc]=314"
```

```js
import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const paymentMethod = await vinr.paymentMethods.create({
type: 'card',
card: {
  number: '4242424242424242',
  exp_month: 12,
  exp_year: 2027,
  cvc: '314',
},
});
```

```python
import vinr

payment_method = vinr.PaymentMethod.create(
  type="card",
  card={
      "number": "4242424242424242",
      "exp_month": 12,
      "exp_year": 2027,
      "cvc": "314",
  },
)
```

```ruby
payment_method = Vinr::PaymentMethod.create(
type: 'card',
card: {
  number: '4242424242424242',
  exp_month: 12,
  exp_year: 2027,
  cvc: '314',
},
)
```

```json
{
"id": "pm_9bR3",
"type": "card",
"card": {
  "brand": "visa",
  "last4": "4242",
  "exp_month": 12,
  "exp_year": 2027
},
"billing_details": {
  "email": null,
  "name": null
},
"customer": null,
"created": 1716300000
}
```

#### Advanced (Enterprise) — tokenization and PCI scope reduction

In production, card numbers should never pass through your server. Use the VINR.js client-side
library to tokenize the card in the browser and receive a single-use `pm_token_*` reference.
Exchange it for a reusable `pm_` on your server with a single API call — your server never sees
raw card data.

```ts
// Client (browser) — VINR.js
const { token } = await vinr.createToken({
  type: 'card',
  card: cardElement,          // VINR.js UI component
});

// Server — exchange token for reusable payment method
const paymentMethod = await vinr.paymentMethods.createFromToken({
  token: token.id,
  customer: 'cust_8aZ2',
});
```

This keeps your integration out of PCI DSS scope (SAQ A rather than SAQ D).

## Retrieve a payment method

`GET /v1/payment-methods/{id}`

```bash
curl https://api.vinr.com/v1/payment-methods/pm_9bR3 \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
const paymentMethod = await vinr.paymentMethods.retrieve('pm_9bR3');
```

```python
payment_method = vinr.PaymentMethod.retrieve("pm_9bR3")
```

```ruby
payment_method = Vinr::PaymentMethod.retrieve("pm_9bR3")
```

```json
{
"id": "pm_9bR3",
"type": "card",
"card": {
  "brand": "visa",
  "last4": "4242",
  "exp_month": 12,
  "exp_year": 2027
},
"billing_details": {
  "email": "jenny@example.com",
  "name": "Jenny Rosen"
},
"customer": "cust_8aZ2",
"created": 1716300000
}
```

## Update a payment method

Only `billing_details` fields can be updated on an existing payment method. Card credentials are
immutable — create a new payment method to change the card.

`POST /v1/payment-methods/{id}`

```bash
curl -X POST https://api.vinr.com/v1/payment-methods/pm_9bR3 \
-H "X-Api-Key: $VINR_SECRET_KEY" \
-d "billing_details[email]=jenny.rosen@example.com"
```

```js
const paymentMethod = await vinr.paymentMethods.update('pm_9bR3', {
billing_details: { email: 'jenny.rosen@example.com' },
});
```

```python
payment_method = vinr.PaymentMethod.modify(
  "pm_9bR3",
  billing_details={"email": "jenny.rosen@example.com"},
)
```

```ruby
payment_method = Vinr::PaymentMethod.update(
"pm_9bR3",
billing_details: { email: 'jenny.rosen@example.com' },
)
```

```json
{
"id": "pm_9bR3",
"type": "card",
"card": {
  "brand": "visa",
  "last4": "4242",
  "exp_month": 12,
  "exp_year": 2027
},
"billing_details": {
  "email": "jenny.rosen@example.com",
  "name": "Jenny Rosen"
},
"customer": "cust_8aZ2",
"created": 1716300000
}
```

## Detach a payment method

Removes the payment method from its customer. The object is retained but can no longer be used for
new charges.

`POST /v1/payment-methods/{id}/detach`

```bash
curl -X POST https://api.vinr.com/v1/payment-methods/pm_9bR3/detach \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
const paymentMethod = await vinr.paymentMethods.detach('pm_9bR3');
```

```python
payment_method = vinr.PaymentMethod.detach("pm_9bR3")
```

```ruby
payment_method = Vinr::PaymentMethod.detach("pm_9bR3")
```

```json
{
"id": "pm_9bR3",
"type": "card",
"card": {
  "brand": "visa",
  "last4": "4242",
  "exp_month": 12,
  "exp_year": 2027
},
"billing_details": {
  "email": "jenny.rosen@example.com",
  "name": "Jenny Rosen"
},
"customer": null,
"created": 1716300000
}
```

## List payment methods

Returns all payment methods attached to a customer. Filter by `type` to narrow results.

`GET /v1/payment-methods`

```bash
curl "https://api.vinr.com/v1/payment-methods?customer=cust_8aZ2&type=card&limit=10" \
-H "X-Api-Key: $VINR_SECRET_KEY"
```

```js
const paymentMethods = await vinr.paymentMethods.list({
customer: 'cust_8aZ2',
type: 'card',
limit: 10,
});
```

```python
payment_methods = vinr.PaymentMethod.list(
  customer="cust_8aZ2",
  type="card",
  limit=10,
)
```

```ruby
payment_methods = Vinr::PaymentMethod.list(
customer: 'cust_8aZ2',
type: 'card',
limit: 10,
)
```

```json
{
"object": "list",
"data": [
  {
    "id": "pm_9bR3",
    "type": "card",
    "card": {
      "brand": "visa",
      "last4": "4242",
      "exp_month": 12,
      "exp_year": 2027
    },
    "billing_details": {
      "email": "jenny.rosen@example.com",
      "name": "Jenny Rosen"
    },
    "customer": "cust_8aZ2",
    "created": 1716300000
  }
],
"has_more": false
}
```

## Related events

`payment_method.created`, `payment_method.updated`, `payment_method.detached`. See [Events](/docs/api-reference/events).
