---
title: "API overview"
description: "The Flume Partner API is a JSON API over HTTPS under /partner/v1. This page covers base URLs, headers, formats, pagination, versioning and what is not built."
url: https://docs.tryflume.ai/api
updated: 2026-11-11
---

# API overview

> The Flume Partner API is a JSON API over HTTPS under /partner/v1. This page covers base URLs, headers, formats, pagination, versioning and what is not built.

The Flume Partner API is a JSON API over HTTPS. Your backend calls it with a partner key. This page covers what every endpoint shares.

## How it fits together

An API integration makes these calls, in this order. The [API quickstart](https://docs.tryflume.ai/quickstart/api.md) runs each one.

1. **Verify a user: send the code.** [`POST /users/trigger-verification`](https://docs.tryflume.ai/api/trigger-verification.md). Your first call for a new user. Flume emails them a 6-digit code, and you show a code box.
2. **Verify a user: confirm the code.** [`POST /users/confirm-verification`](https://docs.tryflume.ai/api/confirm-verification.md). The right code opens the user's Flume account and returns their access token. Keep it against the user. It does not expire.
3. **Search by photo.** [`POST /search`](https://docs.tryflume.ai/api/search.md). A photo and the user's filters give two lists, strong matches and other similar options, plus a `search_session_uuid`.
4. **Product detail.** [`GET /products/{sku_uuid}`](https://docs.tryflume.ai/api/get-product.md). Photos, price, specification and shipping.
5. **Instant quote.** [`POST /request-instant-quote`](https://docs.tryflume.ai/api/request-instant-quote.md). The delivered price for a quantity and a ZIP code. A quote that is still pricing is read with [`GET /quotes/{quote_uuid}`](https://docs.tryflume.ai/api/get-quote.md).
6. **Open Flume, signed in.** [`POST /deep-links`](https://docs.tryflume.ai/api/create-deep-link.md). A one-time link into the user's Flume account, where every search and quote you made for them is waiting.

Supporting calls: [`GET /filters`](https://docs.tryflume.ai/api/list-filters.md), [`DELETE /users/{external_ref}/token`](https://docs.tryflume.ai/api/revoke-user-token.md), [`GET /keys`](https://docs.tryflume.ai/api/list-keys.md), [`POST /keys`](https://docs.tryflume.ai/api/rotate-key.md), [`DELETE /keys/{key_id}`](https://docs.tryflume.ai/api/revoke-key.md).

**Two headers.** Every call carries your partner key as `X-Flume-Partner-Key`. Steps 3 to 6 also carry the user access token as `X-Flume-User-Token`. Neither works alone. Start with a sandbox key, then a user access token once you have one. Prices are US dollars, sent as text with 2 decimals, for example `"6.40"`.

## Base URL

```text
https://sandbox-api.tryflume.ai/partner/v1
```

| Environment | Base URL |
|---|---|
| Sandbox | `https://sandbox-api.tryflume.ai/partner/v1` |
| Live | `https://ssapi.tryflume.ai/partner/v1` |

Live is in early access and not yet open to new partners. See [Environments](https://docs.tryflume.ai/concepts/environments.md).

## Endpoints

| Area | Endpoints |
|---|---|
| Users | [`POST /users/trigger-verification`](https://docs.tryflume.ai/api/trigger-verification.md), [`POST /users/confirm-verification`](https://docs.tryflume.ai/api/confirm-verification.md), [`DELETE /users/{external_ref}/token`](https://docs.tryflume.ai/api/revoke-user-token.md) |
| Search | [`GET /filters`](https://docs.tryflume.ai/api/list-filters.md), [`POST /search`](https://docs.tryflume.ai/api/search.md) |
| Products | [`GET /products/{sku_uuid}`](https://docs.tryflume.ai/api/get-product.md) |
| Quotes | [`POST /request-instant-quote`](https://docs.tryflume.ai/api/request-instant-quote.md), [`GET /quotes/{quote_uuid}`](https://docs.tryflume.ai/api/get-quote.md) |
| Deep links | [`POST /deep-links`](https://docs.tryflume.ai/api/create-deep-link.md) |
| Keys | [`GET /keys`](https://docs.tryflume.ai/api/list-keys.md), [`POST /keys`](https://docs.tryflume.ai/api/rotate-key.md), [`DELETE /keys/{key_id}`](https://docs.tryflume.ai/api/revoke-key.md) |

## Request headers

| Header | When | Notes |
|---|---|---|
| `X-Flume-Partner-Key` | Every call | Your partner key |
| `X-Flume-User-Token` | Calls made for a user | The user's access token |
| `Idempotency-Key` | Some `POST` calls | 1 to 255 characters. See [Idempotency](https://docs.tryflume.ai/concepts/idempotency.md) |
| `X-Flume-Client-IP` | `POST /users/trigger-verification`, optional | The user's own IPv4 or IPv6 address. Adds a limit per IP address |
| `Content-Type` | Calls with a body | `application/json`, or `multipart/form-data` for `POST /search` |

See [Authentication and keys](https://docs.tryflume.ai/concepts/authentication.md).

## Response headers

| Header | When | Notes |
|---|---|---|
| `X-Request-Id` | Every response | Quote it to Flume support |
| `Retry-After` | Most `409` `IDEMPOTENCY_IN_PROGRESS` and `429` responses | Seconds to wait |
| `Idempotent-Replay` | A replayed answer | `true` |

## Formats

| Thing | Format | Example |
|---|---|---|
| Bodies | JSON, UTF-8 | |
| Ids | UUID strings | `7f3c2a91-4b0e-4c8d-9a21-1f6b2d5e7c30` |
| Money | Decimal string, 2 places, USD | `"6.40"` |
| Timestamps | UTC, ISO 8601, with `Z` | `2026-10-16T09:14:22Z` |
| Dates | ISO 8601 | `2027-03-01` |
| Quantities | Square feet | `6000` |
| Countries | Two letters | `ES` |
| ZIP codes | 5 digits | `22102` |

## Code samples

Every reference page shows the call in curl, Python and Node.js.

- Samples read `FLUME_PARTNER_KEY` and, for calls made for a user, `FLUME_USER_TOKEN` from the environment.
- Ids in a sample are examples. Use ids from your own responses.
- The Python samples need `requests`.
- The Node.js samples use top-level `await`. Save them as `.mjs`, with Node.js 20 or later.

## Strict requests

Request bodies are strict. A field the API does not know is a `422` [`VALIDATION_FAILED`](https://docs.tryflume.ai/api/errors.md#validation_failed) that names it.

One exception: `item`, and its `labels` and `rooms`, accept any extra fields. Flume stores them as sent.

## Errors

Every error is JSON in one envelope. Branch on `error.code`.

```json
{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "destination_zip: String should match pattern '^\\d{5}$'",
    "field": "destination_zip",
    "request_id": "e19b8889-a63b-4000-9dbe-ffd5b9157bd5"
  }
}
```

Every code, with its status and fix: [API error codes](https://docs.tryflume.ai/api/errors.md).

## Pagination

Only `POST /search` pages.

- Send `page` and `page_size` in the payload.
- Read `has_more` and `total` in the response.
- At most 50 results per search and 24 per page.
- There are no cursors.
- Each page is a new search. See [Idempotency](https://docs.tryflume.ai/concepts/idempotency.md#why-does-search-have-no-idempotency).

`GET /keys` returns every key, unpaged.

## Versioning

- The version is in the path: `/partner/v1`.
- The OpenAPI document's `info.version` is `2.0.0`. It counts revisions of the v1 contract.
- Flume has no published deprecation policy yet. Changes are listed in the [changelog](https://docs.tryflume.ai/changelog.md).
- Write your client to ignore response fields it does not know.

## OpenAPI

- [`/openapi.json`](https://docs.tryflume.ai/openapi.json) is the OpenAPI 3.1 document this reference is generated from.
- It lists the server-to-server calls. Calls only the Flume iframe makes are left out.

## Optional and null

- In a **request**, a field marked Optional can be left out.
- In a **response**, every field is always present. A field with no value is `null`. The reference shows this as "or null" after the type.

## What is not available

Webhooks, SDKs, rate limit headers and list endpoints do not exist today. The full list is on the [overview](https://docs.tryflume.ai/index.md#what-exists-today).

## Try a call without writing code

- Or import [`/openapi.json`](https://docs.tryflume.ai/openapi.json) into an HTTP client such as Postman or Bruno. There is no ready-made collection.
