Catalog API

Base URL: /api/v1/catalog

All endpoints require authentication via a Bearer token in the Authorization header.

Authorization: Bearer <token>

Table of Contents

  1. POST /catalog/create
  2. POST /catalog/create/link
  3. GET /catalog/get/tasks_ready_to_run/{project_laui}
  4. GET /catalog/get
  5. GET /catalog/get/item_revisions
  6. POST /catalog/delete
  7. POST /catalog/restore/{item_laui}
  8. POST /catalog/search
  9. GET /catalog/item-types/supported-types
  10. POST /catalog/bootstrap
  11. POST /catalog/validate

1. Create Item

Creates a new catalog item. The item_type field determines which schema (config/schema/{item_type}.json) is used to validate the remaining fields.

POST /api/v1/catalog/create

Description

Accepts a JSON body with item_type as a required field plus any additional fields defined in that item type's schema. The request model uses extra="allow", so all schema-defined fields are passed as top-level keys alongside item_type.

Every item type schema defines unique_constraints -- a set of fields that together must be unique. Attempting to create a duplicate results in a 409 Conflict.

Access Control

No explicit access check at the route level. Access is managed through the access_patch field on the item itself and inherited from the parent when parent_laui is provided.

Request Body

FieldTypeRequiredDescription
item_typestringYesThe type of item to create. Must match a schema file in config/schema/.
namestringYesName of the item. Validation rules (regex, length) depend on item_type.
parent_lauiObjectIdConditionalRequired if is_root is false or omitted. The LAUI of the parent item.
is_rootbooleanNoSet to true for root-level items. Cannot be combined with parent_laui. Default: false.
access_patchobjectNoAccess control patch. Default adds the creating user as owner.
...extra fieldsvariesDepends on schemaAdditional fields defined in the item type's schema.

Parent/Root Rules

  • If is_root is true, then parent_laui must not be present.
  • If is_root is false (or omitted), then parent_laui must be a valid ObjectId string.

Item Type Hierarchy

The parent item type must allow the child item type according to config/catalog.json. Key mappings:

Parent TypeAllowed Children
folder.accountfolder.project, folder.trash, folder.users
folder.projectfolder.action, folder.asset, folder.workflow, folder.operator, folder.payload, folder.connection, folder.bootstrap, folder.config, folder.ai
folder.workflowfolder.workflow, task, config, connection, payload, operator, action
folder.operatorfolder.operator, operator
folder.connectionfolder.connection, connection
folder.payloadfolder.payload, payload
folder.configfolder.config, config
folder.assetfolder.asset, folder.report, folder.table, html_report, table, config
folder.aifolder.ai, folder.chat, folder.skill
folder.chatfolder.chat, chat
folder.skillfolder.skill, skill
folder.userchat_history

Examples

1a. Create a project folder

POST /api/v1/catalog/create

{
  "item_type": "folder.project",
  "name": "ETL Pipeline Project",
  "description": "Production ETL pipelines for analytics",
  "parent_laui": "507f1f77bcf86cd799439011",
  "folder_metadata": {}
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e01"
}

1b. Create a workflow folder

{
  "item_type": "folder.workflow",
  "name": "Daily Ingestion",
  "description": "Daily data ingestion workflow",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e01",
  "folder_metadata": {
    "state": "ACTIVE"
  }
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e02"
}

1c. Create an operator

The name field must match regex ^[a-zA-Z0-9_\-]+\.operator$.

{
  "item_type": "operator",
  "name": "s3-download.operator",
  "description": "Downloads files from S3 buckets",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e03",
  "codeblock": {
    "language": "python",
    "code": "import boto3\n\ndef execute(connection, payload, config):\n    s3 = boto3.client('s3', **connection)\n    s3.download_file(payload['bucket'], payload['key'], payload['dest'])\n    return {'status': 'downloaded'}"
  },
  "bashblock": {
    "language": "bash",
    "code": "pip install boto3"
  },
  "connection": {
    "aws_access_key_id": "",
    "aws_secret_access_key": "",
    "region_name": "us-east-1"
  },
  "payload": {
    "bucket": "my-bucket",
    "key": "data/file.csv",
    "dest": "/tmp/file.csv"
  }
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e04"
}

1d. Create an action

The name field must match regex ^[a-zA-Z0-9_\-]+\.action$.

{
  "item_type": "action",
  "name": "notify-slack.action",
  "description": "Sends a notification to a Slack channel",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
  "codeblock": {
    "language": "python",
    "code": "import requests\n\ndef execute(connection, action_variables):\n    requests.post(connection['webhook_url'], json={'text': action_variables['message']})"
  },
  "bashblock": {
    "language": "bash",
    "code": "pip install requests"
  },
  "project_laui": "60d5ec49f1b2c72b8c9a1e01",
  "account_laui": "507f1f77bcf86cd799439011"
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e05"
}

1e. Create a connection

{
  "item_type": "connection",
  "name": "postgresql",
  "description": "Connection to the bundled postgres-demo database",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e06",
  "content": {
    "host": "postgres-demo",
    "port": 5432,
    "database": "postgres_demo_db",
    "user": "postgres"
  },
  "max_parallelism": 5,
  "sort_dict": {}
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e07"
}

1f. Create a payload

{
  "item_type": "payload",
  "name": "ingestion-params",
  "description": "Parameters for the daily ingestion job",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
  "content": {
    "source_table": "raw_events",
    "target_table": "staged_events",
    "batch_size": 10000,
    "dedup_keys": ["event_id", "timestamp"]
  }
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e08"
}

1g. Create config items (all config_type values)

The config_type field must be one of: system, task, UIaction, taskAction, connection, workflow.

System config:

