Queries
Saved queries, executions, scheduled tasks, pipeline executions, and category management — every endpoint under /api/queries/.
The query engine is the largest surface of Fabrik's API. Seven ViewSets are mounted under /api/queries/:
| Route | Resource |
|---|---|
/api/queries/categories/ | Flat categories for organizing saved queries |
/api/queries/saved-queries/ | The saved queries themselves — canvas + metadata |
/api/queries/execution-logs/ | Historical execution records (read-only) |
/api/queries/scheduled-tasks/ | Frequency-based scheduled queries |
/api/queries/scheduled-executions/ | Run history for scheduled tasks |
/api/queries/task-settings/ | Global task-management defaults (retries, log retention, email) |
/api/queries/pipeline-executions/ | Multi-query pipeline runs |
Categories
GET /api/queries/categories/
List all categories. Categories are flat — there is no parent/child nesting.
Resource shape:
{
"id": 1,
"name": "Network Health",
"description": "",
"color": "#3b82f6",
"icon": "activity",
"query_count": 12,
"created_at": "…"
}POST /api/queries/categories/
Body: { "name": "...", "description": "...", "color": "#3b82f6", "icon": "activity" }. Only name is required (and must be unique).
PATCH / DELETE /api/queries/categories/<id>/
Standard ModelViewSet semantics.
Saved queries
GET /api/queries/saved-queries/
Paginated list.
Filters:
?category=<id>— filter by category.?search=<term>— name and description.?is_favorite=true— only favorited.?ordering=-updated_at— recent first.
Resource shape (summary): the list serializer omits flow_data (the canvas JSON can be hundreds of KB) — fetch the detail endpoint for nodes/edges.
{
"id": "af3…",
"name": "Tenant BD health",
"description": "All BDs with misconfigured subnets",
"category": 1,
"category_name": "Network Health",
"tags_list": ["audit"],
"created_by": { /* user */ },
"is_public": false,
"is_template": false,
"execution_count": 41,
"last_executed_at": "…",
"is_favorite": false,
"enable_time_machine": true,
"major_version": 2,
"minor_version": 3,
"version_string": "v2.3",
"created_at": "…",
"updated_at": "…"
}POST /api/queries/saved-queries/
Create a query. The canvas is sent as flow_data (containing nodes and edges).
GET /api/queries/saved-queries/<id>/
Full detail including version_history.
PATCH /api/queries/saved-queries/<id>/
Any change to nodes, edges, or post_processors auto-increments the version and appends to version_history. Non-structural fields (name, description) don't bump the version.
POST /api/queries/saved-queries/<id>/execute/
Record an execution and bump the query's usage counters. This endpoint does not run the query against APIC — the frontend performs the APIC call itself (via the APIC service) and then posts the outcome here so it lands in the execution log and audit trail. This keeps the view stateless and lets the frontend own retries and cancellation.
Request:
{
"success": true,
"result_count": 142,
"execution_time_ms": 1840,
"error_message": "",
"response_content": "…" // optional, stored on the audit entry
}Response 200:
{ "message": "Execution logged" }For long-running, multi-stage runs, use the pipeline path: POST /api/queries/pipeline-executions/ starts a background job and returns its id; subscribe to ws://…/ws/chain-execution/<job_id>/ to stream progress and results. See WebSockets.
POST /api/queries/saved-queries/validate-connection/
Collection-level (not per-id) action. Checks whether a parent class can contain a child class according to the Neo4j MIM.
Request: { "parentClass": "fvTenant", "childClass": "fvBD" }.
Response 200: { "isValid": true, "message": "…" }.
POST /api/queries/saved-queries/<id>/favorite/
Toggle favorite status on the query (one endpoint, flips the flag).
POST /api/queries/saved-queries/<id>/duplicate/
Server-side clone. Returns the new query.
Execution logs
Read-only. Populated automatically by every execution (manual or scheduled).
GET /api/queries/execution-logs/
Returns the logs the caller can see — queries they own, queries shared with them, public queries, or executions they ran.
Resource shape:
{
"id": "…",
"query": "af3…",
"query_name": "acme — All Bridge Domains",
"executed_by": "alice",
"executed_at": "2026-04-22T08:00:00Z",
"execution_time_ms": 1840,
"result_count": 142,
"success": true,
"error_message": null
}success is a boolean — there is no separate status field. Logs are written by the execute/ action and by scheduled runs.
Scheduled tasks
GET /api/queries/scheduled-tasks/
List scheduled tasks the user owns or has been granted access to.
Resource shape:
{
"id": "…",
"name": "Daily BD audit",
"saved_query": "af3…",
"query_name": "acme — All Bridge Domains",
"apic_connection_ids": [3, 7],
"frequency": "daily",
"minute_of_hour": 0,
"time_of_day": "02:00",
"day_of_week": null,
"day_of_month": null,
"scheduled_datetime": null,
"timezone": "Europe/Istanbul",
"status": "active",
"email_on_success": false,
"email_on_failure": true,
"email_recipients": ["[email protected]"],
"retry_enabled": true,
"retry_count": 3,
"retry_interval_minutes": 5,
"log_retention_days": 30,
"last_run_at": "2026-04-22T02:00:00+03:00",
"next_run_at": "2026-04-23T02:00:00+03:00",
"execution_count": 41,
"success_count": 40,
"failure_count": 1,
"success_rate": 97.6,
"schedule_description": "Daily at 02:00"
}status is one of active | paused | disabled.
POST /api/queries/scheduled-tasks/
Create a schedule. Cadence is frequency-based, not raw cron: frequency is once | hourly | daily | weekly | monthly, refined by the relevant fields (minute_of_hour, time_of_day, day_of_week, day_of_month, or scheduled_datetime for once).
POST /api/queries/scheduled-tasks/<id>/pause/ and .../resume/
Flip the task's status between active and paused. Paused tasks stay in the list but don't fire.
pause/→{ "status": "paused", "message": "Task paused successfully" }resume/→{ "status": "active", "message": "Task resumed successfully" }
POST /api/queries/scheduled-tasks/<id>/execute_now/
Trigger the task immediately rather than waiting for its schedule.
Other detail actions on this ViewSet: clone/, executions/. Collection actions: upcoming/, stats/.
Scheduled task executions
GET /api/queries/scheduled-executions/
History for scheduled-task runs. Filter by ?task_id=<id> for a single task's timeline; also accepts ?status=<…> and ?connection_id=<id>.
Task management settings
GET / PATCH /api/queries/task-settings/
Global task-management defaults (single row, id=1).
Fields:
default_retry_count— default retry attempts for a failing task (default 3).default_retry_interval_minutes— minutes between retries (default 5).default_log_retention_days— when to prune old execution logs (default 30).email_enabled— global on/off for task email notifications.email_from_address— From address used for those emails.
Pipeline executions
Pipelines chain multiple saved queries with variable passing between stages. Full pipeline definition lives on SavedQuery via a special node type — this ViewSet is about runs, not definitions.
POST /api/queries/pipeline-executions/
Start a pipeline run. flow_data and apic_connection_id are required; saved_query_id is optional. Creates a ChainExecutionJob (status pending) and returns its serialized form, including id — subscribe to ws://…/ws/chain-execution/<id>/ to stream progress. See WebSockets.
Response shape (job):
{
"id": "…",
"status": "pending",
"execution_mode": "…",
"total_stages": 4,
"completed_stages": 0,
"failed_stages": 0,
"current_stage_index": 0,
"progress_percentage": 0,
"created_at": "…",
"started_at": null,
"completed_at": null,
"execution_time_ms": null,
"errors": []
}GET /api/queries/pipeline-executions/
List the caller's pipeline runs (jobs with execution_mode='pipeline'), newest first.
GET /api/queries/pipeline-executions/<id>/
Full detail — every stage's inputs, outputs, and timing. The stages/ detail action returns the per-stage breakdown.
POST /api/queries/pipeline-executions/<id>/cancel/
Request cancellation. Only pending or running jobs can be cancelled; in-flight APIC calls finish, subsequent stages don't start.