Documentation Index
Fetch the complete documentation index at: https://figranium.dev/docs/llms.txt
Use this file to discover all available pages before exploring further.
Figranium exposes a local REST API for task management, execution, and data retrieval.
Base URL: http://localhost:11345 (default)
Health
GET /api/health
Returns the server status and storage backend connectivity. Use this endpoint for uptime monitoring, load-balancer health checks, or verifying that Figranium is ready to accept work.
Response (healthy):
{
"status": "ok",
"uptime": 3600,
"storage": "json"
}
Response (degraded — database unreachable):
{
"status": "degraded",
"uptime": 3600,
"storage": "postgres",
"storage_error": "Database unreachable"
}
| Field | Description |
|---|
status | "ok" or "degraded" |
uptime | Server uptime in seconds |
storage | "json" (file-based) or "postgres" |
storage_error | Present only when the database is unreachable |
Returns HTTP 200 when healthy and 503 when degraded. This endpoint does not require authentication.
Authentication
If enabled, authentication must be provided via one of the following methods:
- Header:
x-api-key: your_key or key: your_key
- Authorization Header:
Authorization: Bearer your_key
- Request Body:
{"apiKey": "your_key"} or {"key": "your_key"}
Tasks
GET /api/tasks
Lists all saved tasks. Each task includes its full configuration except for the version history, which is fetched separately when you open a task in the editor.
Response:
[
{
"id": "task_1",
"name": "Scraper",
"description": "Extracts product prices daily",
"url": "https://example.com",
"mode": "agent"
}
]
The description field is optional and only present if the task has one.
POST /api/tasks
Creates or updates a task. If a task with the same id already exists, it is overwritten. Include ?version=true in the query string to save a version snapshot before overwriting.
Body:
{
"name": "New Task",
"description": "Optional summary of what this task does",
"url": "https://example.com",
"mode": "agent",
"actions": []
}
The description field is optional. When set, it appears on the canvas trigger card and in the GET /api/tasks/list response so external tools and AI agents have context about the task without fetching its full definition.
POST /api/tasks/:id/api
Triggers an execution of a specific task.
Body:
{
"variables": {
"query": "override value"
},
"webhookUrl": "https://your-server.com/callback"
}
| Field | Type | Required | Description |
|---|
variables | object | No | Override task-level variables for this run |
webhookUrl | string | No | URL to receive a POST callback with the execution result |
statelessExecution | boolean | No | Run in a clean browser context with no saved cookies |
Response: Returns the execution result (JSON).
Completion webhook
When you include a webhookUrl, Figranium sends a POST request to that URL after the task finishes. The webhook URL is validated against the same SSRF rules as all other outbound requests (see Security). If the URL points to a private network and ALLOW_PRIVATE_NETWORKS is false, the request returns 400 INVALID_WEBHOOK_URL.
The callback payload looks like this:
{
"executionId": "exec_abc123",
"taskId": "task_1",
"status": "success",
"durationMs": 4200,
"result": { "data": [ ... ] }
}
The webhook request times out after 10 seconds. Delivery failures are logged on the server but do not affect the execution result returned to the original caller.
POST /api/tasks/generate-selector
Uses the configured AI provider to generate a CSS selector from a plain-language description and the current page DOM. The endpoint runs the task up to the specified action index to capture the live HTML, then sends it to the AI provider chain (Gemini → OpenAI → Claude → Ollama) and returns the first successful result. Requires authentication.
Body:
{
"task": { "url": "https://example.com", "actions": [...] },
"actionIndex": 2,
"prompt": "the search input field"
}
| Field | Type | Required | Description |
|---|
task | object | Yes | The full task object, including url and actions |
actionIndex | number | Yes | Run actions up to this index to capture the page state |
prompt | string | Yes | A natural-language description of the element to find |
Response (success):
{
"selector": "input[aria-label=\"Search\"]"
}
Error responses:
| Status | Cause |
|---|
400 | Missing task, actionIndex, or prompt, or no AI provider keys configured |
500 | All configured AI providers failed to generate a selector, or the DOM extraction failed |
Ollama requests from this endpoint go through redirect-safe fetching with SSRF validation at every hop. See Ollama URL validation for details.
POST /api/tasks/generate-script
Uses the configured AI provider to generate a JavaScript extraction script from a plain-language description. The endpoint tries each provider in order (Gemini → OpenAI → Claude → Ollama) and returns the first successful result. Requires authentication.
Body:
{
"description": "extract all article titles and links from the page"
}
| Field | Type | Required | Description |
|---|
description | string | Yes | A natural-language description of the data to extract |
Response (success):
{
"script": "const articles = Array.from(document.querySelectorAll('article'));\nreturn articles.map(a => ({\n title: a.querySelector('h2')?.innerText.trim(),\n link: a.querySelector('a')?.href\n}));"
}
Error responses:
| Status | Cause |
|---|
400 | Missing or empty description, or no AI provider keys configured |
502 | All configured AI providers failed to generate a script |
Ollama requests from this endpoint go through redirect-safe fetching with SSRF validation at every hop. See Ollama URL validation for details.
Executions
GET /api/executions
Lists execution history.
Query Parameters:
limit: Number of results (default 50).
status: Filter by status code.
GET /api/executions/:id
Gets detailed logs and result for a specific execution.
DELETE /api/executions/:id
Deletes a single execution record by ID.
Response:
POST /api/executions/clear
Deletes all execution records. Use this endpoint to free disk space or reset history after large batch runs.
Response:
Data
GET /api/data/captures
Lists all captured files (screenshots, recordings).
DELETE /api/data/captures/:name
Deletes a specific capture file.
Settings
AI provider keys
Manage API keys for each AI provider. All providers support multiple keys for automatic failover.
GET /api/settings/gemini-api-key
Returns the configured Gemini API keys.
POST /api/settings/gemini-api-key
Saves one or more Gemini API keys.
Body:
{
"geminiApiKeys": ["your-gemini-key"]
}
GET /api/settings/openai-api-key
Returns the configured OpenAI API keys.
POST /api/settings/openai-api-key
Saves one or more OpenAI API keys.
Body:
{
"openAiApiKeys": ["your-openai-key"]
}
GET /api/settings/claude-api-key
Returns the configured Claude (Anthropic) API keys.
POST /api/settings/claude-api-key
Saves one or more Claude API keys.
Body:
{
"claudeApiKeys": ["your-claude-key"]
}
GET /api/settings/ollama-api-key
Returns the configured Ollama instances.
POST /api/settings/ollama-api-key
Saves one or more Ollama instance configurations. Each entry is a JSON string containing the base URL and model name.
Body:
{
"ollamaApiKeys": ["{\"url\":\"http://localhost:11434\",\"model\":\"gemma4:e2b\"}"]
}
You can also pass a plain URL string (e.g., "http://localhost:11434"), in which case the default model gemma4:e2b is used.
AI model settings
GET /api/settings/ai-models
Returns the currently configured default model for each AI provider. Requires authentication.
Response:
{
"gemini": "gemini-3-flash-preview",
"openai": "gpt-5-nano",
"claude": "claude-haiku-4-6",
"ollama": "llama3.2"
}
POST /api/settings/ai-models
Updates the default model for one or more AI providers. Omitted providers keep their current value. Requires authentication.
Body:
{
"openai": "gpt-4o",
"claude": "claude-sonnet-4-5"
}
Response: Returns the full updated model configuration (same shape as the GET response).
Proxies
GET /api/settings/proxies
Lists configured proxies.
POST /api/settings/proxies
Adds a new proxy.
Body:
{
"server": "http://1.2.3.4:8080",
"label": "US Proxy"
}
Credentials
GET /api/credentials
Lists all saved credentials. Tokens are redacted in the response.
Response:
[
{
"id": "cred_a1b2c3d4e5f6g7h8",
"name": "My Baserow",
"provider": "baserow",
"config": {
"baseUrl": "https://baserow.io",
"token": "••••••••"
}
}
]
POST /api/credentials
Creates a new output provider credential.
Body:
{
"provider": "baserow",
"name": "My Baserow",
"config": {
"baseUrl": "https://baserow.io",
"token": "your-api-token"
}
}
The baseUrl is validated against SSRF rules. If the URL points to a private or internal network address (and ALLOW_PRIVATE_NETWORKS is false), the request returns:
{ "error": "INVALID_BASE_URL", "details": "Invalid base URL format or restricted destination" }
PUT /api/credentials/:id
Updates an existing credential. The same URL validation applies when updating the baseUrl.
DELETE /api/credentials/:id
Deletes a credential by ID.
Response:
GET /api/credentials/:id/proxy/baserow/databases
Lists all Baserow databases accessible by the credential. This proxies the request through Figranium so your Baserow token is never exposed to the browser.
Response:
[
{ "id": 1, "name": "Web Scraping" },
{ "id": 2, "name": "Product Data" }
]
GET /api/credentials/:id/proxy/baserow/databases/:databaseId/tables
Lists all tables within a specific Baserow database. The databaseId parameter must be a numeric value.
Response:
[
{ "id": 45, "name": "Products" },
{ "id": 46, "name": "Pricing History" }
]
Error responses:
| Status | Error code | Cause |
|---|
400 | INVALID_DATABASE_ID | The databaseId parameter is not a valid number |
These proxy endpoints are used by the task editor’s Output tab to let you browse and select a destination table without leaving Figranium.
POST /api/settings/api-key
Generates or regenerates the system API key. If you include an apiKey field in the request body, that value is saved as the new key (max 512 characters). If omitted, a new key is generated automatically.
Body (optional):
{
"apiKey": "your-custom-key"
}
Error responses:
| Status | Error code | Cause |
|---|
400 | API_KEY_TOO_LONG | The supplied key exceeds 512 characters |
GET /api/settings/selector-finder
Returns the default selector finder preference.
Response:
{ "selectorFinder": "highlight" }
Possible values: "highlight" (standard point-and-click picker) or "ai" (AI Selector Finder).
POST /api/settings/selector-finder
Sets the default selector finder tool.
Body:
{ "selectorFinder": "ai" }
Headful
GET /api/headful/status
Returns the current state of the headful (VNC) browser session. Requires authentication.
Response (VNC enabled, session active):
{
"useNovnc": true,
"novncPort": 54311,
"isRunning": true
}
Response (VNC disabled):
| Field | Description |
|---|
useNovnc | Whether VNC support is enabled on the server |
novncPort | The port the noVNC viewer is running on (only present when enabled) |
isRunning | Whether a headful browser session is currently active |
Use this endpoint to check if a headful session is running before starting a new one, or to display connection status in a custom integration.
Schedules
GET /api/schedules
Lists all tasks with an associated schedule.
Response:
{
"schedules": [
{
"taskId": "c1f7a08b",
"taskName": "Daily Price Check",
"schedule": {
"enabled": true,
"frequency": "daily",
"hour": 9,
"minute": 0,
"nextRun": 1690099200000
}
}
]
}
POST /api/schedules/:taskId
Creates or updates a schedule for a task.
Body:
{
"enabled": true,
"frequency": "daily",
"hour": 9,
"minute": 0
}
For advanced scheduling, use a cron expression:
{
"enabled": true,
"cron": "0 9 * * 1-5"
}
Response:
{
"schedule": { ... },
"description": "Every day at 9:00 AM",
"nextRun": 1690099200000
}
DELETE /api/schedules/:taskId
Disables the schedule for a task.
Response:
GET /api/schedules/status/all
Returns runtime status of the scheduler and all active jobs.
Response:
{
"running": true,
"scheduledCount": 2,
"tasks": [
{
"taskId": "c1f7a08b",
"cron": "0 9 * * *",
"nextRun": "2024-07-23T09:00:00.000Z"
}
]
}