{
  "item_type": "config",
  "name": "global-settings",
  "description": "System-wide configuration",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e09",
  "config_type": "system",
  "content": {
    "max_concurrent_tasks": 50,
    "default_timeout_seconds": 3600,
    "log_level": "INFO"
  }
}

Task config:

{
  "item_type": "config",
  "name": "task-retry-policy",
  "description": "Default retry policy for tasks",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e09",
  "config_type": "task",
  "content": {
    "total_retries": 3,
    "retry_interval": 5,
    "backoff_factor": 2
  }
}

UIaction config:

{
  "item_type": "config",
  "name": "dashboard-actions",
  "description": "UI action button configuration",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e09",
  "config_type": "UIaction",
  "content": {
    "buttons": [
      {"label": "Run All", "action": "run_all_tasks"},
      {"label": "Pause", "action": "pause_workflow"}
    ]
  }
}

taskAction config:

{
  "item_type": "config",
  "name": "pre-run-checks",
  "description": "Actions to execute before task runs",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e09",
  "config_type": "taskAction",
  "content": {
    "pre_actions": ["validate_schema", "check_connection"],
    "post_actions": ["send_notification"]
  }
}

Connection config:

{
  "item_type": "config",
  "name": "connection-pool-settings",
  "description": "Connection pool configuration",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e09",
  "config_type": "connection",
  "content": {
    "pool_size": 10,
    "max_overflow": 5,
    "pool_timeout": 30
  }
}

Workflow config:

{
  "item_type": "config",
  "name": "workflow-defaults",
  "description": "Default settings for workflow execution",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e09",
  "config_type": "workflow",
  "content": {
    "max_active_runs": 1,
    "catchup": false,
    "default_priority": 1
  }
}

Response (same for all config types) 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e0a"
}

1h. Create a task (full example)

{
  "item_type": "task",
  "name": "ingest-raw-events",
  "description": "Ingests raw events from source into staging",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
  "partition": "ANALYTICS",
  "project_laui": "60d5ec49f1b2c72b8c9a1e01",
  "account_laui": "507f1f77bcf86cd799439011",
  "operator_laui": "60d5ec49f1b2c72b8c9a1e04",
  "connection_laui": "60d5ec49f1b2c72b8c9a1e07",
  "start_date": "2026-03-01T00:00:00Z",
  "end_date": null,
  "logical_date": "2026-03-19T06:00:00Z",
  "frequency": "0 6 * * *",
  "state": "scheduled",
  "payload_laui": "60d5ec49f1b2c72b8c9a1e08",
  "payload": {
    "source_table": "raw_events",
    "target_table": "staged_events",
    "batch_size": 10000
  },
  "attached_config_lauis": ["60d5ec49f1b2c72b8c9a1e0a"],
  "config": {},
  "total_retries": 3,
  "retry_interval": 5,
  "priority": 2,
  "actions": {
    "create_actions": [],
    "pre_actions": ["60d5ec49f1b2c72b8c9a1e05"],
    "running_actions": [],
    "post_actions": []
  }
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e0b"
}

1i. Create a table

{
  "item_type": "table",
  "name": "raw_events",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e0c",
  "source_system": "REDSHIFT",
  "location_uri": "jdbc:redshift://cluster.abc123.us-east-1.redshift.amazonaws.com:5439/analytics",
  "status": "ACTIVE",
  "load_strategy": "INCREMENTAL",
  "row_count": 5842310,
  "quality_score": 98.7,
  "schema_definition": {
    "columns": [
      {"name": "event_id", "type": "VARCHAR(64)", "nullable": false},
      {"name": "event_type", "type": "VARCHAR(128)", "nullable": false},
      {"name": "timestamp", "type": "TIMESTAMP", "nullable": false},
      {"name": "payload", "type": "SUPER", "nullable": true}
    ]
  },
  "etl_watermarks": {
    "max_updated_at": "2026-03-18T23:59:59Z"
  },
  "lineage_metadata": {
    "upstream_sources": ["s3://data-lake/raw/events/"],
    "transformation_job_id": "60d5ec49f1b2c72b8c9a1e0b"
  }
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e0d"
}

1j. Create an html_report

The name field must match regex ^[a-zA-Z0-9_\-]+\.action$.

{
  "item_type": "html_report",
  "name": "weekly-summary.action",
  "description": "Weekly pipeline execution summary",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e0e",
  "html": "<html><body><h1>Weekly Summary</h1><p>Total runs: 142</p><p>Success rate: 97.2%</p></body></html>"
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e0f"
}

1k. Create a skill

{
  "item_type": "skill",
  "name": "SQL Generation",
  "description": "Generates optimized SQL queries from natural language descriptions",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e10",
  "content": "You are a SQL expert. When the user describes a data query, generate an optimized SQL statement. Always use CTEs for readability. Prefer window functions over subqueries where applicable."
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e11"
}

1l. Create an chat_history

{
  "item_type": "chat_history",
  "name": "Operator Gen Session - March 19",
  "description": "AI session that generated the S3 download operator",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e12",
  "created_item_type": "operator",
  "ai_provider": "anthropic",
  "connection_laui": "60d5ec49f1b2c72b8c9a1e13",
  "connection_name": "Claude API Key",
  "messages": [
    {"role": "user", "content": "Create an operator that downloads files from S3"},
    {"role": "assistant", "content": "Here is the operator code..."}
  ],
  "generated_content": {
    "codeblock": "import boto3\ndef execute(connection, payload, config): ..."
  }
}

Response 200 OK

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e14"
}

Error Responses

422 Unprocessable Entity -- Schema validation failure

Returned when the request body fails validation against the item type's schema.

