A concept is a unit of logic in a project — a Vadalog, SQL, or Python program that produces an output predicate. The Concepts API lets you create concepts, run them (individually or as a dependency chain), read their results, and track execution progress. All paths are relative to the base URL and require authentication. All responses use the standard envelope.

Save a concept

Create or update a concept. Saving a concept with an existing_name updates it in place; otherwise a new concept is created.
POST /concepts/{project_id}/save
ParameterInRequiredDefaultDescription
project_idpathyesThe project ID.
definitionbodyyesThe concept body: Vadalog rules, a SQL query, or Python logic (per concept_type).
concept_typebodyno"logic"One of logic (Vadalog), sql, cypher, or python.
concept_namebodyconditionalRequired for sql, cypher, and python concepts.
output_predicatebodyno""The predicate this concept outputs.
descriptionbodynoHuman-readable description.
bindsbodynoBind annotations linking input/output predicates to data sources.
scopebodyno"user"Scope of the concept.
force_overwritebodynofalseOverwrite a conflicting concept instead of returning 409.

Example

curl -X POST "$BASE_URL/concepts/$PROJECT_ID/save" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "definition": "@output(\"location\").\nlocation(L) <- company(_, L).",
    "concept_type": "logic",
    "scope": "user"
  }'
{
  "status": "success",
  "message": "Concept saved",
  "data": { "id": "cpt_8f2a..." }
}

List concepts

Return all concepts in a project, enriched with their parsed code and binds.
GET /concepts/{project_id}/list
ParameterInRequiredDefaultDescription
project_idpathyesThe project ID.
scopequeryno"user"Scope of the project.
curl "$BASE_URL/concepts/$PROJECT_ID/list?scope=user" \
  -H "Authorization: Bearer $TOKEN"
data is an array of concept objects (name, type, definition, binds, output predicate, description, group, and position).

Run a concept

Execute a concept and its dependency chain. The engine runs at most one job at a time per workspace; see Execution status to track progress.
POST /concepts/{project_id}/run/{concept_name}
ParameterInRequiredDefaultDescription
project_idpathyesThe project ID.
concept_namepathyesThe target concept to run.
scopebodyno"user"Scope of the project.
paramsbodyno{}Runtime parameter values referenced by the program.
force_rerunbodynotrueRe-run even if cached results exist.
persist_outputsbodynotruePersist output predicates so they can be read with /fetch.
computebodynoCompute target.

Example

curl -X POST "$BASE_URL/concepts/$PROJECT_ID/run/location" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "scope": "user", "persist_outputs": true }'
On success, data contains the execution result. On a run error, status is "error" and data carries an errorCode and errorMessage:
{
  "status": "error",
  "message": "Evaluation failed",
  "data": { "errorCode": "VL0023", "errorMessage": "..." }
}
For long-running jobs, prefer firing the run and then polling Execution status rather than blocking on the response. A WebSocket variant, /concepts/{project_id}/run-stream/{concept_name}, streams per-concept progress frames if you need live updates.

Fetch concept results

Read the persisted rows of an output predicate, with pagination.
GET /concepts/{project_id}/fetch
ParameterInRequiredDefaultDescription
project_idpathyesThe project ID.
output_predicatequeryyesThe predicate to read.
paramsqueryno{}JSON string of parameter values.
pagequeryno1Page number.
page_sizequeryno30Rows per page (max 1000).
order_byquerynoe.g. 0:asc,2:desc.
project_scopequeryno"user"Scope of the project.
curl "$BASE_URL/concepts/$PROJECT_ID/fetch?output_predicate=location&page=1&page_size=30" \
  -H "Authorization: Bearer $TOKEN"
{
  "status": "success",
  "message": "Success",
  "data": {
    "rows": [ ["Mountain View, CA"], ["Redmond, WA"] ],
    "count": 2,
    "page": 1,
    "page_size": 30
  }
}

Search concept results

Filter the rows of an output predicate by a search term and/or per-column filters. Same pagination as /fetch.
POST /concepts/{project_id}/search
ParameterInRequiredDefaultDescription
project_idpathyesThe project ID.
output_predicatequeryyesThe predicate to search.
search_termbodynoFree-text term matched across columns.
column_filtersbodynoArray of { "position": <col index>, "value": <string> }.
project_scopequeryno"user"Scope of the project.
curl -X POST "$BASE_URL/concepts/$PROJECT_ID/search?output_predicate=location" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "search_term": "CA", "column_filters": [{ "position": 0, "value": "Mountain" }] }'
The response shape matches /fetch.

Rename a concept

Rename a concept and propagate the new name to every dependent concept.
POST /concepts/{project_id}/rename
ParameterInRequiredDefaultDescription
project_idpathyesThe project ID.
old_namebodyyesCurrent concept name.
new_namebodyyesNew concept name.
scopebodyno"user"Scope of the project.

Execution status

When a concept runs, the platform persists a snapshot of the run (one per run, most recent 50 kept per project). These read-only endpoints report the state of the latest run — they do not start one.

Single project

GET /concepts/{project_id}/execution-status
ParameterInRequiredDefaultDescription
project_idpathyesThe project ID.
scopequeryno"user"Scope of the project.
{
  "status": "success",
  "message": "Execution status",
  "data": {
    "execution_id": "f1c2...",
    "project_id": "proj_123",
    "target_concept": "final_report",
    "order": ["raw_data", "cleaned", "final_report"],
    "total": 3,
    "statuses": {
      "raw_data": { "status": "success" },
      "cleaned":  { "status": "running" }
    },
    "status": "running",
    "failure_reason": null,
    "started_at": "2026-06-19T10:00:00+00:00",
    "updated_at": "2026-06-19T10:00:04+00:00",
    "finished_at": null,
    "duration_ms": null
  }
}
The top-level data.status is the primary field:
ValueMeaning
idleNo run history (single-project endpoint only).
runningA run is in progress. The currently-executing concept is the key in statuses whose status is running.
successThe run completed successfully.
errorThe run failed — see failure_reason.
cancelledThe run was cancelled.
interruptedThe connection dropped or the server restarted mid-run.
success, error, cancelled, and interrupted are terminal. Poll roughly every 1.5 s while running, and stop once the status is terminal or idle.

All projects (batch)

GET /concepts/execution-statuses
ParameterInRequiredDefaultDescription
scopesqueryno"user"Comma-separated scopes, e.g. user,organization.
data is a map keyed by project_id, where each value is the same snapshot as above. Only projects whose latest run is running, error, cancelled, or interrupted appear — a project absent from the map is idle (never run, or its last run succeeded).

Other operations

OperationEndpointNotes
Generate a description with the LLMPOST /concepts/{project_id}/generate-descriptionBody: concept_name, scope. Returns { "description": "..." }.
Read (or lazily generate) a descriptionGET /concepts/{project_id}/descriptionQuery: concept_name, scope.
Ask a question over predicate dataPOST /concepts/{project_id}/llmBody: predicate_names/predicate_data, question. Returns { "response": "..." }.
Export results to CSV / download a fileGET /concepts/{project_id}/downloadQuery: path, export_csv, concept_name. Returns the raw file, not the envelope.
Delete conceptsPOST /concepts/{project_id}/cleanupBody: concept_names (omit to delete all), scope.