Authentication
Every call to https://lantfly.com/api/v3 needs a token, except the OpenAPI spec
and signed storage links. Send it in the Authorization header:
Authorization: Bearer <your API token>
A missing, unknown, expired or revoked token answers 401 with code unauthenticated. The answer is JSON even when
you don't send Accept: application/json.
Create an API token
- Open the Console and go to Settings → API & integrations.
- Under New token, enter a Name (for example
n8n production). - Optionally set Expires in (days). Leave it empty for a token that never expires.
- Choose Access: Full access or Read-only (GET requests only).
- Optionally pick actors under Limit to actors, or switch on Limit token permissions and tick what the token may do. See Scoped tokens.
- Click Create token and copy it. The token is shown once.
Treat a token like a password. Keep it in an environment variable or a secret manager, never in source control or in a browser. Anyone with the token can act for your account, and runs it starts are billed to you.
The examples in these docs read the token from $LANTFLY_TOKEN:
export LANTFLY_TOKEN="paste-your-token-here"
Make a request
- curl
- Node.js
- Python
curl https://lantfly.com/api/v3/me \
-H "Authorization: Bearer $LANTFLY_TOKEN"
const res = await fetch('https://lantfly.com/api/v3/me', {
headers: { Authorization: `Bearer ${process.env.LANTFLY_TOKEN}` },
});
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${res.status} ${error.code}: ${error.message}`);
}
const { data } = await res.json();
console.log(data);
import os
import requests
res = requests.get(
"https://lantfly.com/api/v3/me",
headers={"Authorization": f"Bearer {os.environ['LANTFLY_TOKEN']}"},
timeout=30,
)
if not res.ok:
error = res.json()["error"]
raise RuntimeError(f"{res.status_code} {error['code']}: {error['message']}")
print(res.json()["data"])
Token in the query string
Only two surfaces also accept the token as ?token=…, for clients that can't set a header:
- the MCP server,
https://lantfly.com/mcp(see MCP); - Actor Standby,
/api/v3/standby/….
Every other endpoint ignores ?token=.
URLs end up in logs, browser history and proxies. Prefer the header wherever the client allows it, and use a scoped token when you must put one in a URL.
Scoped tokens
A token can be limited in three ways, and you can combine them. Limits apply on every endpoint, including MCP and Standby.
| Limit | Console option | What the token can do |
|---|---|---|
| Read-only | Access → Read-only (GET requests only) | Only GET and HEAD. Any other method answers 403 insufficient_permissions. |
| Actors | Limit to actors (up to 50) | Read those actors and their builds, start runs of them, read, log and abort those runs, and read (not write) the default storages of those runs. GET /me stays open. Everything else, including lists, versions and environment variables, tasks, schedules, webhooks and billing, answers 403. |
| Permissions | Limit token permissions | Only what the ticked permissions cover. Anything no permission covers (billing, team, token management…) answers 403 insufficient_permissions. GET /me stays open. |
Permissions
| Group | Permission | Allows |
|---|---|---|
| Actors | actors.read | View actors, their versions and builds |
actors.run | Run actors (also Standby and the call-actor MCP tool) | |
actors.build | Build actors and abort builds | |
actors.write | Create, change and delete actors | |
| Runs | runs.read | View runs, their logs and default storages |
runs.write | Abort, resurrect, reboot and change runs | |
| Tasks | tasks.read | View tasks and their input |
tasks.run | Run tasks | |
tasks.write | Create, change and delete tasks | |
| Schedules | schedules.read | View schedules and their log |
schedules.write | Create, change and delete schedules | |
| Storages | storages.read | Read datasets, key-value stores and request queues |
storages.write | Create, write and delete storages | |
| Webhooks | webhooks.read | View webhooks and their dispatches |
webhooks.write | Create, change, test and delete webhooks | |
| Social listening | listening.read | View listening projects, mentions, analytics, creators, campaigns and reports |
listening.write | Create and change listening projects, sources, campaigns, alerts and reports; collect now |
A request the token's permissions don't cover answers:
{
"error": {
"code": "insufficient_permissions",
"message": "This API token does not have the runs.write permission."
}
}
Give each integration its own token with the least it needs: a reporting script gets Read-only plus
listening.read; a Zapier zap that starts one scraper gets Limit to actors with that actor.
Manage tokens
Rename, regenerate and revoke tokens under Settings → API & integrations.
- Regenerate gives a new secret with the same name, limits and expiry. The old secret stops working at once.
- Revoke ends the token. Anything using it gets
401from then on. - Tokens without an expiry keep working until you revoke them, even if they go unused for months.
Endpoints that manage credentials and sessions (/me/tokens…, /me/token-permissions, /me/security, /me/sessions…,
/me/oauth-grants…) answer 403 session_required when called with an API token, even a full-access one. A leaked token
can't mint more tokens, list your sessions or sign you out. Revoke it from the Console.
Organization tokens
A token created while you act for an organization belongs to that organization: it needs no extra header, carries your current role there, and stops working when you leave the organization. See Organizations.
Run token (inside actors)
Each run gets its own short-lived token. Inside the actor container it's in the LANTFLY_TOKEN environment variable, and
the Actor SDK uses it automatically. A run token can only:
- read and update its own run (
GETandPATCH /runs/{run},log,charge,metamorph); - read and write its run's default dataset, key-value store and request queue;
- open or create named storages of the account that owns the run.
Any other call answers 403 insufficient_permissions; another run's unnamed storage answers 404. The run token can't
use the MCP server or Standby. It stops working 5 minutes after the run finishes. A run of an organization acts for the
organization.
Don't pass your personal API token into an actor's input or environment variables. Actors already have what they need through the run token.
Sign-in endpoint
The Console signs in with POST https://lantfly.com/csl/auth/v1/login (email, password) and gets a Console session
back. When the account has two-step sign-in, the answer is two_factor_required with a challenge_token to finish at
POST /csl/auth/v1/2fa/challenge. For scripts and servers, use an API token instead: it doesn't expire with your
session, can be scoped, and can be revoked on its own.