{
  "detail": [
    {
      "type": "string_pattern_mismatch",
      "loc": ["name"],
      "msg": "String should match pattern '^[a-zA-Z0-9_\\-]+\\.operator$'",
      "input": "invalid name!",
      "expected_format": {
        "name": "name",
        "datatype": "string",
        "required": true,
        "regex": "^[a-zA-Z0-9_\\-]+\\.operator$"
      }
    },
    {
      "parent_laui": {"name": "parent_laui", "required": false, "datatype": "ObjectId", "default": null},
      "is_root": {"name": "is_root", "required": false, "datatype": "boolean", "default": false},
      "rules": {
        "valid_requests": [
          {"is_root": true},
          {"is_root": false, "parent_laui": "valid objectid string"},
          {"parent_laui": "valid objectid string"}
        ],
        "info": [
          "If value passed for is_root is true then parent_laui cannot be present.",
          "If value passed for is_root is false or if you do not pass value to is_root then parent_laui must be present."
        ]
      }
    }
  ]
}

422 Unprocessable Entity -- Invalid hierarchy

Returned when the item_type is not allowed under the given parent_laui.

{
  "detail": {
    "message": "invalid item_type for the passed parent_laui",
    "item_type_passed": "task",
    "allowed_item_types": ["folder.operator", "operator"]
  }
}

422 Unprocessable Entity -- Schema file errors

Returned when the schema file for the given item_type has validation issues.

{
  "detail": {
    "summary": "errors found in unknown_type.json",
    "validation_context": { }
  }
}

400 Bad Request -- Invalid argument

{
  "detail": "Invalid argument: <description>"
}

403 Forbidden -- Access denied

{
  "detail": "Access denied"
}

409 Conflict -- Unique constraint violation

Returned when an item with the same unique key combination already exists.

{
  "detail": "Item already exists with the same unique key"
}

503 Service Unavailable -- Write conflict

Returned when a MongoDB write conflict occurs (error code 112), typically due to concurrent transaction contention.

{
  "detail": "write_conflict"
}

500 Internal Server Error

{
  "detail": "Internal server error: <message>"
}

Creates a parent-child link between two existing catalog items.

POST /api/v1/catalog/create/link

Description

Links establish relationships between items. A link records the parent item, child item, their respective types, and whether the parent is the "true parent" (used for containment hierarchy and access inheritance) or a soft reference.

Access Control

CheckPermissionTarget
ParentEDITparent_laui
ChildVIEWchild_laui

Both checks must pass. If the caller lacks EDIT on the parent or VIEW on the child, the request is rejected with 403.

Request Body

FieldTypeRequiredDescription
parent_lauiObjectIdYesThe LAUI of the parent item.
child_lauiObjectIdYesThe LAUI of the child item.

Example

POST /api/v1/catalog/create/link

{
  "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
  "child_laui": "60d5ec49f1b2c72b8c9a1e0b"
}

Success Response

200 OK

{
  "link_laui": "60d5ec49f1b2c72b8c9a2a01"
}

Error Responses

403 Forbidden -- Insufficient permissions

{
  "detail": "Access denied"
}

404 Not Found -- Parent or child does not exist

{
  "detail": "Item not found with laui: 60d5ec49f1b2c72b8c9a1e02"
}

422 Unprocessable Entity -- Validation error

{
  "detail": [
    {
      "type": "value_error",
      "loc": ["parent_laui"],
      "msg": "value is not a valid ObjectId"
    }
  ]
}

500 Internal Server Error

{
  "detail": "Internal server error: <message>"
}

3. Get Tasks Ready to Run

Returns all tasks under a project that are eligible for execution based on scheduling, state, and retry policies.

GET /api/v1/catalog/get/tasks_ready_to_run/{project_laui}

Description

Uses a MongoDB aggregation pipeline to find tasks that meet all of the following criteria:

  • item_type is task
  • project_laui matches the path parameter
  • Not soft-deleted (deleted_at is null)
  • start_date is before the current time
  • user_set_state is not cancel
  • Either end_date is null or logical_date <= end_date
  • One of:
    • Normal path: state is scheduled or success, and logical_date <= now
    • Retry path: state is error or timeout, total_retries > 0, retry_number < total_retries, and last_run_date + (retry_interval * 60000ms) <= now
  • The parent workflow's folder_metadata.state is not PAUSE

Access Control

CheckPermissionTarget
ProjectOWNproject_laui

Path Parameters

ParameterTypeRequiredDescription
project_lauiObjectIdYesThe LAUI of the project containing the tasks.

Example

GET /api/v1/catalog/get/tasks_ready_to_run/60d5ec49f1b2c72b8c9a1e01

Success Response

200 OK

Returns an array of task objects.

