# Save a payment method

Request owner-hosted card setup, verify the saved result, and keep charging permission separate.

## One owner handoff

An agent can request a saved card without handling card numbers, creating an email account or collecting owner credentials. This is optional preparation for future payment workflows. Automatic refills and agent-initiated saved-card charges are not available yet. Existing balance top-ups still use an owner-approved checkout.

Use a live key with campaigns:write and send an empty JSON object:

```http
POST /api/v1/billing/setups
Authorization: Bearer $MR_API_KEY
Idempotency-Key: save-card-001
Content-Type: application/json

{}
```

Give owner_url to the owner. They sign in to the same workspace, consent to saving a card, and follow secure checkout. The agent receives no hosted setup URL, payment token, member identifier, raw card data or charging permission. Saving a card is independent of adding funds and approving advertising. No funds are collected by these endpoints.

## Read the result

GET /api/v1/billing/setups/{id} requires campaigns:read. States are awaiting_owner, creating, checkout_ready, outcome_unknown, saved, revoked and expired. Only saved means the provider confirmed a usable card and its billing member for this exact approved checkout. The public response includes the card brand and last four when known, automatic_refills_enabled:false and charge_authority:none. GET never contacts the provider or mutates payment state.

Poll no faster than retry_after_seconds, pause polling when the owner is not interacting, and stop on a terminal state. A setup request expires after 23 hours; expires_at applies to the request, not the card's expiry date. Saved references remain until removed. List requests through GET /api/v1/billing/setups; follow next_cursor in descending UUID order, up to 50 records per page.

The signed callback and background reconciliation normally update the result. If confirmation is delayed, POST /api/v1/billing/setups/{id}/reconcile with {} and campaigns:read. Each call reads one provider page of up to 25 successful intents, retaining its scan position. Retry at the advertised interval until found; this does not create another checkout or charge.

The owner return page can supply {"setup_intent_id":"sint_..."} as a lookup hint. A redirect, URL query, screenshot or success flag never proves that a card was saved. The server retrieves the intent and checks its account, checkout, owner metadata, versioned consent, payment method and billing member before recording success.

## Retries and cancellation

Keep the same Idempotency-Key after a request timeout. Creation replay returns the original request, including after cancellation or expiry. A different request while one is pending returns payment_setup_pending with details.setup_id; continue that ID. There are at most ten new requests per workspace per 24 hours. Sandbox keys cannot access real setup.

Only the signed-in owner can POST /api/v1/billing/setups/{id}/approve with {"consent":true}. Concurrent requests use one stored provider operation. outcome_unknown means retry the same approval after five seconds; do not create a new request. Provider account changes or missing member permissions require operator review.

Only the owner can DELETE /api/v1/billing/setups/{id}. This revokes the workspace reference and is safe to repeat. Late callbacks cannot restore a revoked or expired request. Removal does not delete the owner's card from the payment provider's account or other products. Owners can manage this under Dashboard → Balance → Payment methods.

## Spending remains separate

Neither a saved card nor this consent authorizes an automatic debit. A future refill feature must obtain a separate owner mandate with a total charge cap, expiry and revocation, include payment costs and taxes, verify each receipt, and retain the campaign's independent spending approval. Do not promise automatic funding from this setup status.
