> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.fluveo.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.fluveo.com/_mcp/server.

# Overview

The Fluveo API is served under the `/v1/*` path prefix and uses familiar PaymentIntent-style requests and responses, so existing v1-style integrations and compatible tooling work as-is.

## Base URL

* Test and live mode: `https://api.devfluveo.com`

The authenticated key selects mode; there is no separate sandbox hostname.

## Authentication

The `/v1` API accepts the same secret-key auth schemes declared by Stripe OpenAPI:

| Scheme          | Example                             |
| --------------- | ----------------------------------- |
| HTTP Basic Auth | `curl -u sk_test_...:`              |
| Bearer Auth     | `Authorization: Bearer sk_test_...` |

Docs and runnable examples prefer Basic Auth because that is Stripe's canonical curl form. Secret keys are server-side credentials: `sk_test_...` for sandbox and `sk_live_...` for production. Publishable keys (`pk_test_...`, `pk_live_...`) are browser-side keys and are not valid for secret-key server operations. The launch `/v1` surface does **not** accept an `api-key` header — secret keys are the only supported credential.

Create a key from the dashboard **API keys** page (it is shown exactly once). See [authentication](/authentication) for the full key lifecycle.

```bash
curl https://api.devfluveo.com/v1/payment_intents \
  -u sk_test_...: \
  -d amount=4242 \
  -d currency=usd
```

## Request bodies

Write operations take `application/x-www-form-urlencoded` bodies, exactly like Stripe. Nested values use bracket syntax — `metadata[order_id]=ord_9001` for maps and `expand[]=latest_charge` for arrays. curl's `-d` sets the form content type automatically; use `--data-urlencode` for values with reserved characters.

```bash
curl https://api.devfluveo.com/v1/payment_intents \
  -u sk_test_...: \
  -d amount=4242 \
  -d currency=usd \
  --data-urlencode 'metadata[order_id]=ord_9001' \
  -d 'expand[]=latest_charge'
```

Unsupported or internal fields are rejected with an `invalid_request_error` that names the offending `param`. Public responses use Stripe object and field names (`id`, `object`, `customer`, `payment_intent`) and never leak internal identifiers.

## Idempotency

Add an `Idempotency-Key` header to safely retry a request. Fluveo caches the response for 24 hours and returns the cached response on duplicate keys — matching the retry semantics developers expect from familiar payment APIs.

```bash
curl https://api.devfluveo.com/v1/payment_intents \
  -u sk_test_...: \
  -H "Idempotency-Key: $(uuidgen)" \
  -d amount=4242 \
  -d currency=usd
```

## Versioning

The v1 surface is pinned to a curated, machine-checked launch contract. The current upstream compatibility baseline is Stripe API `2026-05-27.dahlia`. Breaking shape changes require a public versioning decision and a deprecation period. Additive fields ship without a version bump only when they preserve Stripe semantics.

## Errors

Errors return v1-compatible JSON:

```json
{
  "error": {
    "type":    "invalid_request_error",
    "code":    "amount_too_small",
    "message": "Amount must be at least 50",
    "param":   "amount"
  }
}
```

Error `type` values:

* `api_error` — Fluveo internal error (5xx)
* `invalid_request_error` — your request was malformed (4xx)
* `authentication_error` — your API key is missing or invalid
* `card_error` — the customer's card was declined or rate-limited
* `idempotency_error` — Idempotency-Key conflict
* `rate_limit_error` — too many requests

## External card vault (VGS outbound proxy)

Browser card entry uses VGS Collect so PAN/CVC is collected outside Fluveo. Fluveo surfaces only receive VGS aliases (for example, `tok_sandbox_xxxx`), and reject real card numbers or security codes.

When the router calls a PSP, egress goes through the VGS outbound proxy. VGS reveals the aliases to card data only at the boundary toward the PSP. This flow is PSP-agnostic; the current development/sandbox PSP is Stripe sandbox.

## Webhooks

Register webhook endpoints under `/v1/webhook_endpoints` — each with its own `whsec_...` secret and an `enabled_events` filter (exact event types or the `*` wildcard) — and browse recorded events under `/v1/events`. Deliveries are signed HMAC-SHA256 and carry a Fluveo-branded `Fluveo-Signature` header alongside a compatibility `Stripe-Signature` header, so existing webhook verification code keeps working while keeping Fluveo as the product surface. Endpoint management, the signature contract, and **signed delivery are live today** — a triggered event fans out to every subscribed endpoint, each `POST` signed with that endpoint's own secret. See [Webhooks](/webhooks) and the [event types](/webhooks/event-types) catalog.

## Endpoint reference

Every live endpoint is documented in the **[API Reference](/api-reference)**, generated directly from the canonical OpenAPI contract. For which resources are live versus not yet implemented, see **[API coverage](/api-coverage)**.