[
  {
    "laui": "60d5ec49f1b2c72b8c9a1e0b",
    "item_type": "task",
    "name": "ingest-raw-events",
    "partition": "ANALYTICS",
    "project_laui": "60d5ec49f1b2c72b8c9a1e01",
    "account_laui": "507f1f77bcf86cd799439011",
    "operator_laui": "60d5ec49f1b2c72b8c9a1e04",
    "connection_laui": "60d5ec49f1b2c72b8c9a1e07",
    "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
    "start_date": "2026-03-01T00:00:00Z",
    "end_date": null,
    "logical_date": "2026-03-19T06:00:00Z",
    "frequency": "0 6 * * *",
    "state": "scheduled",
    "iteration": 41,
    "total_retries": 3,
    "retry_interval": 5,
    "retry_number": 0,
    "priority": 2,
    "payload": {
      "source_table": "raw_events",
      "target_table": "staged_events",
      "batch_size": 10000
    },
    "config": {},
    "actions": {
      "create_actions": [],
      "pre_actions": ["60d5ec49f1b2c72b8c9a1e05"],
      "running_actions": [],
      "post_actions": []
    },
    "actions_status": {
      "pre_actions": [],
      "running_actions": [],
      "post_actions": []
    }
  },
  {
    "laui": "60d5ec49f1b2c72b8c9a1e15",
    "item_type": "task",
    "name": "transform-events",
    "partition": "ANALYTICS",
    "project_laui": "60d5ec49f1b2c72b8c9a1e01",
    "account_laui": "507f1f77bcf86cd799439011",
    "operator_laui": "60d5ec49f1b2c72b8c9a1e16",
    "connection_laui": "60d5ec49f1b2c72b8c9a1e07",
    "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
    "start_date": "2026-03-01T00:00:00Z",
    "end_date": null,
    "logical_date": "2026-03-19T07:00:00Z",
    "frequency": "0 7 * * *",
    "state": "error",
    "iteration": 39,
    "total_retries": 2,
    "retry_interval": 10,
    "retry_number": 1,
    "priority": 1,
    "last_run_date": "2026-03-19T07:01:23Z",
    "payload": null,
    "config": {},
    "actions": {
      "create_actions": [],
      "pre_actions": [],
      "running_actions": [],
      "post_actions": []
    },
    "actions_status": {
      "pre_actions": [],
      "running_actions": [],
      "post_actions": []
    }
  }
]

Error Responses

403 Forbidden -- Not project owner

{
  "detail": "Access denied"
}

404 Not Found -- Project does not exist

{
  "detail": "Item not found with laui: 60d5ec49f1b2c72b8c9a1e01"
}

500 Internal Server Error

{
  "detail": "Internal server error: <message>"
}

4. Get Items

Retrieves catalog items by LAUI, root status, or hierarchy traversal with pagination.

GET /api/v1/catalog/get

Description

A flexible endpoint for fetching items. Supports looking up a single item by its LAUI, fetching root-level items, traversing parent-child hierarchies, and filtering by item type -- all with pagination.

Access Control

ScenarioPermissionTarget
is_root=trueSkipped(Returns items the user has access to)
Only item_laui passed (no item_type, parent_or_child, or is_root)Skipped(Returns the item directly)
item_laui + other filtersVIEWitem_laui

Query Parameters

ParameterTypeRequiredDefaultDescription
item_lauiObjectIdConditional--The LAUI of the item to fetch or traverse from. Required if is_root is not true.
is_rootbooleanConditional--Set to true to fetch root-level items. Required if item_laui is not provided.
item_typestringNo--Filter results by item type.
parent_or_child"parent" or "child"No--Direction of hierarchy traversal from item_laui.
depthintegerNo1Number of hierarchy levels to traverse.
per_pageintegerNo10Results per page. Range: 0-1000.
pageintegerNo1Page number. Minimum: 1.
is_deletedbooleanNotrueWhether to include soft-deleted items.
page_tokenstringNo--Opaque token for cursor-based pagination (used for shared items).
item_permissionstringNo--Filter by permission level. Values: view, edit, own, delete, true_parent_edit, is_true_parent.
sort_bystringNo--Field name to sort results by.
filter_statestringNo--Filter items by their state field value.

Validation Rules

  • Either item_laui or is_root must be provided. If neither is passed, the endpoint returns 400.
  • If is_root is true, the following fields cannot be passed: item_laui, item_type, parent_or_child. Passing any of them returns 400.
  • Pagination bounds: per_page must be between 0 and 1000; page must be at least 1. Out-of-range values return 400.

Examples

4a. Get a single item by LAUI

GET /api/v1/catalog/get?item_laui=60d5ec49f1b2c72b8c9a1e0b

Response 200 OK

When only item_laui is passed (no additional filters), returns a flat item object:

{
  "laui": "60d5ec49f1b2c72b8c9a1e0b",
  "item_type": "task",
  "name": "ingest-raw-events",
  "description": "Ingests raw events from source into staging",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
  "is_root": false,
  "state": "scheduled",
  "project_laui": "60d5ec49f1b2c72b8c9a1e01",
  "account_laui": "507f1f77bcf86cd799439011",
  "operator_laui": "60d5ec49f1b2c72b8c9a1e04",
  "connection_laui": "60d5ec49f1b2c72b8c9a1e07",
  "frequency": "0 6 * * *",
  "logical_date": "2026-03-19T06:00:00Z",
  "start_date": "2026-03-01T00:00:00Z",
  "end_date": null,
  "priority": 2,
  "total_retries": 3,
  "retry_interval": 5,
  "created_at": "2026-03-01T10:00:00Z",
  "version": 3
}

4b. Get root items

GET /api/v1/catalog/get?is_root=true

Response 200 OK

{
  "items": [
    {
      "laui": "507f1f77bcf86cd799439011",
      "item_type": "folder.account",
      "name": "My Organization",
      "is_root": true,
      "children": [
        {
          "laui": "60d5ec49f1b2c72b8c9a1e01",
          "item_type": "folder.project",
          "name": "ETL Pipeline Project"
        }
      ]
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 10,
    "has_next": false,
    "next_page_token": null
  }
}

4c. Get children of an item

GET /api/v1/catalog/get?item_laui=60d5ec49f1b2c72b8c9a1e02&parent_or_child=child

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e0b",
      "item_type": "task",
      "name": "ingest-raw-events",
      "children": []
    },
    {
      "laui": "60d5ec49f1b2c72b8c9a1e15",
      "item_type": "task",
      "name": "transform-events",
      "children": []
    },
    {
      "laui": "60d5ec49f1b2c72b8c9a1e0a",
      "item_type": "config",
      "name": "workflow-defaults",
      "children": []
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 10,
    "has_next": false,
    "next_page_token": null
  }
}

