---
title: "Payment methods"
description: "Adding, changing and removing a card."
url: "https://saved.sh/docs/billing/payment-methods"
---

Cards are handled by our payment processor. **We never see or store a card number**; what we
hold is an identifier, the brand, the last four digits and the expiry.

Everything here needs `billing:write`, which is **human-only**. A machine key cannot add,
change or remove a payment method, whatever permissions you try to give it.

## Adding a card [#adding-a-card]

Use the dashboard, under **Settings → Billing**. It is a two-step flow, and the card details
go from your browser to the processor without passing through us.

Via the API, the same two steps:

**1. Begin setup.**

```bash
curl -fsS -X POST "https://api.saved.sh/v1/workspaces/$WID/payment-methods" \
  -H "Authorization: Bearer $TOKEN"
```

```json
{ "id": "seti_1A...", "client_secret": "seti_1A..._secret_..." }
```

**2. Collect the card with the processor's own client library**, using that
`client_secret`, then confirm:

```bash
curl -fsS -X POST "https://api.saved.sh/v1/workspaces/$WID/payment-methods/confirm" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"setup_intent_id": "seti_1A...", "make_default": true}'
```

<Callout type="error">
  **Never send raw card details to our API.** There is no endpoint that accepts them, and there
  will not be. The `client_secret` exists so the card goes from the browser to the processor
  directly, which is what keeps card data out of our systems entirely.
</Callout>

## Listing [#listing]

```bash
curl -fsS "https://api.saved.sh/v1/workspaces/$WID/payment-methods" \
  -H "Authorization: Bearer $TOKEN"
```

```json
{
  "data": [
    { "id": "pm_1A...", "brand": "visa", "last4": "4242",
      "exp_month": 12, "exp_year": 2028, "default": true }
  ]
}
```

`wallet` appears when the method came from Apple Pay, Google Pay or similar.

Permission: `billing:read`.

## Setting the default [#setting-the-default]

```bash
curl -fsS -X POST "https://api.saved.sh/v1/workspaces/$WID/payment-methods/$PM_ID/default" \
  -H "Authorization: Bearer $TOKEN"
```

The default is what gets charged. A workspace with several cards and no default cannot be
charged, so set one.

## Removing [#removing]

```bash
curl -fsS -X DELETE "https://api.saved.sh/v1/workspaces/$WID/payment-methods/$PM_ID" \
  -H "Authorization: Bearer $TOKEN"
```

<Callout type="warn">
  Removing the only card does not close the workspace or stop usage accruing. It means the next
  invoice cannot be paid, which starts the
  [billing ladder](/docs/billing/credit#when-it-runs-out): warned, then stopped after 7 days,
  then blocked after 30. Add a replacement before removing the last one.
</Callout>

## Expiry [#expiry]

An expiring card is the most common cause of a workspace drifting into `warned`. The card's
`exp_month` and `exp_year` are on the listing, so it is checkable:

```bash
curl -fsS "https://api.saved.sh/v1/workspaces/$WID/payment-methods" -H "Authorization: Bearer $TOKEN" \
  | jq -r '.data[] | select(.default) | "default card expires \(.exp_month)/\(.exp_year)"'
```

Worth a calendar reminder. Nothing about a backup product should fail because of a card, but
the ladder is the same either way.

## What we store [#what-we-store]

| We hold                                 | We never hold                           |
| --------------------------------------- | --------------------------------------- |
| A processor identifier for the method   | The card number                         |
| Brand, last four, expiry month and year | CVC                                     |
| Whether it is the default               | Anything that could charge it elsewhere |

The brand and last four are also recorded on the [audit trail](/docs/security/audit-log) when
a method is added, defaulted or removed, so a change is attributable. The card number appears
in neither.

## Failed payments [#failed-payments]

A failed charge moves the workspace to `warned`. Runs continue, and so do reads.

| Elapsed     | State     | Effect                                     |
| ----------- | --------- | ------------------------------------------ |
| Immediately | `warned`  | Nothing stops                              |
| 7 days      | `stopped` | New runs stop. Config and reads still work |
| 30 days     | `blocked` | Config changes stop too. Reads still work  |

Fixing the card returns the workspace to `active`. Backups resume from the next scheduled
fire; missed runs are not replayed.

## Invoices [#invoices]

See [Invoices](/docs/billing/invoices) for what was charged and the hosted receipt.

## Next [#next]

<Cards>
  <Card href="/docs/billing/invoices" title="Invoices" description="Receipts and the upcoming charge." />

  <Card href="/docs/billing/credit" title="Credit" description="Discounts and the signup credit." />
</Cards>
