---
title: "SetupIntents"
description: "7 operations, with parameters and examples."
url: https://docs.fluveo.com/api/setup_intents/
---

> Index of every page: https://docs.fluveo.com/llms.txt. Integrating Fluveo? Read https://docs.fluveo.com/agents/integrate.md first.

> Too long? This page with code in one language only: https://docs.fluveo.com/api/setup_intents.curl.md (cURL), https://docs.fluveo.com/api/setup_intents.node.md (Node.js), https://docs.fluveo.com/api/setup_intents.python.md (Python), https://docs.fluveo.com/api/setup_intents.php.md (PHP).

# SetupIntents

7 operations, with parameters and examples.

A SetupIntent saves a card for later payments without charging it, such as a card on file for one-click upsells. Create one with the customer and the card, confirm it, send the buyer through next_action when the bank asks for 3D Secure, and charge the saved payment_method later with off_session=true. A SetupIntent created without payment_method_types has automatic_payment_methods enabled with allow_redirects=always: its confirm, or its create with confirm=true, needs return_url, unless the create sent automatic_payment_methods[allow_redirects]=never; without one it answers 400 return_url_required and sets nothing up (see Errors).

Send every request to `https://api.fluveo.com/v1` with your secret key as a Bearer token. This page lists only what Fluveo serves; [the OpenAPI file](https://docs.fluveo.com/openapi.json) holds the same operations.

An operation or a parameter marked **Preview** works, but it is not locked yet and may change: [what Preview means](https://docs.fluveo.com/api.md#preview).

> **For AI agents:**
>
> Use plain HTTP; install no payments SDK. Send `Authorization: Bearer sk_test_...` and a fresh `Idempotency-Key` on every POST; reuse the same key only when you retry that same POST. Send only the documented parameters. An operation or a parameter marked Preview may change: prefer the ones without the mark.

## Lists a SetupIntent's confirm attempts, newest first (Preview)

`GET /v1/setup_attempts`

Permission: none. [No restricted key](https://docs.fluveo.com/permissions.md#no-restricted-key) may call this operation; only a secret key may.

**Preview:** this operation works, but it is not locked yet; it may change.

**Query parameters**

- `created` (object, optional): Filter on the creation time, a Unix timestamp: created=<t> for an exact match, or created[gt], created[gte], created[lt], created[lte].
- `ending_before` (string, optional): Cursor: the id of the first object of the current page, to get the previous page. Do not send it with starting_after.
- `limit` (integer, optional): How many objects to return, from 1 to 100. Default 10.
- `setup_intent` (string, required): The SetupIntent whose attempts are listed.
- `starting_after` (string, optional): Cursor: the id of the last object of the previous page, to get the next page. Do not send it with ending_before.

**Headers**

- `Fluveo-Version` (enum, optional): Optional. The only version Fluveo serves is 2026-05-27.dahlia; any other value is refused with a 400. Every answer names that version in its own Fluveo-Version header, except the refusals Fluveo gives before it reads the request (no key, an unknown key, an unknown URL, a body that is not a form) and a file's bytes, which name no version and no Request-Id.

  One of: `2026-05-27.dahlia`.

Returns a list of [`setup_attempt`](https://docs.fluveo.com/api/setup_intents.md#object-setup_attempt) objects.

**Request**

cURL:

```bash
curl -G https://api.fluveo.com/v1/setup_attempts \
  -H "Authorization: Bearer sk_test_..." \
  --data-urlencode "setup_intent=seti_123"
```

Node.js:

```javascript
const response = await fetch("https://api.fluveo.com/v1/setup_attempts" + "?" + new URLSearchParams([["setup_intent","seti_123"]]), {
  method: "GET",
  headers: {
    "Authorization": "Bearer sk_test_...",
  },
});
console.log(await response.json());
```

Python:

```python
import requests

response = requests.get(
    "https://api.fluveo.com/v1/setup_attempts",
    headers={"Authorization": "Bearer sk_test_..."},
    params=[("setup_intent", "seti_123")],
)
print(response.json())
```

PHP:

```php
<?php
$ch = curl_init("https://api.fluveo.com/v1/setup_attempts?setup_intent=seti_123");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer sk_test_...",
    ],
]);
echo curl_exec($ch);
```

## Creates a SetupIntent, and confirms it at once with confirm=true

`POST /v1/setup_intents`

Permission: [`rak_setup_intent_write`](https://docs.fluveo.com/permissions.md#setup_intent).

**Headers**

- `Idempotency-Key` (string, optional): Send a unique key, 1 to 255 characters, on every POST. A retry with the same key and the same body returns the first answer instead of acting twice (with Idempotent-Replayed: true); the same key with another body is refused. Keys are kept 7 days, except on POST /v1/checkout/sessions, POST /v1/checkout/sessions/{session} and POST /v1/webhook_endpoints, where a key holds 24 hours; webhook endpoint keys are also capped at the newest 32 per store and mode. Do not rely on a replay after that window. GET and DELETE ignore it.
- `Fluveo-Version` (enum, optional): Optional. The only version Fluveo serves is 2026-05-27.dahlia; any other value is refused with a 400. Every answer names that version in its own Fluveo-Version header, except the refusals Fluveo gives before it reads the request (no key, an unknown key, an unknown URL, a body that is not a form) and a file's bytes, which name no version and no Request-Id.

  One of: `2026-05-27.dahlia`.

**Body parameters**

- `attach_to_self` (boolean, optional): A flag for a payment method attached to the account itself. A card cannot be: the SetupIntent keeps the value, and its confirm is refused with payment_method_unsupported_type. Not with customer.
- `automatic_payment_methods` (object, optional): enabled=true (the default when payment_method_types is not sent) with allow_redirects always (the default) or never; enabled=false only together with payment_method_types. Judged as on a PaymentIntent, and served back on the object. Not taken by update or confirm.
  - `allow_redirects` (enum, optional): One of: `always`, `never`.
  - `enabled` (boolean, optional)
- `confirm` (boolean, optional, preview): true confirms the SetupIntent in the same call.
- `confirmation_token` (string, optional, preview): A ConfirmationToken to confirm with. Fluveo makes none, so any value answers resource_missing.
- `customer` (string, optional): The customer the card is saved for. Once the SetupIntent succeeds, the payment method is attached to this customer.
- `description` (string, optional, preview): A note for your own records.
- `excluded_payment_method_types` (array of string, optional, preview): Payment method types to leave out; not with payment_method_types. Excluding card leaves no type and is refused.
- `flow_directions` (array of enum, optional, preview): The directions the card is set up for: inbound only, since a card cannot be paid out to (outbound is refused).

  One of: `inbound`, `outbound`.
- `mandate_data` (object, optional, preview): The customer's acceptance of a mandate, checked field by field. Only with confirm=true. A card makes no mandate, so mandate stays null.
  - `customer_acceptance` (object, optional)
    - `accepted_at` (integer, optional)
    - `offline` (object, optional)
    - `online` (object, optional)
      - `ip_address` (string, optional)
      - `user_agent` (string, optional)
    - `type` (enum, optional): One of: `offline`, `online`.
- `metadata` (object, optional): Your own keys and values.
- `on_behalf_of` (string, optional, preview): Another account to set the card up for. A Fluveo store has none, so any value answers resource_missing.
- `payment_method` (string, optional, preview): The card to set up: a PaymentMethod of the store, or a test PaymentMethod name such as pm_card_visa in test mode.
- `payment_method_data` (object, optional, preview): A new card to set up, instead of payment_method: payment_method_data[type]=card with the card in payment_method_data[card] (number, exp_month, exp_year, cvc), for a store with raw card data access. The card becomes a new PaymentMethod, which the SetupIntent names. Do not send it together with payment_method.
  - `allow_redisplay` (enum, optional): Whether the new PaymentMethod may be shown to the customer again: always, limited or unspecified (the default).

    One of: `always`, `limited`, `unspecified`.
  - `billing_details` (object, optional): The card holder's name, email, phone and address, kept on the new PaymentMethod.
    - `address` (object, optional)
      - `city` (string, optional)
      - `country` (string, optional)
      - `line1` (string, optional)
      - `line2` (string, optional)
      - `postal_code` (string, optional)
      - `state` (string, optional)
    - `email` (string, optional)
    - `name` (string, optional)
    - `phone` (string, optional)
    - `tax_id` (string, optional)
  - `metadata` (object, optional): Your own key-value pairs for the new PaymentMethod.
  - `type` (enum, optional): card, the only type a SetupIntent sets up.

    One of: `card`.
- `payment_method_options` (object, optional, preview): Card options: request_three_d_secure, mandate_options, and with confirm=true network and three_d_secure. An option of another type answers unsupported.
  - `card` (object, optional): Card options.
    - `mandate_options` (object, optional): The mandate an Indian card needs for later charges: amount, amount_type (fixed or maximum), currency, interval (day, week, month, year or sporadic), reference, start_date and supported_types[] (india) are required, description, end_date and interval_count optional. Sent whole each time and kept on the SetupIntent; a card that is not Indian makes no mandate.
      - `amount` (integer, optional)
      - `amount_type` (enum, optional): One of: `fixed`, `maximum`.
      - `currency` (string, optional)
      - `description` (string, optional)
      - `end_date` (integer, optional)
      - `interval` (enum, optional): One of: `day`, `month`, `sporadic`, `week`, `year`.
      - `interval_count` (integer, optional)
      - `reference` (string, optional)
      - `start_date` (integer, optional)
      - `supported_types` (array of string, optional)
    - `network` (enum, optional): The card network to use for this card. On a create it needs confirm=true and must be a network the card carries; a confirm keeps it on the SetupIntent and uses it when the card carries it, and a confirm without it clears it.

      One of: `amex`, `cartes_bancaires`, `diners`, `discover`, `eftpos_au`, `girocard`, `interac`, `jcb`, `link`, `mastercard`, `unionpay`, `visa`, `unknown`.
    - `request_three_d_secure` (enum, optional): automatic (the default) asks for 3D Secure when the bank or the card network requires it; any and challenge ask for it whenever the card supports it.

      One of: `automatic`, `any`, `challenge`.
    - `three_d_secure` (object, optional): 3D Secure results your own authentication already got (version, cryptogram, transaction_id, electronic_commerce_indicator, ares_trans_status, requestor_challenge_indicator, network_options[cartes_bancaires]), used by this confirm instead of a new challenge. Only with a confirm, never with request_three_d_secure in the same request, and never shown or kept on the SetupIntent.
      - `ares_trans_status` (enum, optional): One of: `A`, `C`, `I`, `N`, `R`, `U`, `Y`.
      - `cryptogram` (string, optional)
      - `electronic_commerce_indicator` (enum, optional): One of: `01`, `02`, `05`, `06`, `07`.
      - `network_options` (object, optional)
      - `requestor_challenge_indicator` (string, optional)
      - `transaction_id` (string, optional)
      - `version` (enum, optional): One of: `1.0.2`, `2.1.0`, `2.2.0`, `2.3.0`, `2.3.1`.
- `payment_method_types` (array of enum, optional): card, or boleto on a store that takes Boleto. Without it, the SetupIntent has automatic_payment_methods and lists every method the store takes that its payment method configuration has on and that a SetupIntent saves (card, and boleto in Brazil; pix is never saved), less any excluded_payment_method_types. A confirm takes any method of the list.

  One of: `card`, `boleto`.
- `return_url` (string, optional, preview): Where the buyer comes back after 3D Secure. Only with confirm=true.
- `single_use` (object, optional, preview): amount and currency of a single-use mandate. Kept, but a card SetupIntent with it cannot be confirmed, since single_use is refused for a card.
  - `amount` (integer, optional)
  - `currency` (string, optional)
- `usage` (enum, optional, preview): off_session (the default) to charge the card later without the buyer, or on_session.

  One of: `off_session`, `on_session`.

Use only the documented body parameters. Send a new `Idempotency-Key` with each new request, and the same key again only to retry that request.

Returns a [`setup_intent`](https://docs.fluveo.com/api/setup_intents.md#object-setup_intent) object.

**Request**

cURL:

```bash
curl https://api.fluveo.com/v1/setup_intents \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: $(uuidgen)" \
  --data-urlencode "confirm=true" \
  --data-urlencode "customer=cus_123" \
  --data-urlencode "payment_method=pm_123" \
  --data-urlencode "return_url=https://example.com/saved" \
  --data-urlencode "usage=off_session"
```

Node.js:

```javascript
const response = await fetch("https://api.fluveo.com/v1/setup_intents", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sk_test_...",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: new URLSearchParams([["confirm","true"],["customer","cus_123"],["payment_method","pm_123"],["return_url","https://example.com/saved"],["usage","off_session"]]),
});
console.log(await response.json());
```

Python:

```python
import uuid

import requests

response = requests.post(
    "https://api.fluveo.com/v1/setup_intents",
    headers={"Authorization": "Bearer sk_test_...", "Idempotency-Key": str(uuid.uuid4())},
    data=[("confirm", "true"), ("customer", "cus_123"), ("payment_method", "pm_123"), ("return_url", "https://example.com/saved"), ("usage", "off_session")],
)
print(response.json())
```

PHP:

```php
<?php
$ch = curl_init("https://api.fluveo.com/v1/setup_intents");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer sk_test_...",
        "Idempotency-Key: " . bin2hex(random_bytes(16)),
    ],
    CURLOPT_POSTFIELDS => "confirm=true&customer=cus_123&payment_method=pm_123&return_url=https%3A%2F%2Fexample.com%2Fsaved&usage=off_session",
]);
echo curl_exec($ch);
```

## Lists the store's SetupIntents, newest first

`GET /v1/setup_intents`

Permission: [`rak_setup_intent_read`](https://docs.fluveo.com/permissions.md#setup_intent).

**Query parameters**

- `attach_to_self` (boolean, optional, preview): true lists only the SetupIntents created or updated with attach_to_self=true; false lists only the others.
- `created` (object, optional, preview): Filter on the creation time, a Unix timestamp: created=<t> for an exact match, or created[gt], created[gte], created[lt], created[lte].
- `customer` (string, optional): Only the SetupIntents of this customer.
- `ending_before` (string, optional, preview): Cursor: the id of the first object of the current page, to get the previous page. Do not send it with starting_after.
- `limit` (integer, optional): How many objects to return, from 1 to 100. Default 10.
- `payment_method` (string, optional, preview): Only the SetupIntents that use this payment method.
- `starting_after` (string, optional, preview): Cursor: the id of the last object of the previous page, to get the next page. Do not send it with ending_before.

**Headers**

- `Fluveo-Version` (enum, optional): Optional. The only version Fluveo serves is 2026-05-27.dahlia; any other value is refused with a 400. Every answer names that version in its own Fluveo-Version header, except the refusals Fluveo gives before it reads the request (no key, an unknown key, an unknown URL, a body that is not a form) and a file's bytes, which name no version and no Request-Id.

  One of: `2026-05-27.dahlia`.

Returns a list of [`setup_intent`](https://docs.fluveo.com/api/setup_intents.md#object-setup_intent) objects.

**Request**

cURL:

```bash
curl -G https://api.fluveo.com/v1/setup_intents \
  -H "Authorization: Bearer sk_test_..." \
  --data-urlencode "customer=cus_123"
```

Node.js:

```javascript
const response = await fetch("https://api.fluveo.com/v1/setup_intents" + "?" + new URLSearchParams([["customer","cus_123"]]), {
  method: "GET",
  headers: {
    "Authorization": "Bearer sk_test_...",
  },
});
console.log(await response.json());
```

Python:

```python
import requests

response = requests.get(
    "https://api.fluveo.com/v1/setup_intents",
    headers={"Authorization": "Bearer sk_test_..."},
    params=[("customer", "cus_123")],
)
print(response.json())
```

PHP:

```php
<?php
$ch = curl_init("https://api.fluveo.com/v1/setup_intents?customer=cus_123");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer sk_test_...",
    ],
]);
echo curl_exec($ch);
```

## Updates a SetupIntent's customer, payment method, description, metadata or 3D Secure request (Preview)

`POST /v1/setup_intents/{intent}`

Permission: [`rak_setup_intent_write`](https://docs.fluveo.com/permissions.md#setup_intent).

**Preview:** this operation works, but it is not locked yet; it may change.

**Path parameters**

- `intent` (string, required): The PaymentIntent's id.

**Headers**

- `Idempotency-Key` (string, optional): Send a unique key, 1 to 255 characters, on every POST. A retry with the same key and the same body returns the first answer instead of acting twice (with Idempotent-Replayed: true); the same key with another body is refused. Keys are kept 7 days, except on POST /v1/checkout/sessions, POST /v1/checkout/sessions/{session} and POST /v1/webhook_endpoints, where a key holds 24 hours; webhook endpoint keys are also capped at the newest 32 per store and mode. Do not rely on a replay after that window. GET and DELETE ignore it.
- `Fluveo-Version` (enum, optional): Optional. The only version Fluveo serves is 2026-05-27.dahlia; any other value is refused with a 400. Every answer names that version in its own Fluveo-Version header, except the refusals Fluveo gives before it reads the request (no key, an unknown key, an unknown URL, a body that is not a form) and a file's bytes, which name no version and no Request-Id.

  One of: `2026-05-27.dahlia`.

**Body parameters**

- `attach_to_self` (boolean, optional): A flag for a payment method attached to the account itself; true only together with payment_method. A card cannot be: its confirm is refused with payment_method_unsupported_type.
- `customer` (string, optional): The customer the card is saved for; it can be set once, and the same customer again changes nothing. Another customer, or an empty value, is refused.
- `description` (string, optional): A note for your own records; an empty value clears it.
- `flow_directions` (array of enum, optional): The directions the card is set up for: inbound only, since a card cannot be paid out to (outbound is refused).

  One of: `inbound`, `outbound`.
- `metadata` (object, optional): Your own keys and values; an empty value removes a key.
- `payment_method` (string, optional): The card to set up. The SetupIntent goes back to requires_confirmation.
- `payment_method_data` (object, optional): A new card to set up, instead of payment_method, as on create. The SetupIntent names the new PaymentMethod and goes back to requires_confirmation. Do not send it together with payment_method.
  - `allow_redisplay` (enum, optional): Whether the new PaymentMethod may be shown to the customer again: always, limited or unspecified (the default).

    One of: `always`, `limited`, `unspecified`.
  - `billing_details` (object, optional): The card holder's name, email, phone and address, kept on the new PaymentMethod.
    - `address` (object, optional)
      - `city` (string, optional)
      - `country` (string, optional)
      - `line1` (string, optional)
      - `line2` (string, optional)
      - `postal_code` (string, optional)
      - `state` (string, optional)
    - `email` (string, optional)
    - `name` (string, optional)
    - `phone` (string, optional)
    - `tax_id` (string, optional)
  - `metadata` (object, optional): Your own key-value pairs for the new PaymentMethod.
  - `type` (enum, optional): card, the only type a SetupIntent sets up.

    One of: `card`.
- `payment_method_options` (object, optional): Card options: request_three_d_secure, network and mandate_options. three_d_secure is taken only by a confirm, and an option of another type answers unsupported.
  - `card` (object, optional): Card options.
    - `mandate_options` (object, optional): The mandate an Indian card needs for later charges: amount, amount_type (fixed or maximum), currency, interval (day, week, month, year or sporadic), reference, start_date and supported_types[] (india) are required, description, end_date and interval_count optional. Sent whole each time and kept on the SetupIntent; a card that is not Indian makes no mandate.
      - `amount` (integer, optional)
      - `amount_type` (enum, optional): One of: `fixed`, `maximum`.
      - `currency` (string, optional)
      - `description` (string, optional)
      - `end_date` (integer, optional)
      - `interval` (enum, optional): One of: `day`, `month`, `sporadic`, `week`, `year`.
      - `interval_count` (integer, optional)
      - `reference` (string, optional)
      - `start_date` (integer, optional)
      - `supported_types` (array of string, optional)
    - `network` (enum, optional): A card network, checked and shown in this answer only: an update does not keep it, so the next read and the confirm do not have it.

      One of: `amex`, `cartes_bancaires`, `diners`, `discover`, `eftpos_au`, `girocard`, `interac`, `jcb`, `link`, `mastercard`, `unionpay`, `visa`, `unknown`.
    - `request_three_d_secure` (enum, optional): automatic (the default) asks for 3D Secure when the bank or the card network requires it; any and challenge ask for it whenever the card supports it.

      One of: `automatic`, `any`, `challenge`.
- `payment_method_types` (array of enum, optional): card, or boleto on a store that takes Boleto.

  One of: `card`, `boleto`.

Use only the documented body parameters. Send a new `Idempotency-Key` with each new request, and the same key again only to retry that request.

Returns a [`setup_intent`](https://docs.fluveo.com/api/setup_intents.md#object-setup_intent) object.

**Request**

cURL:

```bash
curl https://api.fluveo.com/v1/setup_intents/seti_123 \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: $(uuidgen)" \
  --data-urlencode "metadata[order_id]=1042"
```

Node.js:

```javascript
const response = await fetch("https://api.fluveo.com/v1/setup_intents/seti_123", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sk_test_...",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: new URLSearchParams([["metadata[order_id]","1042"]]),
});
console.log(await response.json());
```

Python:

```python
import uuid

import requests

response = requests.post(
    "https://api.fluveo.com/v1/setup_intents/seti_123",
    headers={"Authorization": "Bearer sk_test_...", "Idempotency-Key": str(uuid.uuid4())},
    data=[("metadata[order_id]", "1042")],
)
print(response.json())
```

PHP:

```php
<?php
$ch = curl_init("https://api.fluveo.com/v1/setup_intents/seti_123");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer sk_test_...",
        "Idempotency-Key: " . bin2hex(random_bytes(16)),
    ],
    CURLOPT_POSTFIELDS => "metadata%5Border_id%5D=1042",
]);
echo curl_exec($ch);
```

## Retrieves a SetupIntent. One that waits on the buyer's 3D Secure is read again from the card network first (Preview)

`GET /v1/setup_intents/{intent}`

Permission: [`rak_setup_intent_read`](https://docs.fluveo.com/permissions.md#setup_intent).

**Preview:** this operation works, but it is not locked yet; it may change.

**Path parameters**

- `intent` (string, required): The PaymentIntent's id.

**Headers**

- `Fluveo-Version` (enum, optional): Optional. The only version Fluveo serves is 2026-05-27.dahlia; any other value is refused with a 400. Every answer names that version in its own Fluveo-Version header, except the refusals Fluveo gives before it reads the request (no key, an unknown key, an unknown URL, a body that is not a form) and a file's bytes, which name no version and no Request-Id.

  One of: `2026-05-27.dahlia`.

Returns a [`setup_intent`](https://docs.fluveo.com/api/setup_intents.md#object-setup_intent) object.

**Request**

cURL:

```bash
curl https://api.fluveo.com/v1/setup_intents/seti_123 \
  -H "Authorization: Bearer sk_test_..."
```

Node.js:

```javascript
const response = await fetch("https://api.fluveo.com/v1/setup_intents/seti_123", {
  method: "GET",
  headers: {
    "Authorization": "Bearer sk_test_...",
  },
});
console.log(await response.json());
```

Python:

```python
import requests

response = requests.get(
    "https://api.fluveo.com/v1/setup_intents/seti_123",
    headers={"Authorization": "Bearer sk_test_..."},
)
print(response.json())
```

PHP:

```php
<?php
$ch = curl_init("https://api.fluveo.com/v1/setup_intents/seti_123");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer sk_test_...",
    ],
]);
echo curl_exec($ch);
```

## Cancels a SetupIntent that has not succeeded (Preview)

`POST /v1/setup_intents/{intent}/cancel`

Permission: [`rak_setup_intent_write`](https://docs.fluveo.com/permissions.md#setup_intent).

**Preview:** this operation works, but it is not locked yet; it may change.

**Path parameters**

- `intent` (string, required): The PaymentIntent's id.

**Headers**

- `Idempotency-Key` (string, optional): Send a unique key, 1 to 255 characters, on every POST. A retry with the same key and the same body returns the first answer instead of acting twice (with Idempotent-Replayed: true); the same key with another body is refused. Keys are kept 7 days, except on POST /v1/checkout/sessions, POST /v1/checkout/sessions/{session} and POST /v1/webhook_endpoints, where a key holds 24 hours; webhook endpoint keys are also capped at the newest 32 per store and mode. Do not rely on a replay after that window. GET and DELETE ignore it.
- `Fluveo-Version` (enum, optional): Optional. The only version Fluveo serves is 2026-05-27.dahlia; any other value is refused with a 400. Every answer names that version in its own Fluveo-Version header, except the refusals Fluveo gives before it reads the request (no key, an unknown key, an unknown URL, a body that is not a form) and a file's bytes, which name no version and no Request-Id.

  One of: `2026-05-27.dahlia`.

**Body parameters**

- `cancellation_reason` (enum, optional): Why the SetupIntent was canceled.

  One of: `abandoned`, `duplicate`, `requested_by_customer`.

Use only the documented body parameters. Send a new `Idempotency-Key` with each new request, and the same key again only to retry that request.

Returns a [`setup_intent`](https://docs.fluveo.com/api/setup_intents.md#object-setup_intent) object.

**Request**

cURL:

```bash
curl https://api.fluveo.com/v1/setup_intents/seti_123/cancel \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: $(uuidgen)" \
  --data-urlencode "cancellation_reason=requested_by_customer"
```

Node.js:

```javascript
const response = await fetch("https://api.fluveo.com/v1/setup_intents/seti_123/cancel", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sk_test_...",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: new URLSearchParams([["cancellation_reason","requested_by_customer"]]),
});
console.log(await response.json());
```

Python:

```python
import uuid

import requests

response = requests.post(
    "https://api.fluveo.com/v1/setup_intents/seti_123/cancel",
    headers={"Authorization": "Bearer sk_test_...", "Idempotency-Key": str(uuid.uuid4())},
    data=[("cancellation_reason", "requested_by_customer")],
)
print(response.json())
```

PHP:

```php
<?php
$ch = curl_init("https://api.fluveo.com/v1/setup_intents/seti_123/cancel");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer sk_test_...",
        "Idempotency-Key: " . bin2hex(random_bytes(16)),
    ],
    CURLOPT_POSTFIELDS => "cancellation_reason=requested_by_customer",
]);
echo curl_exec($ch);
```

## Confirms a SetupIntent: the card is set up, or the buyer is sent to 3D Secure through next_action

`POST /v1/setup_intents/{intent}/confirm`

Permission: [`rak_setup_intent_write`](https://docs.fluveo.com/permissions.md#setup_intent).

**Path parameters**

- `intent` (string, required): The PaymentIntent's id.

**Headers**

- `Idempotency-Key` (string, optional): Send a unique key, 1 to 255 characters, on every POST. A retry with the same key and the same body returns the first answer instead of acting twice (with Idempotent-Replayed: true); the same key with another body is refused. Keys are kept 7 days, except on POST /v1/checkout/sessions, POST /v1/checkout/sessions/{session} and POST /v1/webhook_endpoints, where a key holds 24 hours; webhook endpoint keys are also capped at the newest 32 per store and mode. Do not rely on a replay after that window. GET and DELETE ignore it.
- `Fluveo-Version` (enum, optional): Optional. The only version Fluveo serves is 2026-05-27.dahlia; any other value is refused with a 400. Every answer names that version in its own Fluveo-Version header, except the refusals Fluveo gives before it reads the request (no key, an unknown key, an unknown URL, a body that is not a form) and a file's bytes, which name no version and no Request-Id.

  One of: `2026-05-27.dahlia`.

**Body parameters**

- `confirmation_token` (string, optional, preview): A ConfirmationToken to confirm with. Fluveo makes none, so any value answers resource_missing.
- `mandate_data` (object, optional, preview): The customer's acceptance of a mandate, checked field by field. A card makes no mandate, so mandate stays null.
  - `customer_acceptance` (object, optional)
    - `accepted_at` (integer, optional)
    - `offline` (object, optional)
    - `online` (object, optional)
      - `ip_address` (string, optional)
      - `user_agent` (string, optional)
    - `type` (enum, optional): One of: `offline`, `online`.
- `payment_method` (string, optional): The card to set up, when the SetupIntent has none yet or should use another.
- `payment_method_data` (object, optional, preview): A new card to set up in this confirm, instead of payment_method, as on create. Do not send it together with payment_method.
  - `allow_redisplay` (enum, optional): Whether the new PaymentMethod may be shown to the customer again: always, limited or unspecified (the default).

    One of: `always`, `limited`, `unspecified`.
  - `billing_details` (object, optional): The card holder's name, email, phone and address, kept on the new PaymentMethod.
    - `address` (object, optional)
      - `city` (string, optional)
      - `country` (string, optional)
      - `line1` (string, optional)
      - `line2` (string, optional)
      - `postal_code` (string, optional)
      - `state` (string, optional)
    - `email` (string, optional)
    - `name` (string, optional)
    - `phone` (string, optional)
    - `tax_id` (string, optional)
  - `metadata` (object, optional): Your own key-value pairs for the new PaymentMethod.
  - `type` (enum, optional): card, the only type a SetupIntent sets up.

    One of: `card`.
- `payment_method_options` (object, optional, preview): Card options: request_three_d_secure, network, mandate_options and three_d_secure. An option of another type answers unsupported.
  - `card` (object, optional): Card options.
    - `mandate_options` (object, optional): The mandate an Indian card needs for later charges: amount, amount_type (fixed or maximum), currency, interval (day, week, month, year or sporadic), reference, start_date and supported_types[] (india) are required, description, end_date and interval_count optional. Sent whole each time and kept on the SetupIntent; a card that is not Indian makes no mandate.
      - `amount` (integer, optional)
      - `amount_type` (enum, optional): One of: `fixed`, `maximum`.
      - `currency` (string, optional)
      - `description` (string, optional)
      - `end_date` (integer, optional)
      - `interval` (enum, optional): One of: `day`, `month`, `sporadic`, `week`, `year`.
      - `interval_count` (integer, optional)
      - `reference` (string, optional)
      - `start_date` (integer, optional)
      - `supported_types` (array of string, optional)
    - `network` (enum, optional): The card network to use for this card. On a create it needs confirm=true and must be a network the card carries; a confirm keeps it on the SetupIntent and uses it when the card carries it, and a confirm without it clears it.

      One of: `amex`, `cartes_bancaires`, `diners`, `discover`, `eftpos_au`, `girocard`, `interac`, `jcb`, `link`, `mastercard`, `unionpay`, `visa`, `unknown`.
    - `request_three_d_secure` (enum, optional): automatic (the default) asks for 3D Secure when the bank or the card network requires it; any and challenge ask for it whenever the card supports it.

      One of: `automatic`, `any`, `challenge`.
    - `three_d_secure` (object, optional): 3D Secure results your own authentication already got (version, cryptogram, transaction_id, electronic_commerce_indicator, ares_trans_status, requestor_challenge_indicator, network_options[cartes_bancaires]), used by this confirm instead of a new challenge. Only with a confirm, never with request_three_d_secure in the same request, and never shown or kept on the SetupIntent.
      - `ares_trans_status` (enum, optional): One of: `A`, `C`, `I`, `N`, `R`, `U`, `Y`.
      - `cryptogram` (string, optional)
      - `electronic_commerce_indicator` (enum, optional): One of: `01`, `02`, `05`, `06`, `07`.
      - `network_options` (object, optional)
      - `requestor_challenge_indicator` (string, optional)
      - `transaction_id` (string, optional)
      - `version` (enum, optional): One of: `1.0.2`, `2.1.0`, `2.2.0`, `2.3.0`, `2.3.1`.
- `return_url` (string, optional): Where the buyer comes back after 3D Secure.

Use only the documented body parameters. Send a new `Idempotency-Key` with each new request, and the same key again only to retry that request.

Returns a [`setup_intent`](https://docs.fluveo.com/api/setup_intents.md#object-setup_intent) object.

**Request**

cURL:

```bash
curl https://api.fluveo.com/v1/setup_intents/seti_123/confirm \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: $(uuidgen)" \
  --data-urlencode "payment_method=pm_123" \
  --data-urlencode "return_url=https://example.com/saved"
```

Node.js:

```javascript
const response = await fetch("https://api.fluveo.com/v1/setup_intents/seti_123/confirm", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sk_test_...",
    "Idempotency-Key": crypto.randomUUID(),
  },
  body: new URLSearchParams([["payment_method","pm_123"],["return_url","https://example.com/saved"]]),
});
console.log(await response.json());
```

Python:

```python
import uuid

import requests

response = requests.post(
    "https://api.fluveo.com/v1/setup_intents/seti_123/confirm",
    headers={"Authorization": "Bearer sk_test_...", "Idempotency-Key": str(uuid.uuid4())},
    data=[("payment_method", "pm_123"), ("return_url", "https://example.com/saved")],
)
print(response.json())
```

PHP:

```php
<?php
$ch = curl_init("https://api.fluveo.com/v1/setup_intents/seti_123/confirm");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => "POST",
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer sk_test_...",
        "Idempotency-Key: " . bin2hex(random_bytes(16)),
    ],
    CURLOPT_POSTFIELDS => "payment_method=pm_123&return_url=https%3A%2F%2Fexample.com%2Fsaved",
]);
echo curl_exec($ch);
```

## The setup_attempt object

Ids start with `setatt_`.

**Attributes**

- `application` (enum, nullable): One of: `null`.
- `attach_to_self` (boolean)
- `created` (integer)
- `customer` (string, nullable, expandable): An id by default; send `expand[]=customer` to get the full customer or deleted_customer object.
- `customer_account` (enum, nullable): One of: `null`.
- `flow_directions` (array, nullable)
- `id` (string)
- `livemode` (boolean)
- `object` (enum): One of: `setup_attempt`.
- `on_behalf_of` (enum, nullable): One of: `null`.
- `payment_method` (string, expandable): An id by default; send `expand[]=payment_method` to get the full payment_method object.
- `payment_method_details` (object)
- `setup_error` (object, nullable)
- `setup_intent` (string, expandable): An id by default; send `expand[]=setup_intent` to get the full setup_intent object.
- `status` (string)
- `usage` (string)

## The setup_intent object

Ids start with `seti_`.

**Attributes**

- `allowed_payment_method_types` (enum, nullable): One of: `null`.
- `application` (enum, nullable): One of: `null`.
- `attach_to_self` (boolean)
- `automatic_payment_methods` (object, nullable)
- `cancellation_reason` (enum, nullable): One of: `abandoned`, `duplicate`, `requested_by_customer`.
- `client_secret` (string, nullable)
- `created` (integer)
- `customer` (string, nullable, expandable): An id by default; send `expand[]=customer` to get the full customer or deleted_customer object.
- `customer_account` (string, nullable)
- `description` (string, nullable)
- `excluded_payment_method_types` (array, nullable)
- `flow_directions` (array, nullable)
- `id` (string)
- `last_setup_error` (object, nullable)
- `latest_attempt` (string, nullable, expandable): An id by default; send `expand[]=latest_attempt` to get the full setup_attempt object.
- `livemode` (boolean)
- `managed_payments` (object, nullable)
- `mandate` (enum, nullable): One of: `null`.
- `metadata` (object, nullable)
- `next_action` (object, nullable)
- `object` (enum): One of: `setup_intent`.
- `on_behalf_of` (enum, nullable): One of: `null`.
- `payment_method` (string, nullable, expandable): An id by default; send `expand[]=payment_method` to get the full payment_method object.
- `payment_method_configuration_details` (object, nullable)
- `payment_method_options` (object, nullable)
- `payment_method_types` (array)
- `single_use_mandate` (enum, nullable): One of: `null`.
- `status` (enum): One of: `canceled`, `processing`, `requires_action`, `requires_confirmation`, `requires_payment_method`, `succeeded`.
- `usage` (string)