4d. Get parents of an item (breadcrumb)

GET /api/v1/catalog/get?item_laui=60d5ec49f1b2c72b8c9a1e0b&parent_or_child=parent&depth=3

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e02",
      "item_type": "folder.workflow",
      "name": "Daily Ingestion",
      "children": []
    },
    {
      "laui": "60d5ec49f1b2c72b8c9a1e01",
      "item_type": "folder.project",
      "name": "ETL Pipeline Project",
      "children": []
    },
    {
      "laui": "507f1f77bcf86cd799439011",
      "item_type": "folder.account",
      "name": "My Organization",
      "children": []
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 10,
    "has_next": false,
    "next_page_token": null
  }
}

4e. Get children filtered by item type with pagination

GET /api/v1/catalog/get?item_laui=60d5ec49f1b2c72b8c9a1e02&parent_or_child=child&item_type=task&per_page=5&page=2

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e20",
      "item_type": "task",
      "name": "archive-old-events",
      "children": []
    }
  ],
  "pagination": {
    "current_page": 2,
    "per_page": 5,
    "has_next": false,
    "next_page_token": null
  }
}

4f. Get items with permission filter

GET /api/v1/catalog/get?item_laui=60d5ec49f1b2c72b8c9a1e01&parent_or_child=child&item_permission=edit

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e02",
      "item_type": "folder.workflow",
      "name": "Daily Ingestion",
      "children": []
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 10,
    "has_next": false,
    "next_page_token": null
  }
}

Error Responses

400 Bad Request -- Neither item_laui nor is_root provided

{
  "detail": "either one of item_laui or is_root must be passed"
}

400 Bad Request -- Invalid pagination parameters

{
  "detail": {
    "issue": "invalid pagination params passed",
    "expected pagination params": {
      "per_page": {"min": 0, "max": 1000},
      "page": {"min": 1}
    }
  }
}

400 Bad Request -- Invalid field combination with is_root

{
  "detail": {
    "error_type": "Invalid Field Combination",
    "message": "Invalid fields passed when 'is_root' is set to True.",
    "invalid_fields_passed": ["item_type"],
    "fields_disallowed_for_root": ["item_type", "item_laui", "parent_or_child"]
  }
}

403 Forbidden -- Insufficient view access

{
  "detail": "Access denied"
}

404 Not Found

{
  "detail": "Item not found with laui: 60d5ec49f1b2c72b8c9a1e0b"
}

500 Internal Server Error

{
  "detail": "Internal server error: <message>"
}

5. Get Item Revisions

Retrieves the version history for a catalog item, or a specific version snapshot.

GET /api/v1/catalog/get/item_revisions

Description

Every time a versioned field on an item is updated, a revision is created. This endpoint returns either the full list of revisions (as projections with LAUI and item_laui) or a specific revision by version number (as a full ItemRevision).

Access Control

No explicit access check at the route level.

Query Parameters

ParameterTypeRequiredDescription
item_lauiObjectIdYesThe LAUI of the item whose revisions to fetch.
versionintegerNoA specific version number. If omitted, returns all revisions.

Examples

5a. Get all revisions for an item

GET /api/v1/catalog/get/item_revisions?item_laui=60d5ec49f1b2c72b8c9a1e0b

Response 200 OK

Returns List[ItemRevisionProjection]:

[
  {
    "laui": "60d5ec49f1b2c72b8c9a3a01",
    "item_laui": "60d5ec49f1b2c72b8c9a1e0b"
  },
  {
    "laui": "60d5ec49f1b2c72b8c9a3a02",
    "item_laui": "60d5ec49f1b2c72b8c9a1e0b"
  },
  {
    "laui": "60d5ec49f1b2c72b8c9a3a03",
    "item_laui": "60d5ec49f1b2c72b8c9a1e0b"
  }
]

5b. Get a specific version

GET /api/v1/catalog/get/item_revisions?item_laui=60d5ec49f1b2c72b8c9a1e0b&version=2

Response 200 OK

Returns a single ItemRevision:

{
  "laui": "60d5ec49f1b2c72b8c9a3a02",
  "item_laui": "60d5ec49f1b2c72b8c9a1e0b",
  "name": "ingest-raw-events",
  "item_type": "task",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
  "is_root": false,
  "description": "Ingests raw events from source into staging (v2 - added dedup)",
  "connection_laui": "60d5ec49f1b2c72b8c9a1e07",
  "payload": {
    "source_table": "raw_events",
    "target_table": "staged_events",
    "batch_size": 10000,
    "dedup_keys": ["event_id"]
  },
  "created_at": "2026-03-10T14:22:00Z",
  "created_by": "507f1f77bcf86cd799439099",
  "updated_by": "507f1f77bcf86cd799439099"
}

Error Responses

404 Not Found -- Item or version does not exist

{
  "detail": "Item not found with laui: 60d5ec49f1b2c72b8c9a1e0b"
}

500 Internal Server Error

{
  "detail": "Internal server error: <message>"
}

6. Delete Item

Soft-deletes or hard-deletes a catalog item.

POST /api/v1/catalog/delete

Description

By default, performs a soft delete (sets deleted_at timestamp). When hard_delete is true, permanently removes the item and its data from the database.

If parent_laui is provided, the delete operation also removes the link between the parent and the item.

Access Control

CheckPermissionTarget
ItemDELETEitem_laui

Request Body

FieldTypeRequiredDefaultDescription
item_lauiObjectIdYes--The LAUI of the item to delete.
parent_lauiObjectIdNo--The LAUI of the parent item. If provided, removes the link as well.
hard_deletebooleanNofalseIf true, permanently deletes the item. If false, soft-deletes (sets deleted_at).

