---
title: Getting Started | FLORA API
description: Start using the FLORA API to run techniques programmatically.
---

# FLORA API

**Questions or need help getting started?** [Book an API onboarding call](https://cal.com/harishv/30min) — we’re happy to walk you through setup and answer questions.

**API access requires a paid FLORA subscription.** Manage your plan at [app.flora.ai](https://app.flora.ai).

The FLORA API lets you interact with your creative canvas programmatically. Let’s walk through an example of how to use it to look up a technique, inspect its inputs, submit a run, and poll for results.

**Base URL:** `https://app.flora.ai/api/v1`

## Step 1: Create your API key

1. Sign in to [FLORA](https://app.flora.ai).
2. Open **Settings** > **API Keys**, or use [this link](https://app.flora.ai/projects?openSettings=true\&initialTab=apiKeys).
3. Click **Create API Key**, give it a name, and copy the secret immediately. It is shown only once.
4. You can only have one active key at a time. To rotate keys, revoke the old key first.

Use the key in every request:

```
Authorization: Bearer sk_live_XXXX
```

## Step 2: Find or list a technique

Every technique has a **slug**: a short, URL-safe identifier. You can find it in the URL when you open a technique in FLORA:

```
https://app.flora.ai/api/v1/techniques/portrait-enhancer
```

You can also list techniques:

Terminal window

```
curl "https://app.flora.ai/api/v1/techniques?limit=5" \
  -H "Authorization: Bearer sk_live_XXXX"
```

Any technique you’ve built with the technique builder or that is available in your techniques dashboard can be used via the API. Techniques themselves are authored in [FLORA’s visual workflow editor](https://app.flora.ai) — the API runs them by slug, it doesn’t create or edit them.

## Step 3: Look up a technique’s inputs

Before running a technique, fetch its details to see the required inputs, expected outputs, and per-run cost in USD:

Terminal window

```
curl https://app.flora.ai/api/v1/techniques/{slug} \
  -H "Authorization: Bearer sk_live_XXXX"
```

Example response:

```
{
  "technique_id": "abc123...",
  "name": "Portrait Enhancer",
  "description": "Enhance portrait photos with AI",
  "run_cost": 0.05,
  "inputs": [
    { "id": "input_image", "name": "Input Image", "type": "imageUrl" }
  ],
  "outputs": [
    { "id": "output_image", "name": "Output Image", "type": "imageUrl" }
  ]
}
```

Use the `inputs` array to build your run request. Match each input `id` and `type` exactly.

## Public API ID prefixes

Most create/list requests require public IDs returned by the API:

\| Resource | Prefix | Where to get it | | --------- | -------- | ----------------------------------- | | Workspace | `ws_` | `GET /workspaces` | | Project | `prj_` | `GET /projects?workspace_id=ws_...` | | Technique | `tech_` | `GET /techniques` | | Run | `run_` | Create run responses | | Asset | `asset_` | Create/list asset responses |

If an endpoint returns `input_validation_error`, check both the field name and the ID prefix in the error response.

## Step 4: Create a run

Terminal window

```
curl -X POST https://app.flora.ai/api/v1/techniques/{slug}/runs \
  -H "Authorization: Bearer sk_live_XXXX" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": [
      { "id": "input_image", "type": "imageUrl", "value": "https://example.com/photo.jpg" }
    ],
    "mode": "async"
  }'
```

Response:

```
{
  "run_id": "j57abc...",
  "created_at": 1710000000000,
  "status": "pending",
  "progress": 0,
  "poll_url": "https://app.flora.ai/api/v1/techniques/{slug}/runs/j57abc..."
}
```

## Step 5: Poll for results

Terminal window

```
curl https://app.flora.ai/api/v1/techniques/{slug}/runs/{runId} \
  -H "Authorization: Bearer sk_live_XXXX"
```

Poll every 2–5 seconds until `status` is `completed` or `failed`.

```
{
  "run_id": "j57abc...",
  "status": "completed",
  "progress": 100,
  "created_at": 1710000000000,
  "started_at": 1710000001000,
  "completed_at": 1710000030000,
  "charged_cost": 0.05,
  "outputs": [
    {
      "output_id": "output_image",
      "type": "imageUrl",
      "url": "https://ik.imagekit.io/flora/..."
    }
  ]
}
```

**Output URLs are long-lived but not permanent.** Download anything you need to keep — don’t rely on a returned URL still resolving weeks or months later.

## Core endpoints

\| Method | Path | Description | | ------ | --------------------------------------- | ------------------------------------------------------------ | | GET | `/workspaces` | List workspaces available to your API key | | GET | `/projects?workspace_id={workspace_id}` | List projects in a workspace | | POST | `/assets` | Create an asset or reserve a signed upload | | GET | `/models?type=image` | List available models | | GET | `/techniques/{slug}` | Get technique details, inputs, outputs, and per-run USD cost | | POST | `/techniques/{slug}/runs` | Create and start a technique run | | GET | `/techniques/{slug}/runs/{runId}` | Poll technique run status and results |

## Create run request fields

\| Field | Required | Notes | | ----------------- | -------- | ----------------------------------------------------------------------- | | `inputs` | Yes | Must match the technique’s expected inputs: count, IDs, and types | | `inputs[].id` | Yes | Input identifier from the technique’s `inputs` array | | `inputs[].type` | Yes | Usually `imageUrl`, `videoUrl`, or `text` | | `inputs[].value` | Yes | URL for images/videos, or text content | | `mode` | Yes | Use `"async"` | | `idempotency_key` | No | Prevents duplicate runs on retry; the same key returns the existing run |

## Input media URL restrictions

Only **HTTPS** URLs are accepted (`https://`, not `http://`).

Supported hosts include FLORA media, Google Cloud Storage, Amazon S3, and ImageKit URLs.

## Run statuses

\| Status | Meaning | | ----------- | ---------------------------------------- | | `pending` | Queued | | `running` | In progress; `progress` shows 0–100% | | `completed` | Done; check `outputs` and `charged_cost` | | `failed` | Check `error_code` and `error_message` |

## Errors

Errors return an object like `{ "error": { "code": "...", "message": "..." } }`. Validation errors may also include `fields`, for example `{ "field": "workspace_id", "message": "Workspace identifier must start with ws_" }`.

\| Code | HTTP | Meaning | | ------------------------ | ---- | --------------------------------------------- | | `unauthorized` | 401 | Missing auth header | | `invalid_api_key` | 401 | Bad or revoked key | | `invalid_json` | 400 | Malformed request body | | `input_validation_error` | 400 | Wrong inputs for this technique | | `not_found` | 404 | Bad resource ID, technique slug, or run ID | | `insufficient_credits` | 402 | Workspace balance is too low to start the run | | `forbidden` | 403 | Your key cannot perform this action |

## Problems?

If you need help, send us the request ID from the response headers. You can capture headers with `curl -i`:

Terminal window

```
curl -i https://app.flora.ai/api/v1/techniques/cctv-cam \
  -H "Authorization: Bearer sk_live_XXXX"
```

Include the request ID, the endpoint you called, and the approximate time of the request when you contact support.
