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

> ## Agent Instructions
> Flowsign is one word with a lowercase s.
> The REST API base URL is https://my.flowsign.app and every endpoint lives under /api/v1.
> When answering API questions, cite the HTTP method and endpoint path.
> API access needs the Enterprise plan and an API key with the API access permission.

# Authentication

> Bearer API keys, who can create them, and why a request is refused.

Every `/api/v1` request is authenticated with an API key sent as a Bearer token.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://my.flowsign.app/api/v1/workspaces \
    -H "Authorization: Bearer fsk_your_key_here"
  ```

  ```javascript JavaScript theme={null}
  const res = await fetch("https://my.flowsign.app/api/v1/workspaces", {
    headers: { Authorization: `Bearer ${process.env.FLOWSIGN_API_KEY}` },
  });

  const { data } = await res.json();
  console.log(data.active, data.workspaces);
  ```

  ```python Python theme={null}
  import os

  import requests

  res = requests.get(
      "https://my.flowsign.app/api/v1/workspaces",
      headers={"Authorization": f"Bearer {os.environ['FLOWSIGN_API_KEY']}"},
      timeout=30,
  )
  res.raise_for_status()

  data = res.json()["data"]
  print(data["active"], data["workspaces"])
  ```

  ```csharp C# theme={null}
  using System.Net.Http.Headers;
  using System.Net.Http.Json;
  using System.Text.Json;

  using var http = new HttpClient { BaseAddress = new Uri("https://my.flowsign.app") };
  http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
      "Bearer",
      Environment.GetEnvironmentVariable("FLOWSIGN_API_KEY"));

  var body = await http.GetFromJsonAsync<JsonElement>("/api/v1/workspaces");
  var data = body.GetProperty("data");

  Console.WriteLine(data.GetProperty("active").GetString());
  ```
</CodeGroup>

Keys start with `fsk_`. Flowsign stores only a hash of the key; the full value is shown once, when the key is created.

## Creating and managing keys

Keys are created in the app at **Settings > API keys** ([my.flowsign.app/settings/api-keys](https://my.flowsign.app/settings/api-keys)). Only an owner can create, list or revoke them.

* **Name** the key after where it will live (for example "Production server").
* **Role** is what the key can do. The key acts with that role's permissions, not the issuer's, and only roles with the **API access** permission are offered.
* **Workspace** is where the key acts. A key is bound to one workspace for its whole life.
* **Expiry** is optional. A key with no expiry works until you revoke it; a key with an expiry stops working at the end of that day, in the local time of whoever created it.
* The key value is displayed once in a reveal dialog and cannot be read again. If you lose it, create a new key.
* **Revoke** a key from the same page. Revocation is immediate and permanent.
* There is no rotate operation. To rotate, create a new key, move your integration to it, then revoke the old one.
* An organisation can hold at most 50 unrevoked keys, and expired keys count until they are revoked. Creating one beyond that returns `409`; revoke a key to make room.

The page lists each key's **Name** (with when it was last used), **Key** prefix, **Can do** (its role), **Issued by** and **Status** (Active, Expired or Revoked, with the expiry or revocation date).

<Warning>
  A key carries the full API access of the role chosen when it was created. Store it in a secrets manager, never in client-side code or a repository, and revoke it the moment it is no longer needed.
</Warning>

## Who can use the API

* **Creating keys** requires an owner.
* **Permission.** The role a key is given must have the **API access** permission. The built-in Admin profile has it; Sender and Viewer do not. An administrator can grant it from **Roles & Permissions**.
* **Acting as a role.** A key acts with the permissions of the role chosen at creation, not the issuer's, and it is never an owner. Package visibility is the exception: without the **view all packages** permission (`canViewAllPackages`), a key sees only the packages its issuer owns or has been shared, including the ones the key created. Endpoints that change data check that role's permissions, so a key on a role without the send permission cannot send packages (`403 Missing permission: canSendPackages`). Audit events record the issuing user alongside the key. A key sees every template in its workspace, not only the ones its issuer created; the role's template access decides whether it can use them (USE) or also create and edit them (CREATE).
* **Webhook endpoints** (`/api/v1/webhooks`) need the **manage webhooks** permission on the key's role.
* **Plan.** The public API is included in the Enterprise plan. Webhooks are a separate feature on the same plan. Calls from organisations without the feature return `402`.
* **IP allowlist.** If your organisation has an IP allowlist (**Settings > Security**), API calls from other addresses are refused with `403 IP address not allowed`. A request whose client address cannot be determined is refused the same way.

## Workspaces

A key belongs to the organisation and is bound to the workspace chosen when it was created. Every request acts there. You may send `X-Workspace-Id` to be explicit, but it can only repeat the key's own workspace id; any other value is refused with `401`. To act in another workspace, create a key for it. See [Workspaces](/api-reference/workspaces).

## Why a request is refused

| Status | Cause |
| - | - |
| `401 Unauthorized` | No `Authorization` header, a token that does not start with `fsk_`, an unknown key, or a key that is revoked or expired. Also returned when the key's role has lost the API access permission, when the issuing user's account has been deleted, or when `X-Workspace-Id` names any workspace other than the key's own. |
| `402` | The organisation's plan does not include the public API (or webhooks, on webhook routes, or custom fields, on `GET /api/v1/custom-fields`). The message names the missing feature. |
| `403 IP address not allowed` | The caller's address is outside the organisation's IP allowlist, or could not be determined while an allowlist is in place. |
| `403 Missing permission: ...` | The key's role lacks the permission the endpoint needs. |
| `403 Missing permission: canManageWebhooks` | Webhook endpoints need the manage webhooks permission on the key's role. |

See [Errors](/api-reference/errors) for the response format, validation details and rate limits.