Examples

6a. Soft delete

POST /api/v1/catalog/delete

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e0b",
  "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
  "hard_delete": false
}

Response 200 OK

{
  "message": "Item deleted successfully"
}

6b. Hard delete

{
  "item_laui": "60d5ec49f1b2c72b8c9a1e0f",
  "hard_delete": true
}

Response 200 OK

{
  "message": "Item deleted successfully"
}

Error Responses

403 Forbidden -- No delete permission

{
  "detail": "Access denied"
}

404 Not Found

{
  "detail": "Item not found with laui: 60d5ec49f1b2c72b8c9a1e0b"
}

422 Unprocessable Entity -- Validation error

{
  "detail": [
    {
      "type": "value_error",
      "loc": ["item_laui"],
      "msg": "value is not a valid ObjectId"
    }
  ]
}

500 Internal Server Error

{
  "detail": "Internal server error: <message>"
}

7. Restore Item

Restores a previously soft-deleted item.

POST /api/v1/catalog/restore/{item_laui}

Description

Clears the deleted_at timestamp on a soft-deleted item, making it active again in the catalog.

Access Control

CheckPermissionTarget
ItemDELETEitem_laui

Path Parameters

ParameterTypeRequiredDescription
item_lauiObjectIdYesThe LAUI of the item to restore.

Example

POST /api/v1/catalog/restore/60d5ec49f1b2c72b8c9a1e0b

Success Response

200 OK

{
  "message": "Item restored successfully"
}

Error Responses

403 Forbidden -- No delete permission

{
  "detail": "Access denied"
}

404 Not Found -- Item does not exist

{
  "detail": "Item not found with laui: 60d5ec49f1b2c72b8c9a1e0b"
}

422 Unprocessable Entity -- Invalid ObjectId

{
  "detail": [
    {
      "type": "value_error",
      "loc": ["item_laui"],
      "msg": "value is not a valid ObjectId"
    }
  ]
}

500 Internal Server Error

{
  "detail": "Internal server error: <message>"
}

Searches catalog items or links with flexible filters, optional projections, and pagination.

POST /api/v1/catalog/search

Description

A powerful search endpoint that supports two mutually exclusive search modes:

  • Item search: Finds items by type, name, parent, batch LAUIs, or primary key lookup. Supports field projection (include/exclude).
  • Link search: Finds links by parent, child, parent type, child type, or true_parent flag.

Exactly one of item_filter or link_filter must be provided. Providing both or neither results in a 422 error.

Access Control

No explicit access check at the route level.

Request Body

FieldTypeRequiredDescription
item_filterSearchItemsFilterConditionalFilter for item search. Mutually exclusive with link_filter.
link_filterSearchLinksFilterConditionalFilter for link search. Mutually exclusive with item_filter.
paginationPaginationRequestNoPagination settings.
projectionSearchItemsProjectionNoField projection for item searches. Ignored for link searches.

SearchItemsFilter

FieldTypeDescription
item_lauiObjectIdFind a specific item by LAUI.
is_rootbooleanFilter by root status.
item_typestringFilter by item type.
namestringFilter by name (exact match).
parent_lauiObjectIdFilter by parent LAUI.
item_lauisList[ObjectId]Batch lookup by multiple LAUIs.
get_by_pkbooleanIf true, look up by primary key. Requires item_type and all PK fields for that type. Default: false.
...extra fieldsvariesAny additional fields to filter on (e.g., state, project_laui). Model uses extra="allow".

SearchLinksFilter

FieldTypeDescription
parent_lauiObjectIdFilter links by parent LAUI.
child_lauiObjectIdFilter links by child LAUI.
true_parentbooleanFilter links by true_parent flag.
parent_typestringFilter links by parent item type.
child_typestringFilter links by child item type.

SearchItemsProjection

FieldTypeDescription
includeList[string]Fields to include in the response. item_type and pk are always included.
excludeList[string]Fields to exclude from the response.

PaginationRequest

FieldTypeDefaultDescription
pageinteger1Page number.
per_pageinteger10Results per page.
sort_order"asc" or "desc""asc"Sort direction by created_at.
page_tokenstring--Opaque cursor token for pagination.

Examples

8a. Search items by item_type

POST /api/v1/catalog/search

{
  "item_filter": {
    "item_type": "task"
  },
  "pagination": {
    "page": 1,
    "per_page": 20,
    "sort_order": "desc"
  }
}

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e15",
      "item_type": "task",
      "pk": "transform-events-60d5ec49f1b2c72b8c9a1e01-507f1f77bcf86cd799439011-ANALYTICS",
      "name": "transform-events",
      "state": "error",
      "frequency": "0 7 * * *"
    },
    {
      "laui": "60d5ec49f1b2c72b8c9a1e0b",
      "item_type": "task",
      "pk": "ingest-raw-events-60d5ec49f1b2c72b8c9a1e01-507f1f77bcf86cd799439011-ANALYTICS",
      "name": "ingest-raw-events",
      "state": "scheduled",
      "frequency": "0 6 * * *"
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 20,
    "has_next": false,
    "next_page_token": null
  }
}

8b. Search items by name

{
  "item_filter": {
    "name": "ingest-raw-events"
  }
}

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e0b",
      "item_type": "task",
      "pk": "ingest-raw-events-60d5ec49f1b2c72b8c9a1e01-507f1f77bcf86cd799439011-ANALYTICS"
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 10,
    "has_next": false,
    "next_page_token": null
  }
}

8c. Search items by parent_laui

