> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tryflowy.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Flowy is a node-based AI creative platform: you generate images, video, audio, 3D and vector on an infinite Canvas, refine on the Studio timeline, and export or publish from the same project.
> Prefer the Flowy MCP server (https://mcp.tryflowy.ai/mcp) or the REST API at https://apis.tryflowy.ai/v1 for programmatic work. Install with `flowy mcp install` from the @flowy/cli package.
> Credits are workspace-scoped. Generations reserve credits on start and only deduct on success, so failed runs refund automatically.

# Authentication

> Create an API key and use it to authenticate every request.

The Flowy API authenticates with **API keys** (created in the dashboard) or **OAuth access tokens** (minted when you connect an AI agent; see [the MCP server](/api/mcp)). Send either as a Bearer token in the `Authorization` header on every request:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
Authorization: Bearer flowy_xxxxxxxx
```

A missing, malformed, revoked, or expired credential returns `401 Unauthorized`.

**Who pays:** OAuth connections are **account-bound**: by default they act in and bill your personal account wallet, and can act in any workspace you can manage by passing `workspace_id` (see [List workspaces](/api/list-workspaces)). Dashboard API keys belong to the workspace they were created in and bill that workspace by default.

## Secret vs publishable keys

<Note>
  **Publishable keys are coming soon.** Today every key you create is a **secret** key: the publishable column below previews what's next.
</Note>

There are two kinds of key. Pick the one that matches where your code runs.

|              | **Secret key**     | **Publishable key**            |
| ------------ | ------------------ | ------------------------------ |
| Prefix       | `flowy_…`          | `flowy_pk_…`                   |
| Use it       | Server-side only   | In a browser / client app      |
| Protected by | Keeping it private | A per-key **domain allowlist** |

<Warning>
  A **secret** key grants full use of its scopes to anyone who has it. Treat it like a password and keep it server-side. A **publishable** key is meant to be visible in client code, so its only real protection is the domain allowlist (plus its [scopes](/api/permissions), daily cap, and [rate limit](/api/rate-limits)). Give publishable keys the narrowest scopes and a sensible spend cap.
</Warning>

## Create a key

<Steps>
  <Step title="Open API keys settings">
    In the app, go to [Settings → API keys](/settings/api-keys). You'll need to be a workspace **owner** or **editor**.
  </Step>

  <Step title="Choose the key's shape">
    Pick an **owner** (You or Machine) and a **permission** level (All, Read-only, or Restricted). Optionally set a daily spend cap and rate limit under advanced options.
  </Step>

  <Step title="Copy it now">
    Your key (`flowy_…`) is shown **once**. Copy it and store it in a secrets manager or server environment variable. You won't be able to see it again.
  </Step>
</Steps>

## Key owner: You vs Machine

When you create a key you choose who **owns** it:

* **You**: the key is tied to your user account.
* **Machine**: the key is owned by a workspace **service account**. It keeps working even if you later leave the workspace, and runs are attributed to the service account rather than to you. The service account takes no seat and never appears in your members list.

<Tip>
  Use a **Machine** owner for long-lived production integrations, so the key doesn't break the day the person who created it changes teams.
</Tip>

## Authenticate a request

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  export FLOWY_API="https://apis.tryflowy.ai/genstudio-svc-v2/api/v1"
  export FLOWY_KEY="flowy_..."

  curl "$FLOWY_API/apps" \
    -H "Authorization: Bearer $FLOWY_KEY"
  ```

  ```javascript Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  const BASE = "https://apis.tryflowy.ai/genstudio-svc-v2/api/v1";
  const KEY = process.env.FLOWY_KEY; // "flowy_..."

  const res = await fetch(`${BASE}/apps`, {
    headers: { Authorization: `Bearer ${KEY}` },
  });
  const { data } = await res.json();
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import os, requests

  BASE = "https://apis.tryflowy.ai/genstudio-svc-v2/api/v1"
  KEY = os.environ["FLOWY_KEY"]  # "flowy_..."

  res = requests.get(f"{BASE}/apps", headers={"Authorization": f"Bearer {KEY}"})
  data = res.json()["data"]
  ```
</CodeGroup>

Every request you make with a key is recorded in [Settings → Logs](/settings/logs): useful for debugging your integration and auditing what a key has been doing.

## Using a publishable key in the browser

<Note>
  Publishable keys aren't available to create yet. This section previews how they'll work.
</Note>

A publishable key works the same way, `Authorization: Bearer flowy_pk_…`, but the request must come from one of the key's **allowed domains** (matched on the `Origin`, falling back to the `Referer`). Add `example.com` for an exact host, or `*.example.com` to allow any subdomain. A request from a domain that isn't allowlisted returns `403 Forbidden`.

```javascript Browser theme={"theme":{"light":"github-light","dark":"vesper"}}
// Runs from https://example.com — an allowed domain — succeed.
await fetch(`${BASE}/apps/${appId}/runs`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${PUBLISHABLE_KEY}`, // flowy_pk_...
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ inputs: [{ node_id: "scene", prompt: "a red bicycle" }] }),
});
```

## Protecting your keys

Because a leaked key spends your workspace credits, every key has several safeguards. Set them when you create or edit a key:

| Safeguard            | What it does                                                                                                                             |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Scopes**           | Limit which operations the key can perform: e.g. a read-only key can't start runs. See [Permissions](/api/permissions).                  |
| **Domain allowlist** | For publishable keys: only requests from your domains are accepted.                                                                      |
| **Daily spend cap**  | Once the key spends its cap (credits/day), new runs are rejected with `402` until the next UTC day.                                      |
| **Rate limit**       | Caps requests per minute for the key. Excess requests get `429`. See [Rate limits](/api/rate-limits).                                    |
| **Revoke**           | Disables the key immediately. The **Last used** column and the [request logs](/settings/logs) help you spot a key behaving unexpectedly. |

<Note>
  Your workspace's available credit balance is always the final backstop: when it reaches zero, runs stop regardless of any cap.
</Note>
