---
title: "Platforms and checkouts"
description: "How a checkout platform sends payments to Fluveo with each merchant's own Fluveo key."
url: https://docs.fluveo.com/platforms/
---

> 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/platforms.curl.md (cURL), https://docs.fluveo.com/platforms.node.md (Node.js), https://docs.fluveo.com/platforms.python.md (Python), https://docs.fluveo.com/platforms.php.md (PHP).

# Platforms and checkouts

How a checkout platform sends payments to Fluveo with each merchant's own Fluveo key.

A platform, in Fluveo's words, is a checkout: the software where a buyer fills the cart and pays. The platform does not own the payments. It only sends each payment to Fluveo on behalf of the merchant who runs the store.

## One merchant, one Fluveo account, one key

Every merchant opens its own Fluveo account. The account has an id that starts with `mch_`, and the merchant creates its own secret keys in the [Fluveo Dashboard](https://dash.fluveo.com), under **Settings**, **API keys**. Then the merchant pastes its secret key into the platform's settings.

- The platform keeps one Fluveo key per merchant, and calls `/v1` with that merchant's key for that merchant's payments.
- The platform never holds a Fluveo key of its own that reaches every store. There is no such key.
- There is no header that acts for another account. A request that sends one gets a `400` error that names the header.
- Fields that route money to someone else are refused by name with a `400`: `transfer_data`, `on_behalf_of`, `application_fee_amount`, `transfer_group` and the like. A platform cannot take a fee or split a payment through the API.

## Money and events stay with the merchant

Because every call carries the merchant's own key, everything it creates belongs to that merchant:

- PaymentIntents, Checkout Sessions, refunds and disputes live in the merchant's account and are read with the merchant's key.
- `GET /v1/balance` and payouts show the merchant's own money.
- Webhook endpoints are created with the merchant's key, so each endpoint gets only that merchant's events, signed with that endpoint's own `whsec_` secret.

**Check which account a pasted key belongs to**

cURL:

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

Node.js:

```javascript
const response = await fetch("https://api.fluveo.com/v1/account", {
  headers: { Authorization: "Bearer sk_test_..." },
});
const account = await response.json();
console.log(account.id, account.country, account.default_currency);
```

Python:

```python
import requests

response = requests.get(
    "https://api.fluveo.com/v1/account",
    headers={"Authorization": "Bearer sk_test_..."},
)
account = response.json()
print(account["id"], account["country"], account["default_currency"])
```

PHP:

```php
<?php
$ch = curl_init("https://api.fluveo.com/v1/account");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer sk_test_..."],
]);
$account = json_decode(curl_exec($ch), true);
echo $account["id"], " ", $account["country"], " ", $account["default_currency"];
```

The answer's `id` is the merchant's `mch_` id, `country` is `US` or `BR`, and `default_currency` is that account's currency. A platform can make this call right after the merchant pastes the key, to show which Fluveo account it is connected to.

## Build a platform integration

If you build a checkout that many merchants use, follow these rules.

### Step 1: Ask each merchant for its own secret key

Show a field where the merchant pastes its Fluveo secret key. Store it encrypted on your server, next to that merchant's store. Never send it to the browser and never write it to a log.

### Step 2: Check the key once

Call `GET /v1/account` with the key. A `401` means the key is wrong. Keep the `mch_` id it returns, so you can show the merchant which account is connected.

### Step 3: Send every request with that merchant's key

Use plain HTTP with `Authorization: Bearer <the merchant's key>`. Install no server SDK and send no header that acts for another account. Send an `Idempotency-Key` on every POST and reuse it when you retry the same request.

### Step 4: Receive that merchant's events

Create a webhook endpoint with the merchant's key, keep its `whsec_` secret beside that merchant, and check the `Fluveo-Signature` header of each event with that secret.

## When a merchant changes its key

In the Dashboard, a merchant can rotate a key and choose when the old key expires: now, or in 1 hour, 24 hours, 3 days or 7 days. Both keys work until then, so the merchant can paste the new key into the platform before the old one stops. After the expiration, or at once with **Now** or **Expire key**, the platform's calls with the old key answer `401` with code `api_key_expired` until the new key is pasted. A merchant linked to several platform accounts keeps one named key for each; rotating or expiring one never stops the others.

## Test it

- Paste a `sk_test_...` key and call `GET /v1/account`: you get the `mch_` id of that test account.
- Send a `sk_live_...` key: you get a `403`. Fluveo serves test mode only for now.

> **For AI agents:**
>
> On a platform, each merchant uses its own Fluveo secret key; there is no platform-wide key. Never send a header that acts for another account, transfer_data, on_behalf_of or application_fee_amount: Fluveo refuses them. Never ask a merchant for a live key; build and test with sk_test_ keys only. Keep each merchant's key and its whsec_ secret server side, one pair per merchant.

## Platforms

- [Shopify](https://docs.fluveo.com/platforms/shopify.md): no integration today.
- [WooCommerce](https://docs.fluveo.com/platforms/woocommerce.md): no plugin today.

## Next

- [Authentication](https://docs.fluveo.com/start/authentication.md): keys, the Bearer header and the errors a wrong key gets.
- [Idempotency](https://docs.fluveo.com/start/idempotency.md): how to retry a POST safely.
- [Webhooks](https://docs.fluveo.com/webhooks.md) and [checking signatures](https://docs.fluveo.com/webhooks/signatures.md).
- [The Account object](https://docs.fluveo.com/api/account.md) in the API reference.