{
  "item_filter": {
    "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
    "item_type": "task"
  },
  "pagination": {
    "per_page": 50
  }
}

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e0b",
      "item_type": "task",
      "pk": "ingest-raw-events-60d5ec49f1b2c72b8c9a1e01-507f1f77bcf86cd799439011-ANALYTICS"
    },
    {
      "laui": "60d5ec49f1b2c72b8c9a1e15",
      "item_type": "task",
      "pk": "transform-events-60d5ec49f1b2c72b8c9a1e01-507f1f77bcf86cd799439011-ANALYTICS"
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 50,
    "has_next": false,
    "next_page_token": null
  }
}

8d. Batch search by item_lauis

{
  "item_filter": {
    "item_lauis": [
      "60d5ec49f1b2c72b8c9a1e0b",
      "60d5ec49f1b2c72b8c9a1e15",
      "60d5ec49f1b2c72b8c9a1e04"
    ]
  }
}

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e0b",
      "item_type": "task",
      "pk": "ingest-raw-events-60d5ec49f1b2c72b8c9a1e01-507f1f77bcf86cd799439011-ANALYTICS"
    },
    {
      "laui": "60d5ec49f1b2c72b8c9a1e15",
      "item_type": "task",
      "pk": "transform-events-60d5ec49f1b2c72b8c9a1e01-507f1f77bcf86cd799439011-ANALYTICS"
    },
    {
      "laui": "60d5ec49f1b2c72b8c9a1e04",
      "item_type": "operator",
      "pk": "s3-download.operator-60d5ec49f1b2c72b8c9a1e03"
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 10,
    "has_next": false,
    "next_page_token": null
  }
}

8e. Search by primary key (get_by_pk)

When get_by_pk is true, the item_type is required plus all fields listed in that type's unique_constraints. For a task, the primary keys are name, project_laui, account_laui, and partition.

{
  "item_filter": {
    "get_by_pk": true,
    "item_type": "task",
    "name": "ingest-raw-events",
    "project_laui": "60d5ec49f1b2c72b8c9a1e01",
    "account_laui": "507f1f77bcf86cd799439011",
    "partition": "ANALYTICS"
  }
}

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e0b",
      "item_type": "task",
      "pk": "507f1f77bcf86cd799439011-ANALYTICS-ingest-raw-events-60d5ec49f1b2c72b8c9a1e01"
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 10,
    "has_next": false,
    "next_page_token": null
  }
}

8f. Search by extra fields with projection

Using extra="allow" on SearchItemsFilter, you can pass any field present on the items in the database as a filter. The projection controls which fields are returned.

{
  "item_filter": {
    "item_type": "task",
    "state": "error",
    "project_laui": "60d5ec49f1b2c72b8c9a1e01"
  },
  "projection": {
    "include": ["name", "state", "logical_date", "last_run_date", "retry_number", "total_retries"]
  },
  "pagination": {
    "per_page": 100,
    "sort_order": "desc"
  }
}

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e15",
      "item_type": "task",
      "pk": "transform-events-60d5ec49f1b2c72b8c9a1e01-507f1f77bcf86cd799439011-ANALYTICS",
      "name": "transform-events",
      "state": "error",
      "logical_date": "2026-03-19T07:00:00Z",
      "last_run_date": "2026-03-19T07:01:23Z",
      "retry_number": 1,
      "total_retries": 2
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 100,
    "has_next": false,
    "next_page_token": null
  }
}

8g. Search items with exclusion projection

{
  "item_filter": {
    "item_type": "operator",
    "parent_laui": "60d5ec49f1b2c72b8c9a1e03"
  },
  "projection": {
    "exclude": ["codeblock", "bashblock", "connection", "payload"]
  }
}

Response 200 OK

{
  "items": [
    {
      "laui": "60d5ec49f1b2c72b8c9a1e04",
      "item_type": "operator",
      "pk": "s3-download.operator-60d5ec49f1b2c72b8c9a1e03",
      "name": "s3-download.operator",
      "description": "Downloads files from S3 buckets"
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 10,
    "has_next": false,
    "next_page_token": null
  }
}
{
  "link_filter": {
    "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
    "true_parent": true
  }
}

Response 200 OK

{
  "links": [
    {
      "laui": "60d5ec49f1b2c72b8c9a2a01",
      "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
      "child_laui": "60d5ec49f1b2c72b8c9a1e0b",
      "parent_type": "folder.workflow",
      "child_type": "task",
      "true_parent": true
    },
    {
      "laui": "60d5ec49f1b2c72b8c9a2a02",
      "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
      "child_laui": "60d5ec49f1b2c72b8c9a1e15",
      "parent_type": "folder.workflow",
      "child_type": "task",
      "true_parent": true
    },
    {
      "laui": "60d5ec49f1b2c72b8c9a2a03",
      "parent_laui": "60d5ec49f1b2c72b8c9a1e02",
      "child_laui": "60d5ec49f1b2c72b8c9a1e0a",
      "parent_type": "folder.workflow",
      "child_type": "config",
      "true_parent": true
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 10,
    "has_next": false,
    "next_page_token": null
  }
}
{
  "link_filter": {
    "child_type": "task",
    "parent_type": "connection"
  },
  "pagination": {
    "per_page": 5
  }
}

Response 200 OK

{
  "links": [
    {
      "laui": "60d5ec49f1b2c72b8c9a2a10",
      "parent_laui": "60d5ec49f1b2c72b8c9a1e07",
      "child_laui": "60d5ec49f1b2c72b8c9a1e0b",
      "parent_type": "connection",
      "child_type": "task",
      "true_parent": false
    },
    {
      "laui": "60d5ec49f1b2c72b8c9a2a11",
      "parent_laui": "60d5ec49f1b2c72b8c9a1e07",
      "child_laui": "60d5ec49f1b2c72b8c9a1e15",
      "parent_type": "connection",
      "child_type": "task",
      "true_parent": false
    }
  ],
  "pagination": {
    "current_page": 1,
    "per_page": 5,
    "has_next": false,
    "next_page_token": null
  }
}

Error Responses

422 Unprocessable Entity -- Both filters provided

{
  "detail": "Only one of item_filter or link_filter can be passed not both"
}

422 Unprocessable Entity -- Neither filter provided

{
  "detail": "Atleast one of item_filter or link_filter must be passed"
}

422 Unprocessable Entity -- get_by_pk without item_type

{
  "detail": "if get_by_pk is true then item_type must be passed"
}

422 Unprocessable Entity -- get_by_pk with missing primary keys

{
  "detail": "following primary keys:['account_laui', 'partition'] are missing for the item_type:task"
}

500 Internal Server Error

{
  "detail": "Internal server error: <message>"
}

9. Get Supported Types

Returns the allowed child and parent item types for a given item type.

GET /api/v1/catalog/item-types/supported-types

Description

Looks up the catalog hierarchy configuration and returns which item types can be children of the given type and which types can be its parents. Useful for validation before creating links or items.

Access Control

No explicit access check.

Query Parameters

ParameterTypeRequiredDescription
item_typestringYesThe item type to look up (e.g., task, folder.workflow).

Example

GET /api/v1/catalog/item-types/supported-types?item_type=folder.workflow

Success Response

200 OK

{
  "supported_children_types": ["folder.workflow", "task", "config", "connection", "payload", "operator", "action"],
  "supported_parent_types": ["folder.project", "folder.workflow"]
}

Error Responses

422 Unprocessable Entity — Unknown item type

{
  "detail": "Unknown item_type: folder.workflow"
}

500 Internal Server Error

{
  "detail": "Internal server error"
}

10. Bootstrap Project

Initializes the standard folder structure for a newly created project.

POST /api/v1/catalog/bootstrap

Description

Creates the default set of sub-folders under a project (folder.workflow, folder.operator, folder.action, folder.payload, folder.connection, folder.config, folder.asset, folder.ai, folder.bootstrap). Idempotent — folders that already exist are skipped.

Access Control

No explicit access check at the route level. The caller must have sufficient access on the project to create child items.

Query Parameters

ParameterTypeRequiredDescription
project_lauistringYesThe LAUI of the project to bootstrap.

Example

POST /api/v1/catalog/bootstrap?project_laui=60d5ec49f1b2c72b8c9a1e01

Success Response

200 OK

{
  "project_laui": "60d5ec49f1b2c72b8c9a1e01",
  "folders": [
    "60d5ec49f1b2c72b8c9a1e20",
    "60d5ec49f1b2c72b8c9a1e21",
    "60d5ec49f1b2c72b8c9a1e22"
  ]
}

The folders array contains the LAUIs of the created (or pre-existing) folder items.

Error Responses

400 Bad Request — Invalid project LAUI

{
  "detail": "Invalid argument: <description>"
}

500 Internal Server Error

{
  "detail": "Internal server error: <message>"
}

11. Validate Codeblock

Statically validates a codeblock for syntax and structural correctness.

POST /api/v1/catalog/validate

Description

Runs static analysis on the provided codeblock without executing it. For operator types, checks that the four required methods (run, initialize, check_completion, finish) are present. Returns errors and warnings.

Access Control

No explicit access check.

Request Body

FieldTypeRequiredDescription
codeblockobjectYesMap of language to code string, e.g. {"python": "def run(context): ..."}.
item_typestringYesThe item type the codeblock belongs to (operator, action, chat, agent).

Example

POST /api/v1/catalog/validate

{
  "codeblock": {
    "python": "import boto3\n\ndef initialize(context):\n    pass\n\ndef run(context):\n    return {}\n\ndef check_completion(context):\n    return True\n\ndef finish(context):\n    pass"
  },
  "item_type": "operator"
}

Success Response

200 OK

{
  "valid": true,
  "errors": [],
  "warnings": []
}

With errors

{
  "valid": false,
  "errors": [
    {
      "code": "missing_method",
      "message": "Required method 'initialize' is not defined",
      "file": null,
      "line": null
    }
  ],
  "warnings": []
}

ValidationResult fields

FieldTypeDescription
validbooltrue if no errors were found.
errorsarrayList of CodeblockValidationEntry objects.
warningsarrayList of CodeblockValidationEntry objects (non-fatal).

CodeblockValidationEntry fields

FieldTypeDescription
codestringError/warning code identifier.
messagestringHuman-readable description.
filestring | nullSource file where the issue was found, if applicable.
lineinteger | nullLine number, if applicable.

Error Responses

500 Internal Server Error

{
  "detail": "Internal server error: <message>"
}

Appendix: Item Type Schemas

Quick reference for the unique constraints (primary key fields) of each item type. The pk value stored in the database is the sorted PK field values joined by -.

Item TypeUnique Constraints
folderparent_laui, name
operatorparent_laui, name
actionproject_laui, name, account_laui
connectionparent_laui, name
payloadparent_laui, name
configparent_laui, name
taskname, project_laui, account_laui, partition
tablesource_system, name
html_reportparent_laui, name
chatparent_laui, name
skillparent_laui, name
chat_historyparent_laui, name

Appendix: Permission Enum Values

Used with the item_permission query parameter on GET /catalog/get.

ValueDescription
viewRead access to the item.
editWrite access to the item.
ownFull ownership of the item.
deletePermission to delete the item.
true_parent_editEdit access inherited from the true parent.
is_true_parentIndicates the user is the true parent of the item.