{ "openapi": "3.1.0", "info": { "title": "Jentic Mini", "description": "**Jentic Mini** is the open-source, self-hosted implementation of the Jentic API \u2014 fully API-compatible with the [Jentic hosted and VPC editions](https://jentic.com).\n\n## What is Jentic Mini?\nJentic Mini gives any agent a local execution layer: search a catalog of registered APIs, broker authenticated requests without exposing credentials to the agent, enforce access policies, and observe every execution. It is designed to be dropped in as a self-hosted alternative to the Jentic cloud service.\n\n## Hosted vs Self-hosted\nThe **Jentic hosted and VPC editions** offer deeper implementations across three areas:\n\n| Capability | Jentic Mini (this) | Jentic hosted / VPC |\n|------------|-------------------|---------------------|\n| **Search** | BM25 full-text search | Advanced semantic search (~64% accuracy improvement over BM25) |\n| **Request brokering** | In-process credential injection | Scalable AWS Lambda-based broker with encryption at rest and in-transit, SOC 2-grade security, and 3rd-party credential vault integrations (HashiCorp Vault, AWS Secrets Manager, etc.) |\n| **Simulation** | Basic simulate mode | Full sandbox for simulating API calls and toolkit behaviour (enterprise-only) |\n| **Catalog** | Local registry only | Central catalog \u2014 aggregates the collective know-how of agents across API definitions and Arazzo workflows |\n\n## Authentication\n**Agents (OAuth identity)** \u2014 `Authorization: Bearer` with `at_\u2026` access tokens (from `POST /oauth/token`) or `rat_\u2026` registration tokens (received from `POST /register`, only usable for polling registration status). New agents should use the registration flow; see `GET /.well-known/oauth-authorization-server` for OAuth metadata.\n**Agents (toolkit key)** \u2014 `X-Jentic-API-Key: tk_xxx`. Legacy path; still supported but new agents should use OAuth registration via `POST /register`.\n**Humans** \u2014 [log in here](/login) for a session cookie (required for admin operations).\n\n## Tag groups\n| Tag | Who uses it | Purpose |\n|-----|-------------|----------|\n| **search** | Agents | Full-text search \u2014 the main entrypoint |\n| **inspect** | Agents | Inspect capabilities, list APIs and operations |\n| **execute** | Agents | Transparent request broker \u2014 runs API operations and Arazzo workflows. Credential injection, policy enforcement, and simulate mode built-in. |\n| **toolkits** | Agents/Humans | Toolkits, access keys, permissions, access requests |\n| **observe** | Agents | Read execution traces |\n| **catalog** | Humans/admin | Register APIs, upload specs, overlays, notes |\n| **credentials** | Humans only | Manage the credentials vault |\n\nAgents with a toolkit key need: **search**, **inspect**, **execute**, **toolkits** (read), **observe**.", "version": "0.13.2", "contact": { "name": "Jentic Mini Support", "url": "https://github.com/jentic/jentic-mini", "email": "hello@jentic.com" }, "license": { "name": "Apache 2.0", "identifier": "Apache-2.0" } }, "paths": { "/.well-known/oauth-authorization-server": { "get": { "tags": ["oauth"], "summary": "OAuth 2.0 Authorization Server Metadata (RFC 8414)", "operationId": "oauth_authorization_server_metadata__well_known_oauth_authorization_server_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } }, "security": [] } }, "/agents": { "get": { "tags": ["agents"], "summary": "List Agents", "operationId": "list_agents_agents_get", "parameters": [ { "name": "view", "in": "query", "required": false, "schema": { "enum": ["active", "declined", "removed"], "type": "string", "description": "active: not denied and not deregistered; declined: denied only; removed: soft-deleted (deregistered)", "default": "active", "title": "View" }, "description": "active: not denied and not deregistered; declined: denied only; removed: soft-deleted (deregistered)" }, { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "When view=active only: pending, approved, disabled", "title": "Status" }, "description": "When view=active only: pending, approved, disabled" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/agents/{agent_id}": { "get": { "tags": ["agents"], "summary": "Get Agent", "operationId": "get_agent_agents__agent_id__get", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "404": { "description": "Agent or toolkit not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "delete": { "tags": ["agents"], "summary": "Deregister agent (soft delete)", "description": "Soft-delete for audit: revoke tokens, strip JWKS and registration secrets, drop grants.", "operationId": "delete_agent_agents__agent_id__delete", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "204": { "description": "Successful Response" }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "404": { "description": "Agent or toolkit not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/agents/{agent_id}/approve": { "post": { "tags": ["agents"], "summary": "Approve Agent", "operationId": "approve_agent_agents__agent_id__approve_post", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Agent is not in 'pending' status.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "404": { "description": "Agent or toolkit not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/agents/{agent_id}/deny": { "post": { "tags": ["agents"], "summary": "Decline registration", "operationId": "deny_agent_agents__agent_id__deny_post", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Agent is not in 'pending' status.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "404": { "description": "Agent or toolkit not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/agents/{agent_id}/disable": { "post": { "tags": ["agents"], "summary": "Disable Agent", "operationId": "disable_agent_agents__agent_id__disable_post", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "404": { "description": "Agent or toolkit not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/agents/{agent_id}/enable": { "post": { "tags": ["agents"], "summary": "Enable Agent", "operationId": "enable_agent_agents__agent_id__enable_post", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Agent is not currently disabled.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "404": { "description": "Agent or toolkit not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/agents/{agent_id}/grants": { "post": { "tags": ["agents"], "summary": "Add Grant", "operationId": "add_grant_agents__agent_id__grants_post", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GrantBody" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "404": { "description": "Agent or toolkit not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "409": { "description": "Conflicting state (e.g. disabled toolkit).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "get": { "tags": ["agents"], "summary": "List Grants", "operationId": "list_grants_agents__agent_id__grants_get", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "put": { "tags": ["agents"], "summary": "Replace the agent's grants atomically", "description": "Replace the agent's full grant set in a single transaction.\n\nUsed by the admin UI's grant-edit flow: the user picks a set of toolkits\nin a dialog and submits the whole set in one call, instead of dispatching\na stream of POST/DELETE requests sequentially. A 5xx mid-operation under\nthe old flow would leave the agent in a partial state \u2014 this endpoint\neliminates that window.\n\nBehaviour:\n\n* Adds toolkits in ``toolkit_ids`` that the agent doesn't already hold.\n Disabled toolkits and unknown toolkit_ids reject the **whole** call.\n* Removes existing grants not in ``toolkit_ids``.\n* Preserves ``granted_at`` / ``granted_by`` for grants that survive\n (the conflict path is a no-op, exactly like POST).", "operationId": "replace_grants_agents__agent_id__grants_put", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GrantsReplaceBody" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "404": { "description": "Agent or toolkit not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "409": { "description": "Conflicting state (e.g. disabled toolkit).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/agents/{agent_id}/jwks": { "put": { "tags": ["agents"], "summary": "Rotate Agent Jwks", "operationId": "rotate_agent_jwks_agents__agent_id__jwks_put", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Body" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Invalid or missing jwks.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "404": { "description": "Agent or toolkit not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/agents/{agent_id}/grants/{toolkit_id}": { "delete": { "tags": ["agents"], "summary": "Delete Grant", "operationId": "delete_grant_agents__agent_id__grants__toolkit_id__delete", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } }, { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit id to revoke", "title": "Toolkit Id" }, "description": "Toolkit id to revoke" } ], "responses": { "204": { "description": "Successful Response" }, "403": { "description": "Human session required.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "404": { "description": "Agent or toolkit not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/apis": { "get": { "tags": ["catalog"], "summary": "List APIs \u2014 browse all available API providers (local and catalog)", "description": "Returns paginated list of API providers \u2014 both locally registered and from the Jentic public catalog.\n\nEvery entry has:\n- `source: \"local\"` \u2014 spec is indexed locally, operations are searchable and executable\n- `source: \"catalog\"` \u2014 available from the Jentic public catalog; add credentials to use\n- `has_credentials: bool` \u2014 whether credentials have been configured for this API\n- `has_workflows: bool` \u2014 only on catalog rows; `true` when the public catalog\n also ships Arazzo workflows for this vendor (renders as a `+ workflows` chip\n in the UI). Always `false` / omitted on local rows since those workflows are\n already imported and listed under `GET /workflows`.\n\nUse `?source=local` or `?source=catalog` to filter. Default returns all.\nTo use a catalog API: call `POST /credentials` with `api_id` set \u2014 the spec is imported automatically.", "operationId": "list_apis_apis_get", "parameters": [ { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "description": "Page number (1-indexed)", "default": 1, "title": "Page" }, "description": "Page number (1-indexed)" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "description": "Results per page", "default": 20, "title": "Limit" }, "description": "Results per page" }, { "name": "source", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by source: `local` (locally registered) or `catalog` (public catalog, not yet configured). Default: all.", "title": "Source" }, "description": "Filter by source: `local` (locally registered) or `catalog` (public catalog, not yet configured). Default: all." }, { "name": "q", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Substring filter on API id/name", "title": "Q" }, "description": "Substring filter on API id/name" }, { "name": "include_imported", "in": "query", "required": false, "schema": { "type": "boolean", "description": "When `source=catalog`, controls whether catalog entries that have already been imported into the local workspace are still returned. Default `false` preserves the historical 'things you don't have yet' behaviour used by the workspace 'From the catalog' section. The `/discover` UI sets this to `true` so users keep seeing the full Jentic public catalog after importing \u2014 registered entries surface with `source: local` and a `Ready` / `Credential expired` pill instead of vanishing. No-op when `source != catalog`.", "default": false, "title": "Include Imported" }, "description": "When `source=catalog`, controls whether catalog entries that have already been imported into the local workspace are still returned. Default `false` preserves the historical 'things you don't have yet' behaviour used by the workspace 'From the catalog' section. The `/discover` UI sets this to `true` so users keep seeing the full Jentic public catalog after importing \u2014 registered entries surface with `source: local` and a `Ready` / `Credential expired` pill instead of vanishing. No-op when `source != catalog`." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiListPage" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use when you need to discover available API providers by vendor name, browse registered APIs, or check which APIs have credentials configured. Returns both locally registered APIs (source: local) and available catalog APIs (source: catalog). Use ?q= to filter by API ID or name, ?source= to filter by source type, and ?page=/limit= for pagination.", "prerequisites": ["Requires authentication (toolkit key or human session)"], "avoid_when": "Do not use if you already know the API ID \u2014 use GET /apis/{api_id} directly instead. Do not use for natural language capability discovery \u2014 use GET /search for that.", "related_operations": [ "GET /apis/{api_id} \u2014 get detailed API metadata including security schemes and credential status", "GET /apis/{api_id}/operations \u2014 list all operations for a specific API", "GET /search \u2014 search for capabilities across all APIs by natural language intent", "POST /credentials \u2014 add credentials for an API (imports from catalog if not yet registered)" ] }, "security": [] } }, "/apis/{api_id}": { "get": { "tags": ["catalog"], "summary": "Get API details \u2014 metadata, auth schemes, servers, and optional spec sections", "description": "Returns API metadata enriched with selected OpenAPI spec sections.\n\n**Default response** (no `?sections=`) includes:\n- Summary fields: id, name, vendor, description, base_url, operation_count, overlay_count\n- `info` \u2014 title, version, contact, license, terms of service\n- `servers` \u2014 base URLs and variables (merged from spec + confirmed overlays)\n- `security_schemes` \u2014 security scheme definitions (merged from spec + confirmed overlays),\n plus `security_required` (global security requirements)\n- `credentials_configured` \u2014 list of auth_types that already have a credential bound.\n Use this to build a credential-setup UI: iterate `security_schemes`, check each key\n against `security_schemes` (each scheme has a `type` field) to determine which auth types need credentials.\n to fill in the required fields and POST to `/credentials`.\n\n**Credential setup flow:**\n1. Call `GET /apis/{api_id}` \u2014 inspect `security_schemes` and `credentials_configured`\n2. For each unconfigured scheme, determine required fields from the scheme type:\n - `http bearer` \u2192 `secret` (token)\n - `http basic` \u2192 `secret` (password) + optional `identity` (username)\n - `apiKey` \u2192 `secret` (key value); if compound, check scheme names for Secret/Identity\n3. Prompt user for values, then `POST /credentials` with `api_id`, `auth_type`, `value` (and `identity` if needed).\n4. Verify with `GET /credentials?api_id={api_id}`\n\n**Optional sections** (add via `?sections=`):\n- `tags` \u2014 tag objects with names and descriptions\n- `paths` \u2014 full paths object (can be very large \u2014 prefer GET /apis/{api_id}/operations)\n- `components` \u2014 all reusable component definitions (schemas, parameters, responses, etc.)\n- `webhooks` \u2014 OpenAPI 3.1 webhooks (if present)\n\n**Full spec download:** `GET /apis/{api_id}/openapi.json`", "operationId": "get_api_apis__api_id__get", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "API ID (hostname or hostname/path format)", "title": "Api Id" }, "description": "API ID (hostname or hostname/path format)" }, { "name": "sections", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Comma-separated list of OpenAPI spec sections to include in the response. Valid values: components, info, paths, security, servers, tags, webhooks. Default (when omitted): info, security, servers. Large sections (paths, components, webhooks) must be requested explicitly. Use GET /apis/{api_id}/openapi.json to download the full merged spec.", "title": "Sections" }, "description": "Comma-separated list of OpenAPI spec sections to include in the response. Valid values: components, info, paths, security, servers, tags, webhooks. Default (when omitted): info, security, servers. Large sections (paths, components, webhooks) must be requested explicitly. Use GET /apis/{api_id}/openapi.json to download the full merged spec." } ], "responses": { "200": { "description": "API detail \u2014 format controlled by Accept header.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApiOut", "type": "object" } }, "application/yaml": { "schema": { "type": "string", "description": "API detail as YAML" } }, "text/markdown": { "schema": { "type": "string", "description": "LLM-friendly API summary" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use after finding an API via GET /apis or GET /search to inspect its authentication requirements, security schemes, and available credential setup options. Critical for understanding which auth types need credentials before calling operations. Returns API metadata enriched with OpenAPI spec sections (info, servers, security_schemes). Use ?sections= to request additional spec sections (tags, paths, components).", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid API ID from GET /apis or catalog (format: hostname or hostname/path)" ], "avoid_when": "Do not use to download the full OpenAPI spec \u2014 use GET /apis/{api_id}/openapi.json for that. Do not use to list operations \u2014 use GET /apis/{api_id}/operations instead.", "related_operations": [ "GET /apis \u2014 list available APIs to find the api_id", "GET /apis/{api_id}/openapi.json \u2014 download full merged OpenAPI spec with overlays applied", "GET /apis/{api_id}/operations \u2014 list all operations for this API", "POST /credentials \u2014 add credentials after inspecting security_schemes", "GET /credentials?api_id={api_id} \u2014 check which credentials are configured" ] }, "security": [] }, "delete": { "tags": ["catalog"], "summary": "Remove an API from the workspace", "description": "Remove an API and its single-API workflows from the workspace.\n\nBy default credentials are preserved (api_id reference kept intact) so they\nautomatically re-link if the API is re-imported later. Toolkit bindings also\nsurvive. Pass `cascade=true` to also delete all credentials and their\ntoolkit bindings for a clean slate.", "operationId": "delete_api_apis__api_id__delete", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "API id to delete, e.g. api.elevenlabs.io", "title": "Api Id" }, "description": "API id to delete, e.g. api.elevenlabs.io" }, { "name": "cascade", "in": "query", "required": false, "schema": { "type": "boolean", "description": "If true, also delete credentials bound to this API", "default": false, "title": "Cascade" }, "description": "If true, also delete credentials bound to this API" } ], "responses": { "204": { "description": "Successful Response" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/apis/{api_id}/openapi.json": { "get": { "tags": ["catalog"], "summary": "Download merged OpenAPI spec as JSON \u2014 base spec with all confirmed overlays applied", "description": "Returns the full merged OpenAPI spec for this API as a JSON download.\n\nAll confirmed overlays are applied on top of the base spec using deep merge\n(overlay values win on conflict). Pending overlays are not included.\n\nOverlay actions with `target: \"$\"` are applied as root-level deep merges.\nActions targeting specific paths or operations are listed in\n`x-jentic-unapplied-overlays` for transparency.\n\nFor selective access to spec sections without downloading the full file,\nuse `GET /apis/{api_id}?sections=info,servers,security,tags`.", "operationId": "get_api_openapi_json_apis__api_id__openapi_json_get", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "API ID (hostname or hostname/path format)", "title": "Api Id" }, "description": "API ID (hostname or hostname/path format)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use when you need the full OpenAPI specification file for an API with all confirmed overlays applied (security scheme corrections, server URL fixes). Returns complete spec as JSON download with Content-Disposition attachment header. Overlay actions with target: $ are deep-merged; other actions listed in x-jentic-unapplied-overlays. Useful for SDK generation, schema analysis, or importing into external tools.", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid API ID from GET /apis (format: hostname or hostname/path)" ], "avoid_when": "Do not use for lightweight API inspection \u2014 use GET /apis/{api_id}?sections=info,servers,security instead. Do not use to browse operations \u2014 use GET /apis/{api_id}/operations for paginated operation list.", "related_operations": [ "GET /apis/{api_id} \u2014 get API metadata with selective spec sections (no download, lighter weight)", "GET /apis/{api_id}/openapi.yaml \u2014 download the same spec in YAML format", "GET /apis/{api_id}/operations \u2014 list operations without downloading full spec", "GET /apis/{api_id}/overlays \u2014 view overlays that are merged into this spec", "POST /apis/{api_id}/overlays \u2014 submit a new overlay to correct security schemes or servers" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/apis/{api_id}/openapi.yaml": { "get": { "tags": ["catalog"], "summary": "Download merged OpenAPI spec as YAML \u2014 base spec with all confirmed overlays applied", "description": "Returns the full merged OpenAPI spec for this API as a YAML download.\n\nAll confirmed overlays are applied on top of the base spec using deep merge\n(overlay values win on conflict). Pending overlays are not included.\n\nOverlay actions with `target: \"$\"` are applied as root-level deep merges.\nActions targeting specific paths or operations are listed in\n`x-jentic-unapplied-overlays` for transparency.\n\nFor selective access to spec sections without downloading the full file,\nuse `GET /apis/{api_id}?sections=info,servers,security,tags`.", "operationId": "get_api_openapi_yaml_apis__api_id__openapi_yaml_get", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "API ID (hostname or hostname/path format)", "title": "Api Id" }, "description": "API ID (hostname or hostname/path format)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use when you need the full OpenAPI specification file for an API in YAML format with all confirmed overlays applied. Same content as GET /apis/{api_id}/openapi.json but in YAML. Useful for human readability, configuration files, or tools that prefer YAML format.", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid API ID from GET /apis (format: hostname or hostname/path)" ], "avoid_when": "Do not use for lightweight API inspection \u2014 use GET /apis/{api_id}?sections=info,servers,security instead. Do not use to browse operations \u2014 use GET /apis/{api_id}/operations for paginated operation list.", "related_operations": [ "GET /apis/{api_id} \u2014 get API metadata with selective spec sections (no download, lighter weight)", "GET /apis/{api_id}/openapi.json \u2014 download the same spec in JSON format", "GET /apis/{api_id}/operations \u2014 list operations without downloading full spec", "GET /apis/{api_id}/overlays \u2014 view overlays that are merged into this spec", "POST /apis/{api_id}/overlays \u2014 submit a new overlay to correct security schemes or servers" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/apis/{api_id}/operations": { "get": { "tags": ["catalog"], "summary": "List operations for an API \u2014 enumerate all available actions", "description": "Returns paginated list of operations for the given API. Each item has capability id, summary, description and OpenAPI tags. Use GET /inspect/{id} for full schema.", "operationId": "list_api_operations_apis__api_id__operations_get", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "API ID to list operations for", "title": "Api Id" }, "description": "API ID to list operations for" }, { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "description": "Page number (1-indexed)", "default": 1, "title": "Page" }, "description": "Page number (1-indexed)" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "description": "Results per page", "default": 50, "title": "Limit" }, "description": "Results per page" }, { "name": "offset", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "minimum": 0 }, { "type": "null" } ], "description": "Skip N operations (0-indexed). When provided, takes precedence over `page` for cursor-style pagination \u2014 pass `offset=N&limit=M` to grab an arbitrary window from the Detail Sheet's load-more affordance.", "title": "Offset" }, "description": "Skip N operations (0-indexed). When provided, takes precedence over `page` for cursor-style pagination \u2014 pass `offset=N&limit=M` to grab an arbitrary window from the Detail Sheet's load-more affordance." }, { "name": "tag", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Case-insensitive substring filter on the operation's OpenAPI `tags[]`. Tags are projected from the spec at request time. `total` reflects the post-filter count so the page envelope stays consistent.", "title": "Tag" }, "description": "Case-insensitive substring filter on the operation's OpenAPI `tags[]`. Tags are projected from the spec at request time. `total` reflects the post-filter count so the page envelope stays consistent." } ], "responses": { "200": { "description": "Operation list \u2014 format controlled by Accept header.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OperationListPage", "type": "object" } }, "application/yaml": { "schema": { "type": "string", "description": "Operation list as YAML" } }, "text/markdown": { "schema": { "type": "string", "description": "Operation list as Markdown table" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use after finding an API via GET /apis to enumerate all available operations (endpoints) for that API. Returns paginated list of capability IDs, summaries, and descriptions. Each operation can then be inspected via GET /inspect/{id} for full parameter schemas and auth requirements before execution. Useful for discovering what actions an API supports.", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid API ID from GET /apis (format: hostname or hostname/path)" ], "avoid_when": "Do not use for natural language capability discovery across all APIs \u2014 use GET /search instead. Do not use to inspect a specific operation's parameters \u2014 use GET /inspect/{id} after finding the capability ID.", "related_operations": [ "GET /apis \u2014 list available APIs to find the api_id", "GET /inspect/{id} \u2014 inspect operation details (parameters, request/response schemas, auth)", "GET /search \u2014 search for specific capabilities by natural language intent instead of browsing", "GET /{target} (broker) \u2014 execute an operation after finding its capability ID" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/apis/{api_id}/overlays": { "post": { "tags": ["catalog"], "summary": "Submit an OpenAPI overlay \u2014 patch the stored spec for this API", "description": "Submit an OpenAPI Overlay 1.0 document to patch the stored spec for this API.\n\nOverlays are additive and ordered \u2014 later overlays override matching keys from\nearlier ones via merge. A new overlay starts as **pending** and is\nauto-confirmed the first time a broker call for this API succeeds.\n\nSee the `overlay` field schema for structure, common targets, and security\nscheme examples including compound apiKey schemes (Discourse-style).", "operationId": "submit_overlay_apis__api_id__overlays_post", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "API ID to submit overlay for", "title": "Api Id" }, "description": "API ID to submit overlay for" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OverlaySubmit" } } }, "description": "OpenAPI Overlay 1.0 document to patch the stored spec \u2014 adds security schemes, corrects base URLs, or enriches operation metadata" }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use when an API's stored OpenAPI spec is missing security schemes, has incorrect base URLs, or lacks required metadata. Submit an OpenAPI Overlay 1.0 document to patch the spec without modifying the original file. Common use: adding BearerAuth or apiKey schemes when the spec declares no security. Overlay starts as pending and auto-confirms on first successful broker call.", "prerequisites": [ "Requires authentication (admin/human session)", "Valid API ID from GET /apis", "Valid OpenAPI Overlay 1.0 structure (overlay, info, actions array)" ], "avoid_when": "Do not use for testing security schemes before adding credentials \u2014 first add credentials via POST /credentials, then submit overlay if authentication fails with 401/403. Do not submit duplicate overlays \u2014 check GET /apis/{api_id}/overlays first.", "related_operations": [ "GET /apis/{api_id}/overlays \u2014 list existing overlays to avoid duplicates", "GET /apis/{api_id} \u2014 inspect current security_schemes before patching", "POST /credentials \u2014 add credentials after overlay is confirmed", "GET /apis/{api_id}/openapi.json \u2014 download merged spec to verify overlay was applied" ] }, "security": [ { "HumanLogin": [] } ] }, "get": { "tags": ["catalog"], "summary": "List overlays for an API \u2014 returns full overlay documents", "description": "Return all overlays for an API, each with its full overlay document included.\n\nConfirmed overlays are listed first, then pending, both ordered by creation date\ndescending. Each overlay includes the complete OpenAPI Overlay 1.0 document so\nclients don't need a second call to inspect the overlay content.", "operationId": "list_overlays_apis__api_id__overlays_get", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "API ID to list overlays for", "title": "Api Id" }, "description": "API ID to list overlays for" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use to inspect existing overlays for an API before submitting a new one (avoids duplicates) or to verify which overlays are confirmed vs pending. Each overlay includes the complete OpenAPI Overlay 1.0 document with all actions, so no second call needed. Confirmed overlays are listed first, then pending, ordered by creation date descending.", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid API ID from GET /apis" ], "avoid_when": "Do not use to download the merged spec \u2014 use GET /apis/{api_id}/openapi.json for that (overlays already applied). Do not use to inspect base security schemes \u2014 use GET /apis/{api_id} instead.", "related_operations": [ "POST /apis/{api_id}/overlays \u2014 submit a new overlay after checking for duplicates", "DELETE /apis/{api_id}/overlays/{overlay_id} \u2014 delete an overlay", "GET /apis/{api_id}/openapi.json \u2014 download merged spec with all confirmed overlays applied", "GET /apis/{api_id} \u2014 view current security_schemes (includes merged overlays)" ] }, "security": [] } }, "/apis/{api_id}/overlays/{overlay_id}": { "delete": { "tags": ["catalog"], "summary": "Delete an overlay", "description": "Delete an overlay by ID.\n\nPermanently removes the overlay from the database. Works on both pending and confirmed\noverlays. If the overlay was confirmed and actively patching the spec, the next\nbroker call will use the spec without this overlay's changes.\n\nParameters:\n api_id: API ID that owns this overlay\n overlay_id: Overlay ID to delete (format: overlay_xxxxxxxx)\n\nReturns:\n Confirmation with deleted overlay_id and api_id.\n\nUse when an overlay was submitted incorrectly or is no longer needed. To replace\nan incorrect overlay, delete it first, then submit a corrected version.", "operationId": "delete_overlay_apis__api_id__overlays__overlay_id__delete", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "API ID", "title": "Api Id" }, "description": "API ID" }, { "name": "overlay_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Overlay ID to delete", "title": "Overlay Id" }, "description": "Overlay ID to delete" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use to remove an incorrect or obsolete overlay from an API. Works on both pending and confirmed overlays. After deletion, the merged spec (GET /apis/{api_id}/openapi.json) will no longer include the deleted overlay's patches.", "prerequisites": [ "Requires authentication (admin/human session)", "Valid API ID and overlay ID from GET /apis/{api_id}/overlays" ], "avoid_when": "Do not use to temporarily disable an overlay \u2014 deletion is permanent. Do not delete overlays that other toolkits may depend on without coordination.", "related_operations": [ "GET /apis/{api_id}/overlays \u2014 list overlays to find the overlay_id", "POST /apis/{api_id}/overlays \u2014 submit a replacement overlay after deleting an incorrect one", "GET /apis/{api_id}/openapi.json \u2014 verify overlay removal by downloading merged spec" ] }, "security": [ { "HumanLogin": [] } ] } }, "/catalog": { "get": { "tags": ["catalog", "catalog"], "summary": "List the public API catalog", "description": "Returns entries from the cached public API catalog manifest.\nUse ``POST /catalog/refresh`` to sync from GitHub first if the list is empty.", "operationId": "list_catalog_catalog_get", "parameters": [ { "name": "q", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Search term to filter APIs by name or description", "title": "Q" }, "description": "Search term to filter APIs by name or description" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 500, "minimum": 1, "description": "Maximum number of results (1-500)", "default": 50, "title": "Limit" }, "description": "Maximum number of results (1-500)" }, { "name": "registered_only", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Return only APIs already registered locally", "default": false, "title": "Registered Only" }, "description": "Return only APIs already registered locally" }, { "name": "unregistered_only", "in": "query", "required": false, "schema": { "type": "boolean", "description": "Return only APIs not yet registered locally", "default": false, "title": "Unregistered Only" }, "description": "Return only APIs not yet registered locally" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use to browse available APIs from the Jentic public catalog (jentic/jentic-public-apis GitHub repo). Returns list of catalog entries with api_id and registration status. Use ?q= to filter by API ID substring, ?registered_only=true to see only locally registered APIs, ?unregistered_only=true to see only APIs not yet imported. Catalog manifest auto-refreshes daily; use POST /catalog/refresh to sync immediately.", "prerequisites": ["Requires authentication (toolkit key or human session)"], "avoid_when": "Do not use to list locally registered APIs \u2014 use GET /apis?source=local instead. Do not use for natural language API discovery \u2014 use GET /search for that.", "related_operations": [ "GET /catalog/{api_id} \u2014 get spec download URL for a catalog API", "POST /import \u2014 import a catalog API after finding it here", "POST /catalog/refresh \u2014 refresh catalog manifest from GitHub if empty or stale", "GET /apis \u2014 list locally registered APIs (includes both local and catalog sources)" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/catalog/refresh": { "post": { "tags": ["catalog", "admin"], "summary": "Refresh the API catalog manifest from GitHub", "description": "Rebuilds the internal catalog manifest from the jentic/jentic-public-apis repository.\nThe manifest is used by lazy import \u2014 when you `POST /credentials` for an API not yet in\nyour local registry, Jentic Mini resolves the spec from this manifest automatically.\n\nFetches the curated apis.json index and the workflows directory listing\n(two unauthenticated HTTP requests). Safe to call repeatedly.\nThe manifest auto-refreshes daily; only call this explicitly if you need immediate sync\nafter a new API has been added to the public catalog.", "operationId": "refresh_catalog_catalog_refresh_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } }, "x-agent-hints": { "when_to_use": "Use when the catalog is empty (GET /catalog returns empty list) or when you need immediate sync after a new API was added to jentic/jentic-public-apis on GitHub. Fetches the curated apis.json index and workflows directory listing from GitHub (two unauthenticated HTTP requests). Manifest auto-refreshes daily on startup, so only call explicitly if you need immediate sync.", "prerequisites": ["Requires authentication (admin/human session)"], "avoid_when": "Do not call repeatedly \u2014 safe but unnecessary since manifest auto-refreshes daily. Do not use to import APIs \u2014 use POST /import after refreshing.", "related_operations": [ "GET /catalog \u2014 list catalog entries after refreshing", "GET /catalog/{api_id} \u2014 get spec URL for an API after refreshing", "POST /import \u2014 import an API after finding it in the refreshed catalog" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/catalog/{api_id}": { "get": { "tags": ["catalog", "catalog"], "summary": "Get a catalog entry with spec location", "description": "Return details for a single catalog API, including the spec download URL.\n\nUse the returned `spec_url` with `POST /import` to import this API:\n\n POST /import\n {\"sources\": [{\"type\": \"url\", \"url\": \"\", \"force_api_id\": \"\"}]}", "operationId": "get_catalog_entry_catalog__api_id__get", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "API ID from catalog to retrieve", "title": "Api Id" }, "description": "API ID from catalog to retrieve" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use after finding an API via GET /catalog to retrieve the spec download URL for import. Returns api_id, registration status, spec_url (GitHub raw file URL), and spec_filename. Use the spec_url with POST /import to register this API locally. Recursively searches the GitHub directory for OpenAPI spec files (openapi.json, openapi.yaml, etc.).", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid catalog api_id from GET /catalog (format: hostname or hostname/path)" ], "avoid_when": "Do not use for APIs already registered locally \u2014 check GET /apis first. Do not use to download the spec directly (use POST /import instead).", "related_operations": [ "GET /catalog \u2014 browse catalog to find the api_id", "POST /import \u2014 import the API using the spec_url returned here", "GET /apis \u2014 check if API is already registered before importing", "POST /credentials \u2014 add credentials after importing" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/catalog/{api_id}/operations": { "get": { "tags": ["catalog", "catalog"], "summary": "Preview operations for a catalog API without importing", "description": "Server-side spec fetch + parse for the directory API preview.\n\nWhy this exists: the Detail Sheet wants to show the operation table for a\ndirectory API without committing to a full import. Doing it server-side is\nthe only sane option \u2014 fetching the raw GitHub spec from the browser hits\nCORS, plus we already have urllib + yaml plumbing here.\n\nReturns the same `{data, total}` envelope as `GET /apis/{id}/operations`\nso the UI can reuse the same renderer for both workspace and directory\nAPIs. Capped at `_PREVIEW_MAX_OPERATIONS` for huge specs (stripe-style).", "operationId": "preview_catalog_operations_catalog__api_id__operations_get", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Catalog api_id to preview operations for", "title": "Api Id" }, "description": "Catalog api_id to preview operations for" }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "description": "Number of operations to skip (pagination).", "default": 0, "title": "Offset" }, "description": "Number of operations to skip (pagination)." }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 200, "minimum": 1, "description": "Maximum operations to return after applying `offset`. The hard ceiling is 200; combined with `offset` it powers cheap load-more pagination from the Detail Sheet.", "default": 200, "title": "Limit" }, "description": "Maximum operations to return after applying `offset`. The hard ceiling is 200; combined with `offset` it powers cheap load-more pagination from the Detail Sheet." }, { "name": "tag", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Case-insensitive substring filter on `op.tags[]`. Filtering happens *before* counting, so `total` reflects the post-filter operation count and `truncated` is computed against the filtered list.", "title": "Tag" }, "description": "Case-insensitive substring filter on `op.tags[]`. Filtering happens *before* counting, so `total` reflects the post-filter operation count and `truncated` is computed against the filtered list." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use to render a read-only operations list for a directory (catalog) API before the user imports it. Fetches the spec server-side from GitHub, parses it, and returns a flat list of {method, path, summary, description, operation_id}. Powers the API Detail Sheet on the Discover page.", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid catalog api_id from GET /catalog" ], "avoid_when": "Do not use for APIs already registered locally \u2014 call GET /apis/{api_id}/operations instead (returns DB-backed operations with stable IDs). Do not use as a replacement for POST /import.", "related_operations": [ "GET /catalog/{api_id} \u2014 get spec_url and registration status", "GET /apis/{api_id}/operations \u2014 read DB-backed operations after import", "POST /import \u2014 register the API locally" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/catalog/{api_id}/workflows": { "get": { "tags": ["catalog", "catalog"], "summary": "Preview workflows for a catalog API without importing", "description": "Server-side Arazzo fetch + parse for the directory workflow preview.\n\nReturns one row per workflow inside `workflows.arazzo.json` with just\nenough metadata to render the API Detail Sheet's Workflows section\n(workflow id, recomputed slug, summary, description, steps count).\n\nEmpty-list response (rather than 404) when the api_id has no\nworkflow manifest entry \u2014 keeps the UI rendering path uniform: the\nsheet always asks, sometimes the answer is \"none\".", "operationId": "preview_catalog_workflows_catalog__api_id__workflows_get", "parameters": [ { "name": "api_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Catalog api_id to preview workflows for", "title": "Api Id" }, "description": "Catalog api_id to preview workflows for" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use to render a read-only workflows list for a directory (catalog) API before the user imports it. Fetches the Arazzo file server-side from GitHub, parses it, and returns a flat list of {workflow_id, slug, summary, description, steps_count}. Powers the Workflows section of the API Detail Sheet on the Discover page.", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid catalog api_id from GET /catalog", "API must have an entry in the workflow manifest (otherwise returns `{data: [], total: 0}` rather than 404 so the UI can render an empty section without branching)." ], "avoid_when": "Do not use for APIs already imported with their workflows \u2014 call GET /workflows?api_id=... instead (returns DB-backed workflows with stable slugs and full step bodies). Do not use as a replacement for POST /credentials, which triggers the actual import pipeline.", "related_operations": [ "GET /catalog/{api_id} \u2014 get spec_url and registration status", "GET /catalog/{api_id}/operations \u2014 preview operations for the same API", "POST /credentials \u2014 import the API and its workflows in one go" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/credentials": { "post": { "tags": ["credentials"], "summary": "Store an upstream API credential \u2014 add a secret to the vault for broker injection", "description": "Store an encrypted credential in the vault for automatic broker injection.\n\nValues are encrypted at rest and **never returned** after creation. Set `api_id` to\nbind the credential to an API; the broker will inject it automatically when proxying\ncalls to that API.\n\n---\n\n### `auth_type` reference\n\nSet `auth_type` to tell the broker how to inject the credential into upstream requests.\nBased on the [Postman auth type taxonomy](https://learning.postman.com/docs/sending-requests/authorization/authorization-types/).\n\n| `auth_type` | Status | Broker injects | `value` | `identity` |\n|---|---|---|---|---|\n| `bearer` | \u2705 implemented | `Authorization: Bearer {value}` | Token, PAT, or OAuth access token | Not used |\n| `basic` | \u2705 implemented | `Authorization: Basic base64({identity or \"token\"}:{value})` | Password or PAT | Username (optional \u2014 defaults to `\"token\"` if omitted, works for GitHub PATs) |\n| `apiKey` | \u2705 implemented | Custom header or query param `= {value}` | API key | For **compound schemes** (e.g. Discourse `Api-Key` + `Api-Username`): set `identity` to the username \u2014 one credential covers both headers when the overlay uses canonical `Secret`/`Identity` scheme names |\n| `oauth2` | \u26a0\ufe0f partial | `Authorization: Bearer {value}` \u2014 token must be pre-obtained | Access token (Pipedream-managed flows only via `pipedream_oauth`) | Not used |\n| `digest` | \ud83d\udd32 planned | RFC 2617 challenge-response (nonce/HMAC handshake) | Password | Username |\n| `jwt` | \ud83d\udd32 planned | `Authorization: Bearer {signed_jwt}` \u2014 auto-generated from signing key | Private key or secret | Key ID (`kid`) \u2014 signing algorithm and claims go in `context` |\n| `aws_sig4` | \ud83d\udd32 planned | `Authorization: AWS4-HMAC-SHA256 ...` signed headers | AWS Secret Access Key | AWS Access Key ID \u2014 region and service go in `context` |\n| `oauth1` | \ud83d\udd32 planned | HMAC-SHA1 signed request (nonce + timestamp) | OAuth secret | OAuth consumer key |\n| `hawk` | \ud83d\udd32 planned | `Authorization: Hawk ...` HMAC request signing | Hawk secret | Hawk key ID |\n| `ntlm` | \ud83d\udd32 not planned | Windows NTLM challenge-response | Password | Username + domain |\n| `akamai_edgegrid` | \ud83d\udd32 not planned | Akamai EdgeGrid signing | Client secret | Client token + access token in `context` |\n\n**Notes:**\n- `pipedream_oauth` is a reserved value written by the Pipedream integration \u2014 do not set it manually.\n- For `oauth2` full flows (auth code, client credentials, PKCE, token refresh) see the roadmap.\n- `context` (not yet exposed) will hold auxiliary fields for multi-value schemes (JWT claims, AWS region/service, etc.).\n\n---\n\n### Workflow\n\n1. Call `GET /apis/{api_id}` \u2014 check `security_schemes` and `credentials_configured` to find gaps.\n2. Post this endpoint with `api_id`, `auth_type`, `value` (and `identity` if needed).\n3. The broker injects the credential automatically on every proxied call to that API.\n4. To scope a credential to a specific toolkit: `POST /toolkits/{id}/credentials`.\n\nIf the API has no registered security scheme yet, submit an overlay first: `POST /apis/{api_id}/overlays`.", "operationId": "create_credentials_post", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CredentialCreate" } } }, "description": "Credential details: label for identification, encrypted value (API key/token/password), optional identity (username/client ID), API ID, and auth type" }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CredentialOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "get": { "tags": ["credentials"], "summary": "List upstream API credentials \u2014 labels and API bindings only, no secret values", "description": "List stored upstream API credentials. Values are never returned.\n\nAll authenticated callers (agent keys and human sessions) can see all credential\nlabels and IDs \u2014 this is intentional. Labels are not secrets, and agents need\nto discover credential IDs in order to file targeted `grant` access requests\n(e.g. \"bind Work Gmail\" vs \"bind Personal Gmail\").\n\nUse `GET /credentials/{id}` to retrieve a specific credential by ID.\nFilter with `?api_id=api.github.com` to list all credentials for a given API.", "operationId": "list_credentials_credentials_get", "parameters": [ { "name": "api_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter credentials by API ID (hostname)", "title": "Api Id" }, "description": "Filter credentials by API ID (hostname)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/CredentialOut" }, "title": "Response List Credentials Credentials Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/credentials/{cid}": { "get": { "tags": ["credentials"], "summary": "Get an upstream API credential by ID", "description": "Retrieve metadata for a single credential. Value is never returned.", "operationId": "get_credential_credentials__cid__get", "parameters": [ { "name": "cid", "in": "path", "required": true, "schema": { "type": "string", "title": "Cid" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CredentialOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }, "patch": { "tags": ["credentials"], "summary": "Update an upstream API credential \u2014 rotate a secret or fix its API binding", "description": "Update a credential's label, secret value, identity field, API binding, or auth_type.\n\nCommon use cases:\n- Rotate an expired token or password (update `value`)\n- Fix incorrect API binding (update `api_id`)\n- Add username to existing credential (update `identity`)\n- Relabel for clarity (update `label`)\n\nOnly changed fields need to be included in the request body. Omitted fields are left unchanged.\n\n**Auth:** Requires human session OR agent key with explicit `PATCH /credentials` allow rule on jentic-mini credential.", "operationId": "patch_credentials__cid__patch", "parameters": [ { "name": "cid", "in": "path", "required": true, "schema": { "type": "string", "description": "Credential ID to update", "title": "Cid" }, "description": "Credential ID to update" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CredentialPatch" } } }, "description": "Fields to update: label, value (for rotation), identity, api_id, or auth_type \u2014 only provided fields are changed" }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CredentialOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "delete": { "tags": ["credentials"], "summary": "Delete an upstream API credential", "description": "Permanently delete a credential.\n\nThe credential is removed from the vault and unbound from all toolkits that reference it.\nAgents using toolkits with this credential will immediately lose access to the upstream API.\n\n**Auth:** Requires human session OR agent key with explicit `DELETE /credentials` allow rule on jentic-mini credential.\n\n**Warning:** This operation cannot be undone. The secret value is irrecoverably destroyed.", "operationId": "delete_credentials__cid__delete", "parameters": [ { "name": "cid", "in": "path", "required": true, "schema": { "type": "string", "description": "Credential ID to delete", "title": "Cid" }, "description": "Credential ID to delete" } ], "responses": { "204": { "description": "Successful Response" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/default-api-key/generate": { "post": { "tags": ["user"], "summary": "Generate (or regenerate) the default toolkit API key", "description": "Rotate the default `tk_xxx` key for the default toolkit (human session only).\n\nOnly available when a default key was created in the past. New instances use agent identity\n(OAuth DCR) for agent onboarding; toolkit keys remain valid for other uses.", "operationId": "generate_default_key_default_api_key_generate_post", "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } }, "security": [ { "HumanLogin": [] } ] } }, "/health": { "get": { "tags": ["meta"], "summary": "Health", "description": "Returns current setup state with explicit instructions for agents and UI.\n\nResponse varies based on setup progress:\n- status='setup_required': No admin account yet \u2192 OAuth metadata URLs for agent DCR; human setup_url\n- status='ok': Admin account exists \u2192 includes version and apis_registered count\n\nThis endpoint is always public (no auth required) so agents can check setup state before\nattempting authenticated calls. UI uses this to determine whether to show setup wizard.\n\nReturns:\n Setup status, version, and context-specific next steps or operational metrics.", "operationId": "health_health_get", "responses": { "200": { "description": "Setup state. Schema varies by status \u2014 discriminate on the `status` field.", "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/HealthSetupRequired" }, { "$ref": "#/components/schemas/HealthOk" } ], "title": "Response Health Health Get" } } } } }, "security": [] } }, "/import": { "post": { "tags": ["catalog"], "summary": "Import an API spec or workflow \u2014 add to the searchable catalog", "description": "Registers an OpenAPI spec or Arazzo workflow into the catalog and BM25 index.\nSource types: path (local file), url (fetch from URL), inline (spec content in request body).\nFor OpenAPI specs: parses operations, computes capability IDs, indexes descriptions.\nFor Arazzo workflows: stores definition, extracts input schema and involved APIs.\nReturns the registered API or workflow with its canonical id.", "operationId": "import_sources_import_post", "requestBody": { "description": "Array of import sources (local file paths, URLs, or inline spec content) to register in the catalog \u2014 supports OpenAPI 3.x and Arazzo 1.0", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImportRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImportOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use to register a new API (OpenAPI 3.x spec) or workflow (Arazzo document) into the local catalog for searchability and execution. Supports three source types: url (fetch from remote URL), path (local file path), inline (spec content in request body). Automatically detects OpenAPI vs Arazzo, parses operations, computes capability IDs, and indexes for BM25 search. Use when adding a new API not yet in the catalog.", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid OpenAPI 3.x or Arazzo 1.0 document", "For url type: publicly accessible spec URL", "For path type: local file system path (server must have read access)", "For inline type: spec content as JSON or YAML string" ], "avoid_when": "Do not use for APIs already in the catalog \u2014 check GET /apis or GET /catalog first. Do not use to add credentials (use POST /credentials). Do not use to update existing specs \u2014 delete and re-import instead.", "related_operations": [ "GET /apis \u2014 check if API is already registered before importing", "GET /catalog \u2014 browse available APIs in public catalog before importing", "POST /credentials \u2014 add credentials after importing an API", "GET /search \u2014 verify imported operations are searchable" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/inspect/{capability_id}": { "get": { "tags": ["inspect"], "summary": "Inspect a capability \u2014 get full schema, auth, and parameters before calling", "description": "Returns everything needed to call an operation or workflow: resolved parameter schema\n(all $refs inlined), response schema, auth translated to concrete header instructions,\nAPI context (name, description, tag descriptions), and HATEOAS _links (execute, upstream).\n\nCapability id format: METHOD/host/path \u2014 e.g. GET/api.stripe.com/v1/customers\nor POST/{jentic_hostname}/workflows/summarise-latest-topics.\nPass ?toolkit_id=... to check whether credentials are configured for that toolkit.\nAccept: text/markdown returns a compact LLM-friendly format.\nAccept: application/openapi+yaml returns the raw OpenAPI operation snippet.", "operationId": "get_capability_inspect__capability_id__get", "parameters": [ { "name": "capability_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Capability ID (METHOD/host/path format) or workflow slug", "title": "Capability Id" }, "description": "Capability ID (METHOD/host/path format) or workflow slug" }, { "name": "toolkit_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Pass to include credential status for this toolkit", "title": "Toolkit Id" }, "description": "Pass to include credential status for this toolkit" } ], "responses": { "200": { "description": "Full capability detail \u2014 format controlled by Accept header.", "content": { "application/json": { "schema": { "type": "object", "description": "Structured JSON with resolved schemas" } }, "text/markdown": { "schema": { "type": "string", "description": "LLM-friendly prose description" } }, "application/openapi+yaml": { "schema": { "type": "string", "description": "Filtered, dereferenced OpenAPI fragment" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use after finding an operation via GET /search when you need complete parameter schemas, authentication requirements, and response formats before making the actual call. Essential step between discovery and execution.", "prerequisites": [ "Valid capability ID from GET /search results (format: METHOD/host/path)", "Optional: Pass ?toolkit_id={id} to check credential configuration status" ], "avoid_when": "Do not use for bulk inspection \u2014 prefer GET /apis/{api_id}/operations when browsing an entire API's operation list.", "related_operations": [ "GET /search \u2014 find capabilities by natural language query first", "GET /{target} \u2014 execute the operation after inspecting", "GET /apis/{api_id}/operations \u2014 list all operations for an API" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/jobs": { "get": { "tags": ["observe"], "summary": "List async jobs \u2014 paginated handles for outstanding and completed async calls", "description": "Returns async jobs only \u2014 calls that could not complete synchronously. Sync calls produce traces but no jobs. Filter by `status` (pending|running|complete|failed|upstream_async). Poll `GET /jobs/{id}` for individual job status.", "operationId": "list_jobs_jobs_get", "parameters": [ { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by status. Accepts a single value or a comma-separated set (e.g. `pending,running` for in-flight only). Whitespace tolerated.", "title": "Status" }, "description": "Filter by status. Accepts a single value or a comma-separated set (e.g. `pending,running` for in-flight only). Whitespace tolerated." }, { "name": "kind", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string", "pattern": "^(workflow|broker)$" }, { "type": "null" } ], "description": "Filter by job kind: `workflow` (multi-step Arazzo runs) or `broker` (individual API calls dispatched async). Used by the Monitor Jobs tab to split workflow runs from broker calls in separate views.", "title": "Kind" }, "description": "Filter by job kind: `workflow` (multi-step Arazzo runs) or `broker` (individual API calls dispatched async). Used by the Monitor Jobs tab to split workflow runs from broker calls in separate views." }, { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "description": "Page number (1-indexed)", "default": 1, "title": "Page" }, "description": "Page number (1-indexed)" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "description": "Results per page (1-100)", "default": 20, "title": "Limit" }, "description": "Results per page (1-100)" }, { "name": "toolkit_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by toolkit id (exact match)", "title": "Toolkit Id" }, "description": "Filter by toolkit id (exact match)" }, { "name": "agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by agent client_id (exact match).", "title": "Agent Id" }, "description": "Filter by agent client_id (exact match)." }, { "name": "since", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "number", "minimum": 0 }, { "type": "null" } ], "description": "Lower bound on `created_at` (unix seconds, inclusive)", "title": "Since" }, "description": "Lower bound on `created_at` (unix seconds, inclusive)" }, { "name": "until", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "number", "minimum": 0 }, { "type": "null" } ], "description": "Upper bound on `created_at` (unix seconds, exclusive)", "title": "Until" }, "description": "Upper bound on `created_at` (unix seconds, exclusive)" }, { "name": "q", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string", "minLength": 1, "maxLength": 200 }, { "type": "null" } ], "description": "Free-text substring match (case-insensitive) across the columns the Jobs tab row renders: `slug_or_id` (workflow slug or broker capability id), `agent_id`, `toolkit_id`, and `upstream_job_url` (so a search for the upstream provider's job-id snippet still finds the right row). Empty/whitespace strings are treated as not set so the no-filter plan stays cheap. None of those columns are indexed for prefix lookups, so `q` always implies a scan over the rows that the tenant + time-window clauses already select \u2014 fine for the Monitor page (24h default) but don't use it as a general-purpose search.", "title": "Q" }, "description": "Free-text substring match (case-insensitive) across the columns the Jobs tab row renders: `slug_or_id` (workflow slug or broker capability id), `agent_id`, `toolkit_id`, and `upstream_job_url` (so a search for the upstream provider's job-id snippet still finds the right row). Empty/whitespace strings are treated as not set so the no-filter plan stays cheap. None of those columns are indexed for prefix lookups, so `q` always implies a scan over the rows that the tenant + time-window clauses already select \u2014 fine for the Monitor page (24h default) but don't use it as a general-purpose search." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JobListPage" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/jobs/{job_id}": { "get": { "tags": ["observe"], "summary": "Poll async job \u2014 check status and retrieve result when complete", "description": "Poll this endpoint after receiving a 202. The job_id comes from the `Location` response header (RFC 7240) or the `X-Jentic-Job-Id` header. Returns `status: pending|running` while in progress. Returns `status: complete` with `result` when done. Returns `status: upstream_async` when the upstream API itself returned 202 \u2014 check `upstream_job_url` to follow the upstream job. Returns `status: failed` with `error` and `http_status` on failure.", "operationId": "get_job_route_jobs__job_id__get", "parameters": [ { "name": "job_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Job ID (format: job_{12chars})", "title": "Job Id" }, "description": "Job ID (format: job_{12chars})" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/JobOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use after receiving HTTP 202 from a broker call or workflow execution to poll for completion. Job ID comes from Location header (RFC 7240) or X-Jentic-Job-Id header. Poll until status is complete, failed, or upstream_async. Jobs are created when: (1) client sends Prefer: wait=0, (2) execution exceeds Prefer: wait=N timeout, or (3) upstream API returns 202.", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid job ID from a 202 response (format: job_{12chars})" ], "avoid_when": "Do not use for synchronous calls (200 responses) \u2014 those produce traces, not jobs. Do not poll excessively \u2014 implement exponential backoff (start at 1s, max 30s).", "related_operations": [ "GET /{target} (broker) \u2014 broker call with Prefer: wait=0 returns 202 + job ID", "POST /workflows/{slug} \u2014 workflow with Prefer: wait=0 returns 202 + job ID", "GET /traces/{id} \u2014 completed jobs reference a trace via trace_id field", "DELETE /jobs/{id} \u2014 cancel an outstanding async job" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }, "delete": { "tags": ["observe"], "summary": "Cancel async job \u2014 best-effort cancellation of an outstanding job", "description": "Requests cancellation of a pending or running async job. Best-effort: cancellation fires at the next async checkpoint; an in-flight upstream HTTP request will complete before the job stops. The job record is retained (marked failed, error='Cancelled by client'). Has no effect on already-completed jobs.", "operationId": "cancel_job_jobs__job_id__delete", "parameters": [ { "name": "job_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Job ID to cancel", "title": "Job Id" }, "description": "Job ID to cancel" } ], "responses": { "204": { "description": "Successful Response" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/notes": { "post": { "tags": ["catalog"], "summary": "Add a note \u2014 annotate a capability with feedback or a correction", "description": "Attaches a note to any capability (operation, workflow, or API). Use to report auth corrections, schema errors, or updated Arazzo workflows. Notes feed back into the catalog improvement loop.", "operationId": "create_note_notes_post", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NoteCreate" } } }, "description": "Note details: resource ID, note type (auth_quirk/usage_hint/execution_feedback/correction), content, optional execution link, confidence level, and source" }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use to report observations about operations, workflows, or APIs that could improve the catalog: auth quirks (non-standard auth requirements), usage hints (tips for effective use), execution feedback (what happened when called), corrections (errors in spec descriptions). Notes feed the Jentic knowledge base for catalog improvement. Link to execution_id for context.", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid resource identifier (operation_id, api_id, or workflow slug)" ], "avoid_when": "Do not use for private execution logs \u2014 use GET /traces instead. Do not use for credential issues \u2014 fix credentials via PATCH /credentials.", "related_operations": [ "GET /notes \u2014 list existing notes for a resource to avoid duplicates", "DELETE /notes/{id} \u2014 remove outdated or incorrect notes", "GET /traces/{id} \u2014 link to execution context when reporting feedback", "POST /apis/{api_id}/overlays \u2014 submit OpenAPI overlay to fix spec issues" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }, "get": { "tags": ["catalog"], "summary": "List notes for a resource", "description": "List notes attached to resources (operations, workflows, APIs).\n\nNotes capture observations from execution \u2014 success signals, failure patterns,\ndata validation findings, and human annotations. Agents use notes to build\noperational knowledge and improve reliability over time.\n\nFilter by `?resource={id}` to see notes for a specific operation/workflow,\nor by `?type={type}` to filter by note category (e.g., \"success\", \"error\", \"validation\").", "operationId": "list_notes_notes_get", "parameters": [ { "name": "resource", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter notes by resource ID (capability_id, api_id, or workflow slug)", "title": "Resource" }, "description": "Filter notes by resource ID (capability_id, api_id, or workflow slug)" }, { "name": "type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter notes by type (auth_quirk, usage_hint, execution_feedback, correction)", "title": "Type" }, "description": "Filter notes by type (auth_quirk, usage_hint, execution_feedback, correction)" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 500, "minimum": 1, "description": "Maximum number of notes to return (1-500)", "default": 50, "title": "Limit" }, "description": "Maximum number of notes to return (1-500)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use to retrieve operational knowledge about operations, workflows, or APIs before calling them. Returns notes from previous executions: auth quirks, usage tips, failure patterns, schema corrections. Filter by ?resource={capability_id} to see notes for a specific operation/workflow, or by ?type={category} to filter by note type (auth_quirk, usage_hint, execution_feedback, correction). Limit defaults to 50, ordered by creation date descending.", "prerequisites": ["Requires authentication (toolkit key or human session)"], "avoid_when": "Do not use for execution history \u2014 use GET /traces instead. Do not use for credential status \u2014 use GET /credentials.", "related_operations": [ "POST /notes \u2014 add a note after discovering new operational knowledge", "DELETE /notes/{id} \u2014 remove outdated notes", "GET /inspect/{id} \u2014 inspect operation schema before checking notes", "GET /traces \u2014 view execution history for context" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/notes/{note_id}": { "delete": { "tags": ["catalog"], "summary": "Delete a note", "description": "Permanently delete a note.\n\nUse this to remove outdated observations, incorrect annotations, or\nnotes that no longer apply after an API change.", "operationId": "delete_note_notes__note_id__delete", "parameters": [ { "name": "note_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Note ID to delete (format: note_{8chars})", "title": "Note Id" }, "description": "Note ID to delete (format: note_{8chars})" } ], "responses": { "204": { "description": "Successful Response" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use to remove outdated observations, incorrect annotations, or notes that no longer apply after an API change. Deletion is permanent.", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid note ID from GET /notes (format: note_{8chars})" ], "avoid_when": "Do not use to hide execution errors \u2014 fix the underlying issue instead. Do not delete notes from other users without coordination.", "related_operations": [ "GET /notes \u2014 list notes to find the note_id", "POST /notes \u2014 add a replacement note after deleting an incorrect one" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/oauth/revoke": { "post": { "tags": ["oauth"], "summary": "OAuth 2.0 token revocation (RFC 7009)", "operationId": "oauth_revoke_oauth_revoke_post", "requestBody": { "content": { "application/x-www-form-urlencoded": { "schema": { "$ref": "#/components/schemas/Body_oauth_revoke_oauth_revoke_post" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "OAuth-formatted error (invalid_request, invalid_grant, unsupported_grant_type).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthError" } } } }, "403": { "description": "Caller is not allowed to revoke this token (e.g. tk_ key, or at_ for a different client_id).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthError" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/oauth/token": { "post": { "tags": ["oauth"], "summary": "OAuth 2.0 token endpoint", "operationId": "oauth_token_oauth_token_post", "requestBody": { "content": { "application/x-www-form-urlencoded": { "schema": { "$ref": "#/components/schemas/Body_oauth_token_oauth_token_post" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "OAuth-formatted error (invalid_request, invalid_grant, unsupported_grant_type).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthError" } } } }, "401": { "description": "OAuth-formatted authentication error (invalid_token).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthError" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [] } }, "/oauth-brokers": { "get": { "tags": ["credentials", "credentials", "inspect"], "summary": "List registered OAuth brokers", "description": "Return all registered OAuth brokers as a flat list. `client_secret` is never included.\n\nAccessible to both agents (toolkit key) and humans (session).", "operationId": "list_oauth_brokers_oauth_brokers_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } }, "x-agent-hints": { "when_to_use": "Use to discover available OAuth brokers (Pipedream, future: Jentic native) for delegated OAuth credential management. Returns list of registered brokers with type, client_id, project_id, and default_external_user_id. Client_secret is never included. Accessible to both agents (toolkit key) and humans (session). Use before connecting apps or syncing accounts.", "prerequisites": ["Requires authentication (toolkit key or human session)"], "avoid_when": "Do not use to retrieve individual broker details \u2014 use GET /oauth-brokers/{broker_id} instead. Do not use to manage OAuth accounts \u2014 use POST /oauth-brokers/{broker_id}/connect-link to initiate OAuth.", "related_operations": [ "POST /oauth-brokers \u2014 register a new OAuth broker (Pipedream)", "GET /oauth-brokers/{broker_id} \u2014 get detailed broker configuration and account statistics", "POST /oauth-brokers/{broker_id}/connect-link \u2014 initiate OAuth flow for an API via broker", "POST /oauth-brokers/{broker_id}/sync \u2014 pull connected accounts into Jentic after OAuth" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }, "post": { "tags": ["credentials", "credentials"], "summary": "Register an OAuth broker", "description": "Register a delegated OAuth broker. Currently supported type: `pipedream`.\n\n---\n\n### Pipedream \u2014 one-time setup\n\nBefore registering, complete these steps in the Pipedream UI:\n\n**1.** Go to [pipedream.com](https://pipedream.com) and sign in or create an account.\n\n**2.** Go to **Settings** (main menu) \u2192 **API** \u2192 click **+ New OAuth Client**.\nName it \"Jentic\". Store the **client ID** and **client secret** safely \u2014 the secret is not shown again.\n\n**3.** Go to **Projects** (main menu) and click **+ New Project**. Name it \"Jentic\".\n\n**4.** Go to **Projects \u2192 Jentic \u2192 Settings** and note the **project ID** (format: `proj_xxx`).\n\nThat's it. Register the broker below \u2014 Jentic automatically configures the Connect\napplication name, support email, and logo in Pipedream on your behalf, so you don't\nneed to touch the Connect \u2192 Configuration screen manually.\n\n---\n\n### Registration\n\n```json\n{\n \"type\": \"pipedream\",\n \"config\": {\n \"client_id\": \"oa_abc123\",\n \"client_secret\": \"pd_secret_xxxx\",\n \"project_id\": \"proj_abc123\",\n \"support_email\": \"support@example.com\"\n }\n}\n```\n\n`support_email` is optional but recommended \u2014 it is displayed to end users in the\nPipedream OAuth consent UI.\n\n`client_secret` is write-only \u2014 Fernet-encrypted at rest, never returned.\n\n---\n\n### After registration\n\nOnce registered, connect individual apps with `POST /oauth-brokers/{id}/connect-link`\n(pass `app` as the Pipedream app slug, e.g. `gmail`, `google_calendar`, `slack`).\nAfter the user completes OAuth, call `POST /oauth-brokers/{id}/sync` to pull the\nconnected account into Jentic. From that point, requests to that API's host are\nautomatically proxied with the user's OAuth token injected server-side.", "operationId": "create_oauth_broker_oauth_brokers_post", "requestBody": { "description": "Broker configuration: type (e.g. 'pipedream'), provider-specific config, and encrypted credentials", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthBrokerCreate" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthBrokerOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/oauth-brokers/{broker_id}": { "patch": { "tags": ["credentials", "credentials"], "summary": "Update an OAuth broker configuration", "description": "Update client_id, client_secret, and/or project_id for an existing broker.\n\nOnly supplied fields are changed. client_secret is re-encrypted if provided.", "operationId": "update_oauth_broker_oauth_brokers__broker_id__patch", "parameters": [ { "name": "broker_id", "in": "path", "required": true, "schema": { "type": "string", "description": "The broker ID", "examples": ["pipedream"], "title": "Broker Id" }, "description": "The broker ID" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthBrokerUpdate" } } }, "description": "Provider-specific config fields to update: client_id, client_secret, project_id \u2014 only provided fields are changed, secrets re-encrypted" }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthBrokerOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "get": { "tags": ["credentials", "credentials", "inspect"], "summary": "Get an OAuth broker", "description": "Retrieve OAuth broker configuration and metadata.\n\nReturns broker type, client ID, project ID, and connected account statistics.\nUse this to verify a broker is registered before creating connect links or syncing accounts.\n\nFor connected account details, use `GET /oauth-brokers/{broker_id}/accounts`.", "operationId": "get_oauth_broker_oauth_brokers__broker_id__get", "parameters": [ { "name": "broker_id", "in": "path", "required": true, "schema": { "type": "string", "description": "The broker ID", "examples": ["pipedream"], "title": "Broker Id" }, "description": "The broker ID" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }, "delete": { "tags": ["credentials", "credentials"], "summary": "Remove an OAuth broker", "description": "Remove a broker and all its connected accounts and credentials.\n\nCascades through oauth_broker_accounts -> toolkit_credentials -> vault.\nDoes not revoke tokens on the provider side - do that in the provider's dashboard.", "operationId": "delete_oauth_broker_oauth_brokers__broker_id__delete", "parameters": [ { "name": "broker_id", "in": "path", "required": true, "schema": { "type": "string", "description": "The broker ID", "examples": ["pipedream"], "title": "Broker Id" }, "description": "The broker ID" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/oauth-brokers/{broker_id}/accounts": { "get": { "tags": ["credentials", "credentials", "inspect"], "summary": "List connected accounts for an OAuth broker", "description": "List the OAuth-connected account mappings stored for this broker.\n\nEach entry represents a SaaS app the user has connected via Pipedream's OAuth\nUI, along with the API host it maps to and the Pipedream `account_id` used when\nrouting requests through the proxy.\n\nUse `POST /oauth-brokers/{id}/sync` to refresh this list from Pipedream.", "operationId": "list_broker_accounts_oauth_brokers__broker_id__accounts_get", "parameters": [ { "name": "broker_id", "in": "path", "required": true, "schema": { "type": "string", "description": "The broker ID", "examples": ["pipedream"], "title": "Broker Id" }, "description": "The broker ID" }, { "name": "external_user_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by external user ID", "examples": ["default"], "title": "External User Id" }, "description": "Filter by external user ID" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/oauth-brokers/{broker_id}/connect-link": { "post": { "tags": ["credentials", "credentials"], "summary": "Generate a Pipedream Connect Link for authorising apps", "description": "Generate a short-lived Pipedream Connect Link URL.\n\nVisit the returned `connect_link_url` in a browser to authorise SaaS apps\n(e.g. Gmail, Slack, GitHub) via Pipedream's hosted OAuth consent UI.\n\nAfter completing the OAuth flow, call `POST /oauth-brokers/{id}/sync` to\npull the new account into jentic-mini so requests start routing through it.\n\nThe link expires after ~1 hour. Generate a new one if it expires before use.\n\nIntentionally open to agents (not human-session-only): only a human can\ncomplete the OAuth flow, so generating the link is safe for agents to initiate.\nRequires at minimum a valid toolkit key or trusted-subnet (admin) access.", "operationId": "create_connect_link_oauth_brokers__broker_id__connect_link_post", "parameters": [ { "name": "broker_id", "in": "path", "required": true, "schema": { "type": "string", "description": "The broker ID", "examples": ["pipedream"], "title": "Broker Id" }, "description": "The broker ID" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConnectLinkRequest" } } }, "description": "Connect link request: Pipedream app slug (e.g. gmail, slack), human-readable label for the connection, and optional api_id override for catalog binding" }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/oauth-brokers/{broker_id}/sync": { "post": { "tags": ["credentials", "credentials"], "summary": "Sync connected accounts from the OAuth broker", "description": "Re-fetch connected accounts from the provider and update local mappings.\n\nCall this after connecting a new app via Pipedream's hosted OAuth UI \u2014\nthe new account will appear in subsequent `GET /oauth-brokers/{id}/accounts`\nresponses and the broker will start routing requests to it automatically.\n\nThis does **not** affect accounts already connected \u2014 it is additive.\n\nIntentionally open to agents: syncing pulls in credentials the human already\nauthorised. No new OAuth flows are initiated.", "operationId": "sync_broker_accounts_oauth_brokers__broker_id__sync_post", "parameters": [ { "name": "broker_id", "in": "path", "required": true, "schema": { "type": "string", "description": "The broker ID", "examples": ["pipedream"], "title": "Broker Id" }, "description": "The broker ID" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SyncRequest" } } }, "description": "Sync request: list of API slugs to sync accounts for (fetches connected accounts from broker and imports as Jentic credentials)" }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/oauth-brokers/{broker_id}/accounts/{account_id}": { "delete": { "tags": ["credentials", "credentials"], "summary": "Remove a connected account from an OAuth broker", "description": "Remove a specific connected account from this broker.\n\nThis performs three actions in order:\n1. Revokes the account in the upstream provider (Pipedream) via their API\n2. Removes the associated credential from all toolkit provisioning\n3. Deletes the credential from the vault and the account from the local DB\n\nIf the Pipedream revoke fails, the local cleanup still proceeds (with a warning).", "operationId": "delete_broker_account_oauth_brokers__broker_id__accounts__account_id__delete", "parameters": [ { "name": "broker_id", "in": "path", "required": true, "schema": { "type": "string", "description": "The broker ID", "examples": ["pipedream"], "title": "Broker Id" }, "description": "The broker ID" }, { "name": "account_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Connected account ID to delete", "title": "Account Id" }, "description": "Connected account ID to delete" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }, "patch": { "tags": ["credentials", "credentials"], "summary": "Update a connected account (e.g. rename label)", "description": "Patch a connected account record.\n\nUpdates the display label for a connected OAuth account. The account remains linked\nto the same external OAuth identity and credentials are not affected. Label changes\nare reflected in both the oauth_broker_accounts table and any associated credentials\nin the vault.\n\nParameters:\n broker_id: OAuth broker ID (e.g. 'pipedream')\n account_id: Connected account ID from the broker\n body: Update request containing the new label\n\nReturns:\n Updated account_id and label.\n\nAuth: Requires human session (admin only).\n\nCurrently supports updating label only. Future versions may support updating\nadditional account metadata.", "operationId": "update_broker_account_oauth_brokers__broker_id__accounts__account_id__patch", "parameters": [ { "name": "broker_id", "in": "path", "required": true, "schema": { "type": "string", "description": "The broker ID", "examples": ["pipedream"], "title": "Broker Id" }, "description": "The broker ID" }, { "name": "account_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Connected account ID to update", "title": "Account Id" }, "description": "Connected account ID to update" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccountUpdate" } } }, "description": "Account update: new display label for this connected OAuth account" }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/oauth-brokers/{broker_id}/accounts/{account_id}/reconnect-link": { "post": { "tags": ["credentials", "credentials"], "summary": "Get a reconnect link for an existing connected account", "description": "Generate a new OAuth connect link for an existing connected account.\n\nThe returned URL sends the user through the Pipedream OAuth flow for the\nsame app slug. On completion, the callback will:\n\n1. Sync the broker (discovering the new account).\n2. If the new account is confirmed present, delete the old account.\n\nThis allows a user to re-authorise a broken connection without losing the\nexisting credential until the replacement is confirmed.", "operationId": "reconnect_account_link_oauth_brokers__broker_id__accounts__account_id__reconnect_link_post", "parameters": [ { "name": "broker_id", "in": "path", "required": true, "schema": { "type": "string", "description": "The broker ID", "examples": ["pipedream"], "title": "Broker Id" }, "description": "The broker ID" }, { "name": "account_id", "in": "path", "required": true, "schema": { "type": "string", "description": "OAuth broker account ID to reconnect", "title": "Account Id" }, "description": "OAuth broker account ID to reconnect" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/register": { "post": { "tags": ["oauth"], "summary": "Dynamic Client Registration (RFC 7591)", "description": "Register an agent identity (client_name + jwks). Returns pending status until a human approves.", "operationId": "dynamic_client_registration_register_post", "requestBody": { "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Body" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Bad request (e.g. malformed jwks).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [] } }, "/register/{client_id}": { "get": { "tags": ["oauth"], "summary": "Read client registration (RFC 7592)", "operationId": "get_registration_register__client_id__get", "parameters": [ { "name": "client_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Client Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "401": { "description": "OAuth-formatted authentication error (invalid_token).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OAuthError" } } } }, "404": { "description": "Resource not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPErrorDetail" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "AgentOauthRegistrationToken": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/search": { "get": { "tags": ["search"], "summary": "Search the catalog \u2014 find operations and workflows by natural language intent", "description": "BM25 search over all registered API operations, Arazzo workflows, and the Jentic public API catalog.\n\nReturns id, summary, description (\u22643 sentences), type, score, and _links.\n- `source: \"local\"` \u2014 operation or workflow in your local registry\n- `source: \"catalog\"` \u2014 API available from the Jentic public catalog; add credentials to use\n\nEach row also carries `matched_on` (which fields the query hit) and an\noptional `match_snippet` with the matched span wrapped in `\u0001` markers.\n\n_links.inspect \u2192 GET /inspect/{id} for full schema and auth detail.\n_links.execute \u2192 broker URL to call directly once ready.\nTypical flow: search \u2192 inspect \u2192 execute.", "operationId": "search_search_get", "parameters": [ { "name": "q", "in": "query", "required": true, "schema": { "type": "string", "description": "Search query, e.g. \"send an email\" or \"create payment\"", "title": "Q" }, "description": "Search query, e.g. \"send an email\" or \"create payment\"" }, { "name": "n", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 100, "minimum": 1, "description": "Number of results to return", "default": 10, "title": "N" }, "description": "Number of results to return" }, { "name": "source", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Restrict results by source: `workspace` (locally registered APIs and workflows) or `directory` (Jentic public catalog). Default `all` mixes both. Legacy synonyms `local`\u2192`workspace` and `catalog`\u2192`directory` are accepted for backwards compatibility.", "title": "Source" }, "description": "Restrict results by source: `workspace` (locally registered APIs and workflows) or `directory` (Jentic public catalog). Default `all` mixes both. Legacy synonyms `local`\u2192`workspace` and `catalog`\u2192`directory` are accepted for backwards compatibility." }, { "name": "type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Restrict by result type: `endpoint` (workspace operations only), `workflow` (workspace workflows + directory APIs that ship workflows), or `api` (directory APIs). Default `all` returns the full mix. Directory APIs always carry a `has_workflows` boolean indicating whether the public catalog also ships Arazzo workflows for that vendor.", "title": "Type" }, "description": "Restrict by result type: `endpoint` (workspace operations only), `workflow` (workspace workflows + directory APIs that ship workflows), or `api` (directory APIs). Default `all` returns the full mix. Directory APIs always carry a `has_workflows` boolean indicating whether the public catalog also ships Arazzo workflows for that vendor." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/SearchResult" }, "title": "Response Search Search Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use when you need to discover APIs or workflows based on a natural language description of what you want to do. Primary entry point for finding capabilities \u2014 search first before exploring individual APIs.", "prerequisites": ["Requires authentication (toolkit key or human session)"], "avoid_when": "Do not use if you already know the exact operation ID or workflow slug \u2014 use GET /inspect/{id} directly instead.", "related_operations": [ "GET /inspect/{id} \u2014 get full operation details after finding it via search", "GET /apis \u2014 browse APIs by provider when you know the vendor", "GET /workflows \u2014 list all workflows when browsing by category" ] }, "security": [] } }, "/toolkits": { "get": { "tags": ["toolkits"], "summary": "List toolkits", "description": "List all toolkits with metadata summary.\n\nReturns all toolkits visible to the caller with key counts and bound credential counts.\nAdmin users see all toolkits. Agents see only their own toolkit.\n\nEach toolkit includes:\n- Metadata (name, description, disabled state, simulation mode)\n- Active key count (revoked keys excluded)\n- Bound credential count (upstream API credentials available to this toolkit)\n\nThe default toolkit implicitly has access to all credentials without explicit binding.", "operationId": "list_toolkits_toolkits_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/ToolkitOut" }, "type": "array", "title": "Response List Toolkits Toolkits Get" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }, "post": { "tags": ["toolkits"], "summary": "Create a toolkit \u2014 scoped bundle of upstream API credentials with a client API key", "description": "Creates a toolkit: a named bundle of upstream API credentials with a scoped client API key for the agent.\nReturns a toolkit API key (tk_xxx) \u2014 shown once, not recoverable.\nBind credentials via POST /toolkits/{id}/credentials.\nSet access policy via PUT /toolkits/{id}/credentials/{cred_id}/permissions.\nAgents use toolkit keys to call the broker; only bound credentials are injected.", "operationId": "create_toolkit_toolkits_post", "requestBody": { "description": "Toolkit details: name, optional description, simulate flag for dry-run mode, and optional first API key configuration", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ToolkitCreate" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ToolkitOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}": { "get": { "tags": ["toolkits"], "summary": "Get toolkit \u2014 metadata, bound upstream API credentials, client API keys, and policy summary", "description": "Get toolkit with all inline context: metadata, bound upstream API credentials, client API key count, and policy summary.\nThe default toolkit implicitly contains ALL upstream API credentials \u2014 no explicit binding needed.", "operationId": "get_toolkit_toolkits__toolkit_id__get", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID (e.g. 'default' or custom toolkit identifier)", "title": "Toolkit Id" }, "description": "Toolkit ID (e.g. 'default' or custom toolkit identifier)" } ], "responses": { "200": { "description": "Toolkit detail \u2014 format controlled by Accept header.", "content": { "application/json": { "schema": { "type": "object" } }, "application/yaml": { "schema": { "type": "string", "description": "Toolkit detail as YAML" } }, "text/markdown": { "schema": { "type": "string", "description": "LLM-friendly toolkit summary" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }, "patch": { "tags": ["toolkits"], "summary": "Update toolkit \u2014 rename or update description", "description": "Update toolkit metadata \u2014 name, description, disabled state, or simulation mode.\n\nOnly changed fields need to be included in the request body. Omitted fields are left unchanged.\n\n**Note:** The default toolkit's name and description cannot be modified (403 error).\n\n**Auth:** Requires human session (admin).", "operationId": "patch_toolkit_toolkits__toolkit_id__patch", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID to update", "title": "Toolkit Id" }, "description": "Toolkit ID to update" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ToolkitPatch" } } }, "description": "Fields to update: name, description, simulate flag, or disabled flag \u2014 only provided fields are changed" }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ToolkitOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "delete": { "tags": ["toolkits"], "summary": "Delete toolkit and revoke all its client API keys", "description": "Permanently delete a toolkit and revoke all its access keys.\n\nAll agents using keys from this toolkit will immediately receive 401 errors.\nCredential bindings are removed, but the credentials themselves remain in the vault.\n\n**Note:** The default toolkit cannot be deleted (403 error).\n\n**Auth:** Requires human session (admin).\n\n**Warning:** This operation cannot be undone.", "operationId": "delete_toolkit_toolkits__toolkit_id__delete", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID to delete", "title": "Toolkit Id" }, "description": "Toolkit ID to delete" } ], "responses": { "204": { "description": "Successful Response" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/access-requests": { "post": { "tags": ["toolkits", "toolkits"], "summary": "Request access \u2014 ask a human to grant a credential or adjust permissions", "description": "Agent submits an access request. A human approves or denies it at the `approve_url`.\n\n**Workflow:**\n1. `GET /credentials?api_id=` \u2014 find the `credential_id` you need\n2. `POST` this endpoint with `type`, `credential_id`, `rules`, and optional `reason`\n3. Return the `approve_url` to your user and poll `status` until `approved` or `denied`\n\nThe toolkit ID in the URL must match the caller's own toolkit.\nAdmin/human sessions may file requests on behalf of any toolkit.", "operationId": "create_access_request_toolkits__toolkit_id__access_requests_post", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccessRequestBody" } } }, "description": "Access request: type (grant/modify_permissions), credential_id, optional permission rules, and optional reason explaining why access is needed" }, "responses": { "202": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccessRequestOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }, "get": { "tags": ["toolkits", "toolkits"], "summary": "List access requests for this toolkit", "description": "List access requests for a toolkit, newest first.\n\nEach item includes the full `payload` (credential ID, rules, etc.) and current `status`.\nFilter by `status=pending` to find outstanding requests awaiting approval.\n\n**`type` values:**\n- `grant` \u2014 agent is requesting a new credential be bound; `payload` contains `credential_id` and optional `rules`\n- `modify_permissions` \u2014 agent is requesting a rule change on an existing credential; `payload` contains `credential_id` and `rules`\n\nAgent keys see only their own toolkit's requests. Admin/human sessions may view any toolkit.", "operationId": "list_access_requests_toolkits__toolkit_id__access_requests_get", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" }, { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by status (pending, approved, denied)", "title": "Status" }, "description": "Filter by status (pending, approved, denied)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/AccessRequestOut" }, "title": "Response List Access Requests Toolkits Toolkit Id Access Requests Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/credentials": { "post": { "tags": ["toolkits"], "summary": "Bind an upstream API credential to this toolkit \u2014 enable broker injection", "description": "Enrolls an existing upstream API credential in this toolkit. The broker automatically injects it into outbound calls for the API it's bound to, when the agent calls using this toolkit's client API key.", "operationId": "add_credential_to_toolkit_toolkits__toolkit_id__credentials_post", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID to bind credential to", "title": "Toolkit Id" }, "description": "Toolkit ID to bind credential to" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ToolkitCredentialAdd" } } }, "description": "Credential binding: credential_id to bind to this toolkit (enables broker to inject auth for that API)" }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CredentialBindingOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "get": { "tags": ["toolkits"], "summary": "List upstream API credentials bound to this toolkit", "description": "List upstream API credentials bound to this toolkit.\nAdmin (human session) may list any toolkit's credentials.\nAgents may list credentials for their own toolkit only.", "operationId": "list_toolkit_credentials_toolkits__toolkit_id__credentials_get", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID to list credentials for", "title": "Toolkit Id" }, "description": "Toolkit ID to list credentials for" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/CredentialBindingOut" }, "title": "Response List Toolkit Credentials Toolkits Toolkit Id Credentials Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/keys": { "post": { "tags": ["toolkits"], "summary": "Issue a new client API key for this toolkit", "description": "Issues an additional client API key (tk_xxx) for this toolkit. Hand this key to the agent. Optionally restrict by IP (CIDR list). Returned once \u2014 not recoverable.", "operationId": "create_toolkit_key_toolkits__toolkit_id__keys_post", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID to issue key for", "title": "Toolkit Id" }, "description": "Toolkit ID to issue key for" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/KeyCreate" } } }, "description": "Key configuration: optional label and optional IP allowlist (CIDR ranges)" }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ToolkitKeyCreated" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "get": { "tags": ["toolkits"], "summary": "List client API keys for this toolkit \u2014 metadata only, no secret values", "description": "List all access keys for this toolkit.\n\nActive and revoked keys are shown (revoked keys have `revoked_at` set).\nThe `api_key` value is never returned \u2014 only the key ID and metadata.", "operationId": "list_toolkit_keys_toolkits__toolkit_id__keys_get", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID to list keys for", "title": "Toolkit Id" }, "description": "Toolkit ID to list keys for" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/access-requests/{req_id}": { "get": { "tags": ["toolkits", "toolkits"], "summary": "Poll an access request \u2014 check approval status", "description": "Poll the status of a specific access request.\n\nPoll this endpoint after directing the user to `approve_url`. Status transitions:\n`pending` \u2192 `approved` | `denied`\n\nOn approval, the `payload` contains the exact data that was applied (credential bound,\nrules set, etc.). For programmatic polling, check `status` field only \u2014 `approved`\nmeans the side effects have already been applied and the toolkit is ready to use.", "operationId": "get_access_request_toolkits__toolkit_id__access_requests__req_id__get", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" }, { "name": "req_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Access request ID (format: areq_xxxxxxxx)", "title": "Req Id" }, "description": "Access request ID (format: areq_xxxxxxxx)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccessRequestOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/credentials/{credential_id}": { "delete": { "tags": ["toolkits"], "summary": "Unbind an upstream API credential from this toolkit", "description": "Unbind a credential from this toolkit.\n\nAgents using this toolkit will immediately lose access to the upstream API.\nThe credential remains in the vault and can be bound to other toolkits.\n\nTo delete the credential entirely (from all toolkits), use `DELETE /credentials/{id}`.", "operationId": "remove_credential_from_toolkit_toolkits__toolkit_id__credentials__credential_id__delete", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" }, { "name": "credential_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Credential ID to unbind", "title": "Credential Id" }, "description": "Credential ID to unbind" } ], "responses": { "204": { "description": "Successful Response" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/keys/{key_id}": { "patch": { "tags": ["toolkits"], "summary": "Update a client API key \u2014 rename or change IP restrictions", "description": "Update label or IP restrictions on a client API key.\n\nModifies the metadata for an existing toolkit key. The key value itself cannot be\nchanged - to rotate a key, revoke the old one and create a new one.\n\nParameters:\n toolkit_id: Toolkit ID containing the key\n key_id: Key ID to update (format: ck_xxxxxxxx)\n body: Update request with optional label and/or allowed_ips\n\nUpdatable fields:\n - label: Human-readable name (e.g. \"Production bot\", \"Staging agent\")\n - allowed_ips: IP allowlist in CIDR notation (e.g. [\"192.168.1.0/24\"]).\n Set to null or empty array to allow all IPs.\n\nReturns:\n Updated key metadata including new label and IP restrictions.\n\nThe key remains active with its original value. Changes take effect immediately.", "operationId": "patch_toolkit_key_toolkits__toolkit_id__keys__key_id__patch", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" }, { "name": "key_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Key ID to update", "title": "Key Id" }, "description": "Key ID to update" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/KeyCreate" } } }, "description": "Fields to update: label or IP allowlist \u2014 only provided fields are changed" }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ToolkitKeyOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "delete": { "tags": ["toolkits"], "summary": "Revoke a client API key", "description": "Revoke a single access key.\n\nOther keys for this toolkit remain active. The revoked key immediately\nstops working \u2014 any agent using it will receive 401 on their next request.", "operationId": "revoke_toolkit_key_toolkits__toolkit_id__keys__key_id__delete", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" }, { "name": "key_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Key ID to revoke", "title": "Key Id" }, "description": "Key ID to revoke" } ], "responses": { "204": { "description": "Successful Response" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/access-requests/{req_id}/approve": { "post": { "tags": ["toolkits", "toolkits"], "summary": "Approve an access request (human session only)", "description": "Approve a pending access request (human or admin action \u2014 agent keys cannot do this).\n\nFor `grant` requests: the upstream API credential is automatically bound to the toolkit.\nFor `modify_permissions` requests: the new permission rules are applied immediately.", "operationId": "approve_access_request_toolkits__toolkit_id__access_requests__req_id__approve_post", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" }, { "name": "req_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Access request ID to approve", "title": "Req Id" }, "description": "Access request ID to approve" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccessRequestOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/access-requests/{req_id}/deny": { "post": { "tags": ["toolkits", "toolkits"], "summary": "Deny an access request (human session only)", "description": "Deny a pending access request.\n\nPermanently rejects the request. The agent will receive a 403 error if it continues\nto attempt the operation that required the permission. To grant access later, the\nagent must file a new request.\n\nParameters:\n toolkit_id: Toolkit ID containing the access request\n req_id: Access request ID (format: areq_xxxxxxxx)\n\nReturns:\n Updated access request with status='denied' and resolved_at timestamp.\n\nAuth: Requires human session (admin).", "operationId": "deny_access_request_toolkits__toolkit_id__access_requests__req_id__deny_post", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" }, { "name": "req_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Access request ID to deny", "title": "Req Id" }, "description": "Access request ID to deny" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AccessRequestOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/credentials/{cred_id}/permissions": { "get": { "tags": ["toolkits", "toolkits"], "summary": "Get the permission rules for a specific credential in this toolkit", "description": "Returns all rules in evaluation order for this credential: agent-defined rules first,\nthen the immutable system safety rules appended by the server. First match wins.\n\nSince rules are scoped to a single credential (which is bound to a specific API),\npath and operation patterns apply only to calls made using this credential.\nSystem rules are tagged `_system: true` \u2014 they cannot be removed.", "operationId": "get_credential_permissions_toolkits__toolkit_id__credentials__cred_id__permissions_get", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" }, { "name": "cred_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Credential ID to get permissions for", "title": "Cred Id" }, "description": "Credential ID to get permissions for" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/PermissionRuleOut" }, "title": "Response Get Credential Permissions Toolkits Toolkit Id Credentials Cred Id Permissions Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }, "put": { "tags": ["toolkits", "toolkits"], "summary": "Replace permission rules for a specific credential", "description": "Replaces the entire agent rule list for this credential.\nSystem safety rules are always appended server-side and cannot be removed.\nUse `PATCH` to add or remove individual rules without replacing the full list.", "operationId": "set_credential_permissions_toolkits__toolkit_id__credentials__cred_id__permissions_put", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" }, { "name": "cred_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Credential ID to set permissions for", "title": "Cred Id" }, "description": "Credential ID to set permissions for" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/PermissionRule" }, "title": "Body" } } }, "description": "Array of permission rules to replace the entire agent rule list for this credential \u2014 each rule specifies effect (allow/deny), optional methods, optional path regex, and optional operation IDs" }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/PermissionRuleOut" }, "title": "Response Set Credential Permissions Toolkits Toolkit Id Credentials Cred Id Permissions Put" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] }, "patch": { "tags": ["toolkits", "toolkits"], "summary": "Add or remove individual permission rules for a specific credential", "description": "Incrementally update rules for this credential without replacing the full list.\n\n- `add`: rules appended (deduplicated)\n- `remove`: rules removed by exact match\n\nExample \u2014 unlock TTS writes for this credential:\n```json\n{\"add\": [{\"effect\": \"allow\", \"methods\": [\"POST\"], \"path\": \"text-to-speech\"}]}\n```", "operationId": "patch_credential_permissions_toolkits__toolkit_id__credentials__cred_id__permissions_patch", "parameters": [ { "name": "toolkit_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Toolkit ID", "title": "Toolkit Id" }, "description": "Toolkit ID" }, { "name": "cred_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Credential ID to patch permissions for", "title": "Cred Id" }, "description": "Credential ID to patch permissions for" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PermissionsPatch" } } }, "description": "Incremental update: arrays of rules to add and/or remove from this credential's policy \u2014 rules are matched by exact equality for removal" }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/PermissionRuleOut" }, "title": "Response Patch Credential Permissions Toolkits Toolkit Id Credentials Cred Id Permissions Patch" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "HumanLogin": [] } ] } }, "/traces": { "get": { "tags": ["observe"], "summary": "List execution traces \u2014 audit recent broker and workflow calls", "description": "Returns recent execution traces with status, capability id, toolkit, timestamp, and HTTP status. Use GET /traces/{trace_id} for step-level detail.", "operationId": "list_traces_traces_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 500, "minimum": 1, "description": "Maximum number of traces to return (1-500)", "default": 20, "title": "Limit" }, "description": "Maximum number of traces to return (1-500)" }, { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "description": "Number of traces to skip for pagination", "default": 0, "title": "Offset" }, "description": "Number of traces to skip for pagination" }, { "name": "toolkit_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by toolkit id (exact match)", "title": "Toolkit Id" }, "description": "Filter by toolkit id (exact match)" }, { "name": "agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by agent client_id (exact match). Admin-only signal.", "title": "Agent Id" }, "description": "Filter by agent client_id (exact match). Admin-only signal." }, { "name": "api_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by upstream API. Exact match against the `api_id` column on executions, which is the catalog-form `apis.id` (e.g. `stripe.com`, `github.com`). Indexed; use this in preference to scanning `operation_id` substrings.", "title": "Api Id" }, "description": "Filter by upstream API. Exact match against the `api_id` column on executions, which is the catalog-form `apis.id` (e.g. `stripe.com`, `github.com`). Indexed; use this in preference to scanning `operation_id` substrings." }, { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by trace status (`success` | `failed` | `pending`)", "title": "Status" }, "description": "Filter by trace status (`success` | `failed` | `pending`)" }, { "name": "since", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "number", "minimum": 0 }, { "type": "null" } ], "description": "Lower bound on `created_at` (unix seconds, inclusive)", "title": "Since" }, "description": "Lower bound on `created_at` (unix seconds, inclusive)" }, { "name": "until", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "number", "minimum": 0 }, { "type": "null" } ], "description": "Upper bound on `created_at` (unix seconds, exclusive)", "title": "Until" }, "description": "Upper bound on `created_at` (unix seconds, exclusive)" }, { "name": "capability_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by exact capability id. Matches `operation_id` for broker calls or `workflow_id` for workflow runs.", "title": "Capability Id" }, "description": "Filter by exact capability id. Matches `operation_id` for broker calls or `workflow_id` for workflow runs." }, { "name": "q", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string", "minLength": 1, "maxLength": 200 }, { "type": "null" } ], "description": "Free-text substring match (case-insensitive) over the columns the Monitor row renders: `operation_id`, `workflow_id`, `api_id`, `agent_id`. Empty/whitespace strings are treated as not set so the no-filter plan stays cheap. Note: none of these columns are indexed for prefix lookups, so `q` always implies a scan over the rows the tenant + time-window clauses already select \u2014 fine for the Monitor page (range capped to 24h by default) but don't use it as a general-purpose search.", "title": "Q" }, "description": "Free-text substring match (case-insensitive) over the columns the Monitor row renders: `operation_id`, `workflow_id`, `api_id`, `agent_id`. Empty/whitespace strings are treated as not set so the no-filter plan stays cheap. Note: none of these columns are indexed for prefix lookups, so `q` always implies a scan over the rows the tenant + time-window clauses already select \u2014 fine for the Monitor page (range capped to 24h by default) but don't use it as a general-purpose search." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TraceListPage" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use when you need to audit recent API calls or workflow executions, review execution history, or debug issues by inspecting recent traces. Returns paginated list of traces with status, HTTP codes, and timing. Use ?limit= and ?offset= for pagination.", "prerequisites": ["Requires authentication (toolkit key or human session)"], "avoid_when": "Do not use if you already have a specific trace ID from a broker call (X-Jentic-Execution-Id header) \u2014 use GET /traces/{id} directly instead.", "related_operations": [ "GET /traces/{id} \u2014 get full trace with step-by-step detail", "GET /{target} (broker) \u2014 returns X-Jentic-Execution-Id header pointing to trace", "POST /workflows/{slug} \u2014 workflow execution returns trace_id in response body" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/traces/usage": { "get": { "tags": ["observe"], "summary": "Trace usage aggregations \u2014 bucketed counts and top groups", "description": "Aggregate execution traces in a time window for monitoring dashboards.\n\nThe endpoint serves three pieces of information in one round-trip:\n\n1. `stats` \u2014 totals, success/failed split, mean and p50/p95 latency, and a\n point-in-time count of in-flight async jobs. Powers the HealthStrip.\n2. `buckets` \u2014 equally-sized time slices for stacking success/failed bar\n charts. Bucket width is chosen by the server based on the window:\n windows \u2264 1h use 60s buckets, \u2264 24h use 1h buckets, anything bigger\n uses 1d buckets. We never return more than ~144 buckets.\n3. `top` \u2014 the top N groups (toolkits, agents or API hosts) by trace count.\n\nAll filters compose with AND semantics on top of the tenant scope.", "operationId": "get_usage_traces_usage_get", "parameters": [ { "name": "since", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "number", "minimum": 0 }, { "type": "null" } ], "description": "Window start (unix seconds, inclusive). Defaults to 24h ago.", "title": "Since" }, "description": "Window start (unix seconds, inclusive). Defaults to 24h ago." }, { "name": "until", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "number", "minimum": 0 }, { "type": "null" } ], "description": "Window end (unix seconds, exclusive). Defaults to now.", "title": "Until" }, "description": "Window end (unix seconds, exclusive). Defaults to now." }, { "name": "group_by", "in": "query", "required": false, "schema": { "type": "string", "description": "What to group the `top` list by: 'toolkit' | 'api' | 'agent'.", "default": "toolkit", "title": "Group By" }, "description": "What to group the `top` list by: 'toolkit' | 'api' | 'agent'." }, { "name": "top_limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 50, "minimum": 1, "description": "Maximum rows in `top` list (1\u201350)", "default": 10, "title": "Top Limit" }, "description": "Maximum rows in `top` list (1\u201350)" }, { "name": "toolkit_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to one toolkit before aggregating", "title": "Toolkit Id" }, "description": "Filter to one toolkit before aggregating" }, { "name": "agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to one agent before aggregating", "title": "Agent Id" }, "description": "Filter to one agent before aggregating" }, { "name": "api_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by upstream API. Exact match against the indexed `api_id` column on executions (catalog-form `apis.id`, e.g. `stripe.com`). Same semantics as `/traces?api_id=`.", "title": "Api Id" }, "description": "Filter by upstream API. Exact match against the indexed `api_id` column on executions (catalog-form `apis.id`, e.g. `stripe.com`). Same semantics as `/traces?api_id=`." }, { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter to a single status before aggregating", "title": "Status" }, "description": "Filter to a single status before aggregating" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UsageResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use when an operator UI needs aggregate signals (totals, success rate, latency, recent activity over time) instead of paginating raw traces. Mirrors the data shown on the Monitor page's HealthStrip and bar chart. Returns a single window summary, equally-sized time buckets, and the top groups by toolkit, API host, or agent.", "prerequisites": ["Requires authentication (toolkit key or human session)"], "avoid_when": "Do not use for individual trace lookup \u2014 use GET /traces or GET /traces/{id}. Do not use for raw timeline data \u2014 bucket widths are chosen by the server (1 minute to 1 day depending on window length).", "related_operations": [ "GET /traces \u2014 list raw traces with the same filter set", "GET /jobs?status=running \u2014 count of in-flight async jobs" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/traces/{trace_id}": { "get": { "tags": ["observe"], "summary": "Get trace detail \u2014 step-by-step execution log", "description": "Returns the full execution trace with all steps: capability called, inputs, outputs, HTTP status, and timing. Useful for debugging failed workflow steps.", "operationId": "get_trace_traces__trace_id__get", "parameters": [ { "name": "trace_id", "in": "path", "required": true, "schema": { "type": "string", "description": "Trace ID (format: exec_{12chars})", "title": "Trace Id" }, "description": "Trace ID (format: exec_{12chars})" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TraceOut" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use after executing a broker call or workflow to retrieve the full execution trace with step-by-step details. Essential for debugging workflow failures \u2014 shows which step failed, what inputs were used, and what error was returned. Trace ID comes from X-Jentic-Execution-Id response header (broker calls) or trace_id in response body (workflows).", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid trace ID from a previous execution (format: exec_{12chars})" ], "avoid_when": "Do not use for browsing recent traces \u2014 use GET /traces with pagination instead.", "related_operations": [ "GET /traces \u2014 list recent traces when you don't have a specific trace ID yet", "GET /{target} (broker) \u2014 execution returns X-Jentic-Execution-Id header", "POST /workflows/{slug} \u2014 workflow execution returns trace_id field" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/user/create": { "post": { "tags": ["user"], "summary": "Create the root admin account (one-time setup)", "description": "Create the single root account for this instance.\n\nThis endpoint is available **once only**. After the first call it returns\n`410 Gone`. There is no multi-user system \u2014 one human owns this instance.\n\nRequires `bcrypt` installed (bundled in Docker image).", "operationId": "create_user_user_create_post", "requestBody": { "description": "Account credentials: username (trimmed of whitespace) and password (stored as bcrypt hash) for the root admin", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserCreate" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [] } }, "/user/login": { "post": { "tags": ["user"], "summary": "Log in and receive a session cookie", "description": "Authenticate with username and password.\n\nAccepts JSON body (`{\"username\": ..., \"password\": ...}`) or HTML form data.\nReturns an httpOnly JWT session cookie valid for 30 days (sliding window).\n\nPass `?redirect_to=/docs` to redirect after a successful browser form login.", "operationId": "login_user_login_post", "parameters": [ { "name": "redirect_to", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Redirect URL after successful login (relative path only)", "title": "Redirect To" }, "description": "Redirect URL after successful login (relative path only)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "requestBody": { "description": "Login credentials: username and password for the root admin account", "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["username", "password"], "properties": { "username": { "type": "string", "example": "admin" }, "password": { "type": "string", "format": "password" } } } } } }, "security": [] } }, "/user/logout": { "post": { "tags": ["user"], "summary": "Log out \u2014 clear the session cookie", "description": "Terminate the current human session.\n\nClears the `jentic_session` httpOnly cookie if present. If you authenticated\nvia Bearer token (Swagger UI OAuth2 flow), discard the token on your end \u2014\nthere is no server-side token store to invalidate.", "operationId": "logout_user_logout_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } }, "security": [ { "HumanLogin": [] } ] } }, "/user/me": { "get": { "tags": ["user"], "summary": "Check current session status", "description": "Returns current session info and authentication context.\n\nResponse varies based on authentication method:\n- Human session (JWT cookie): logged_in=true, includes username\n- Trusted subnet (no auth): logged_in=false, admin=true (note about logging in for named session)\n- Agent key (X-Jentic-API-Key): logged_in=false, agent_key=true, includes toolkit_id\n- No auth: logged_in=false, agent_key=false\n\nUseful for UI to determine what features to show and whether to require login.\nAgents can call this to confirm their key is valid and see which toolkit they belong to.\n\nThis endpoint accepts requests with or without authentication (open passthrough).", "operationId": "me_user_me_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserOut" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/user/token": { "post": { "tags": ["user"], "summary": "OAuth2 password grant \u2014 returns Bearer JWT", "description": "OAuth2 password grant endpoint.\n\nSwagger UI's **Authorize** dialog uses this automatically when you fill in\nthe *HumanLogin* username + password fields. Returns a Bearer JWT that\nSwagger UI injects as `Authorization: Bearer ...` on all subsequent calls.\n\nThis is functionally equivalent to `POST /user/login` but returns the token\nin the response body rather than as a cookie \u2014 the standard OAuth2 pattern\nexpected by Swagger UI.", "operationId": "token_user_token_post", "requestBody": { "description": "OAuth2 password grant form: username, password, and grant_type='password' (form-urlencoded format)", "content": { "application/x-www-form-urlencoded": { "schema": { "$ref": "#/components/schemas/Body_token_user_token_post" } } }, "required": true }, "responses": { "200": { "description": "Access token for use in Authorization: Bearer header", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [] } }, "/version": { "get": { "tags": ["meta"], "summary": "Get Version", "description": "Returns current version and latest GitHub release (cached 6 h).\nSet JENTIC_TELEMETRY=off to disable the outbound GitHub check.", "operationId": "get_version_version_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/workflows": { "get": { "tags": ["catalog"], "summary": "List workflows \u2014 browse available multi-step Arazzo workflows", "description": "Returns registered workflows (source: local) plus available catalog workflow sources\n(source: catalog) \u2014 APIs in the Jentic public catalog that have associated workflows.\n\nCatalog entries show the API they belong to; add credentials to auto-import their workflows.\nUse ?source=local or ?source=catalog to filter. Default returns all.\n\nPass `page` + `limit` for a `{data, total, page, limit, total_pages}` envelope; omit\nboth to keep the original bare-list response (workspace tiles still work the old way).", "operationId": "list_workflows_workflows_get", "parameters": [ { "name": "page", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "minimum": 1 }, { "type": "null" } ], "description": "Page number (1-indexed). When supplied alongside `limit`, the response switches from a bare list to a `{data, total, page, limit, total_pages}` envelope. Default (omitted) returns the unpaginated list for backward compatibility with existing callers.", "title": "Page" }, "description": "Page number (1-indexed). When supplied alongside `limit`, the response switches from a bare list to a `{data, total, page, limit, total_pages}` envelope. Default (omitted) returns the unpaginated list for backward compatibility with existing callers." }, { "name": "limit", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer", "maximum": 100, "minimum": 1 }, { "type": "null" } ], "description": "Page size when paginating. Triggers the paginated envelope shape \u2014 see `page`. Omit both to keep the historical bare-list behaviour.", "title": "Limit" }, "description": "Page size when paginating. Triggers the paginated envelope shape \u2014 see `page`. Omit both to keep the historical bare-list behaviour." }, { "name": "q", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by name or API, e.g. \"stripe\" or \"oauth\"", "title": "Q" }, "description": "Filter by name or API, e.g. \"stripe\" or \"oauth\"" }, { "name": "source", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by source: \"local\" or \"catalog\"", "title": "Source" }, "description": "Filter by source: \"local\" or \"catalog\"" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use when you need to discover multi-step workflows or automated sequences. Lists both registered workflows (source: local) and available catalog workflow sources (source: catalog). Use ?q= to filter by name or API.", "prerequisites": ["Requires authentication (toolkit key or human session)"], "avoid_when": "Do not use if you already know the workflow slug \u2014 use GET /workflows/{slug} directly instead.", "related_operations": [ "GET /workflows/{slug} \u2014 get workflow definition and input schema", "POST /workflows/{slug} \u2014 execute a workflow via broker", "GET /search \u2014 search across operations and workflows by natural language intent", "GET /catalog \u2014 browse available APIs when you know workflows exist for a vendor" ] }, "security": [] } }, "/workflows/{slug}": { "get": { "tags": ["catalog"], "summary": "Get workflow definition \u2014 Arazzo spec and input schema", "description": "Returns the workflow definition with content negotiation:\n- application/json (default): workflow metadata with simplified step info\n- application/vnd.oai.workflows+json: raw Arazzo document as JSON\n- application/vnd.oai.workflows+yaml: raw Arazzo document as YAML\n- text/markdown: compact LLM-friendly summary with input schema and steps\n- text/html: human-readable HTML summary\nExecute via broker: POST /{jentic_host}/workflows/{slug}", "operationId": "get_workflow_workflows__slug__get", "parameters": [ { "name": "slug", "in": "path", "required": true, "schema": { "type": "string", "description": "Workflow slug (URL-safe identifier)", "title": "Slug" }, "description": "Workflow slug (URL-safe identifier)" } ], "responses": { "200": { "description": "Workflow definition \u2014 format controlled by Accept header.", "content": { "application/json": { "schema": { "type": "object", "description": "Workflow metadata (default)" } }, "application/vnd.oai.workflows+json": { "schema": { "type": "object", "description": "Raw Arazzo document as JSON" } }, "application/vnd.oai.workflows+yaml": { "schema": { "type": "string", "description": "Raw Arazzo document as YAML" } }, "text/markdown": { "schema": { "type": "string", "description": "LLM-friendly prose summary" } }, "text/html": { "schema": { "type": "string", "description": "Human-readable HTML visualiser" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use after finding a workflow via GET /workflows or GET /search to retrieve its full definition, input schema, and step sequence. Returns Arazzo spec with content negotiation (JSON, YAML, Markdown, HTML).", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Valid workflow slug (from GET /workflows or GET /search results)" ], "avoid_when": "Do not use to execute the workflow \u2014 use POST /workflows/{slug} via broker for execution.", "related_operations": [ "POST /workflows/{slug} \u2014 execute this workflow with inputs", "GET /inspect/{id} \u2014 get full capability details (use workflow capability ID format: POST/{host}/workflows/{slug})", "GET /workflows \u2014 list all workflows when you don't know the slug yet" ] }, "security": [] }, "delete": { "tags": ["catalog"], "summary": "Delete a workflow from the workspace", "description": "Permanently delete a workflow and its Arazzo file from the workspace.", "operationId": "delete_workflow_workflows__slug__delete", "parameters": [ { "name": "slug", "in": "path", "required": true, "schema": { "type": "string", "description": "Workflow slug to delete", "title": "Slug" }, "description": "Workflow slug to delete" } ], "responses": { "204": { "description": "Successful Response" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } }, "/{target}": { "get": { "tags": ["execute", "execute"], "summary": "Broker \u2014 proxy a call to any registered API with automatic credential injection", "description": "Routes any HTTP request to the upstream API, injecting credentials automatically.\n\nURL shape: `/{upstream_host}/{path}` \u2014 e.g. `/api.stripe.com/v1/customers`\n\nAll HTTP methods supported; Swagger UI shows GET as representative.\n\n**Headers:**\n- `X-Jentic-Simulate: true` \u2014 validate and preview the call without sending it\n- `X-Jentic-Credential: {alias}` \u2014 select a specific credential when multiple exist for an API\n- `X-Jentic-Service: {app_slug}` \u2014 select by service name (e.g. `google_calendar`, `gmail`) when multiple credentials share a host\n- `X-Jentic-Dry-Run: true` \u2014 alias for Simulate (deprecated)\n\nReturns upstream response verbatim plus `X-Jentic-Execution-Id` for trace correlation.", "operationId": "broker_get", "parameters": [ { "name": "target", "in": "path", "required": true, "schema": { "type": "string", "description": "Upstream API path (format: host.domain/path, e.g. api.github.com/repos)", "title": "Target" }, "description": "Upstream API path (format: host.domain/path, e.g. api.github.com/repos)" } ], "responses": { "200": { "description": "Upstream response proxied verbatim. Content-Type matches upstream.", "content": { "application/json": { "schema": {} }, "text/html": {}, "text/plain": {} } }, "202": { "description": "Async job created (RFC 7240). Poll via Location header or GET /jobs/{job_id}" }, "400": { "description": "Bad request (upstream or Jentic validation)" }, "401": { "description": "Missing or rejected credential" }, "403": { "description": "Policy denied or upstream forbidden" }, "404": { "description": "Upstream resource not found" }, "502": { "description": "Upstream unreachable" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } }, "x-agent-hints": { "when_to_use": "Use this after you've inspected an operation via GET /inspect/{id} and are ready to execute it. The broker automatically injects credentials from the toolkit's vault, enforces access policies, and traces all calls. URL format: /{upstream_host}/{path} (e.g., /api.stripe.com/v1/payment_intents). Supports all HTTP methods (GET, POST, PUT, PATCH, DELETE).", "prerequisites": [ "Requires authentication (toolkit key or human session)", "Requires registered API with credentials (use POST /credentials to add)", "Requires credential bound to toolkit (use POST /toolkits/{id}/credentials with {credential_id} in body)", "Toolkit credential must allow the operation (governed by access policy)" ], "avoid_when": "Do not use for workflows \u2014 use POST /workflows/{slug} instead. Do not use for Jentic internal endpoints \u2014 use direct paths like /apis, /search.", "related_operations": [ "GET /inspect/{id} \u2014 inspect operation before calling to see parameters and auth requirements", "GET /traces/{id} \u2014 view execution trace after broker call (use X-Jentic-Execution-Id header)", "GET /jobs/{id} \u2014 poll async job status when Prefer: wait=0 header is used", "POST /credentials \u2014 add credentials before calling", "POST /toolkits/{id}/credentials \u2014 bind credentials to toolkit (body: {credential_id})" ] }, "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] } } }, "components": { "schemas": { "AccessRequestBody": { "properties": { "type": { "type": "string", "enum": ["grant", "modify_permissions"], "title": "Type", "description": "`grant` \u2014 bind an upstream API credential to this toolkit. Requires `credential_id`; `rules` is optional (defaults to system safety rules only). `modify_permissions` \u2014 update permission rules on a credential already bound to this toolkit. Requires both `credential_id` and `rules`." }, "credential_id": { "type": "string", "title": "Credential Id", "description": "The upstream API credential to act on. Discover available IDs and labels via `GET /credentials` or `GET /credentials?api_id=`." }, "rules": { "items": { "$ref": "#/components/schemas/PermissionRule" }, "type": "array", "title": "Rules", "description": "Ordered list of permission rules. For `grant`, applied atomically when approved. For `modify_permissions`, replaces the current agent rules entirely. System safety rules (deny writes, deny sensitive paths) are always appended after these and cannot be removed.\n\nEach `PermissionRule` object \u2014 all fields except `effect` are optional and AND-combined:\n- `effect` *(required)*: `\"allow\"` or `\"deny\"`\n- `methods`: list of HTTP verbs to match, e.g. `[\"GET\", \"POST\"]` \u2014 omit to match all\n- `path`: Python regex matched against the **path component only** of the upstream URL (host and query string are excluded). Uses `re.search()` \u2014 **substring match by default**, case-insensitive. Use `^`/`$` to anchor. `|` is regex OR.\n - Unanchored: `\"issues\"` matches any path *containing* the word \u2014 often too broad\n - Prefix: `\"^/repos/myorg/myrepo/\"` \u2014 everything under that path\n - Exact: `\"^/v1/voices$\"` \u2014 only that specific endpoint\n - **Tip:** always anchor with `^` when generating allow rules to avoid unintended matches\n- `operations`: list of regexes matched against the operation ID\n\n**Examples:**\n```json\n[{\"effect\": \"allow\", \"methods\": [\"POST\"], \"path\": \"^/v1/text-to-speech$\"}]\n[{\"effect\": \"deny\", \"path\": \"admin|billing|pay\"}]\n[{\"effect\": \"allow\", \"operations\": [\"^get_voices$\", \"^tts\"]}]\n```", "default": [] }, "api_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Id", "description": "Optional. Shown in the human approval UI. Usually inferred automatically from the credential." }, "reason": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Reason", "description": "Explain to the human why access is needed. Shown in the approval UI." } }, "type": "object", "required": ["type", "credential_id"], "title": "AccessRequestBody", "description": "Body for POST /toolkits/{id}/access-requests.\n\n**`type=grant`** \u2014 bind an upstream API credential to this toolkit:\n```json\n{\n \"type\": \"grant\",\n \"credential_id\": \"api.elevenlabs.io\",\n \"rules\": [{\"effect\": \"allow\", \"methods\": [\"POST\"], \"path\": \"text-to-speech\"}],\n \"reason\": \"I need to generate audio\"\n}\n```\n\n**`type=modify_permissions`** \u2014 update rules on a credential already bound to this toolkit:\n```json\n{\n \"type\": \"modify_permissions\",\n \"credential_id\": \"api.elevenlabs.io\",\n \"rules\": [{\"effect\": \"allow\", \"methods\": [\"POST\"], \"path\": \"text-to-speech\"}],\n \"reason\": \"I need write access to TTS only\"\n}\n```", "examples": [ { "credential_id": "api.elevenlabs.io", "reason": "I need to generate audio narration", "rules": [ { "effect": "allow", "methods": ["POST"], "path": "text-to-speech" } ], "type": "grant" }, { "credential_id": "api.elevenlabs.io", "reason": "Requesting read access plus TTS writes", "rules": [ { "effect": "allow", "methods": ["GET"] }, { "effect": "allow", "methods": ["POST"], "path": "text-to-speech" } ], "type": "modify_permissions" } ] }, "AccessRequestOut": { "properties": { "id": { "type": "string", "title": "Id", "description": "Unique request ID (areq_xxxxxxxx)", "examples": ["areq_abc123xyz"] }, "toolkit_id": { "type": "string", "title": "Toolkit Id", "description": "The toolkit this request belongs to", "examples": ["default"] }, "type": { "type": "string", "enum": ["grant", "modify_permissions", "add_scope"], "title": "Type", "description": "`grant` \u2014 bind a new upstream API credential to this toolkit (and optionally set permission rules). `modify_permissions` \u2014 update the permission rules on a credential already bound to this toolkit. `add_scope` \u2014 legacy alias for `grant` (deprecated).", "examples": ["grant"] }, "payload": { "additionalProperties": true, "type": "object", "title": "Payload", "description": "Request-type-specific data. For `grant`: `{credential_id, rules?, api_id?}`. For `modify_permissions`: `{credential_id, rules}`.", "examples": [ { "credential_id": "api.github.com", "rules": [ { "effect": "allow", "methods": ["GET"] } ] } ] }, "status": { "type": "string", "enum": ["pending", "approved", "denied"], "title": "Status", "description": "Current approval state. Poll until `approved` or `denied`.", "examples": ["pending"] }, "reason": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Reason", "description": "Human-readable explanation from the agent", "examples": ["Need GitHub API access to list repository issues"] }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description", "description": "Auto-generated summary of what the agent is requesting", "examples": ["Grant access to api.github.com with GET permissions"] }, "approve_url": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Approve Url", "description": "URL for the human to review and approve/deny", "examples": ["http://localhost:8900/approve/areq_abc123xyz"] }, "created_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Created At", "description": "Unix timestamp when filed", "examples": [1672531200.0] }, "resolved_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Resolved At", "description": "Unix timestamp when approved or denied", "examples": [1672531500.0] }, "applied_effects": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Applied Effects", "description": "Side-effects applied on approval (credential bound, rules set, etc.)", "examples": [["Bound credential api.github.com to toolkit default"]] } }, "additionalProperties": true, "type": "object", "required": ["id", "toolkit_id", "type", "status"], "title": "AccessRequestOut", "description": "An access request filed by an agent and awaiting human approval.\n\nThe `payload` shape depends on `type`:\n\n**`grant`** \u2014 bind a new upstream credential to this toolkit (optionally with rules):\n```json\n{ \"type\": \"grant\", \"payload\": { \"credential_id\": \"api.github.com\", \"rules\": [...] }, \"reason\": \"...\" }\n```\n\n**`modify_permissions`** \u2014 update permission rules on an already-bound credential:\n```json\n{ \"type\": \"modify_permissions\", \"payload\": { \"credential_id\": \"api.github.com\", \"rules\": [...] }, \"reason\": \"...\" }\n```" }, "AccountUpdate": { "properties": { "label": { "type": "string", "minLength": 1, "title": "Label", "description": "New display label for this account" } }, "type": "object", "required": ["label"], "title": "AccountUpdate", "description": "Rename a connected OAuth account. Label is used in UI and credential binding displays." }, "ApiListPage": { "properties": { "page": { "type": "integer", "title": "Page", "description": "Current page number (1-indexed)", "examples": [1] }, "limit": { "type": "integer", "title": "Limit", "description": "Results per page", "examples": [50] }, "total": { "type": "integer", "title": "Total", "description": "Total number of items matching query", "examples": [247] }, "total_pages": { "type": "integer", "title": "Total Pages", "description": "Total pages available", "examples": [5] }, "has_more": { "type": "boolean", "title": "Has More", "description": "True if more pages exist after current page", "examples": [true] }, "data": { "items": { "$ref": "#/components/schemas/ApiOut" }, "type": "array", "title": "Data", "description": "Array of API records for this page" } }, "additionalProperties": true, "type": "object", "required": ["page", "limit", "total", "total_pages", "has_more", "data"], "title": "ApiListPage", "description": "Paginated list of API providers registered in the catalog." }, "ApiOut": { "properties": { "id": { "type": "string", "title": "Id", "description": "API ID (typically the base domain)", "examples": ["api.github.com"] }, "name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Name", "description": "Human-readable API name from spec info.title", "examples": ["GitHub REST API"] }, "vendor": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Vendor", "description": "API vendor or maintainer organization", "examples": ["GitHub"] }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description", "description": "API description from spec info.description", "examples": [ "GitHub's REST API for managing repositories, issues, and pull requests" ] }, "base_url": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Base Url", "description": "Primary base URL from spec servers array", "examples": ["https://api.github.com"] }, "created_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Created At", "description": "Unix timestamp when API was imported", "examples": [1672531200.0] } }, "additionalProperties": true, "type": "object", "required": ["id"], "title": "ApiOut", "description": "API provider metadata including ID, name, vendor, and base URL." }, "Body_oauth_revoke_oauth_revoke_post": { "properties": { "token": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Token" }, "token_type_hint": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Token Type Hint" } }, "type": "object", "title": "Body_oauth_revoke_oauth_revoke_post" }, "Body_oauth_token_oauth_token_post": { "properties": { "grant_type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Grant Type" }, "assertion": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Assertion" }, "refresh_token": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Refresh Token" } }, "type": "object", "title": "Body_oauth_token_oauth_token_post" }, "Body_token_user_token_post": { "properties": { "grant_type": { "anyOf": [ { "type": "string", "pattern": "^password$" }, { "type": "null" } ], "title": "Grant Type" }, "username": { "type": "string", "title": "Username" }, "password": { "type": "string", "format": "password", "title": "Password" }, "scope": { "type": "string", "title": "Scope", "default": "" }, "client_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Client Id" }, "client_secret": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "format": "password", "title": "Client Secret" } }, "type": "object", "required": ["username", "password"], "title": "Body_token_user_token_post" }, "ConnectLinkRequest": { "properties": { "app": { "type": "string", "title": "App", "description": "The Pipedream app slug to connect (e.g. `gmail`, `slack`, `github`, `stripe`). Required \u2014 Pipedream Connect Links must target a specific app. Find the slug via `GET /oauth-brokers/{id}/apps` or at pipedream.com/apps.", "examples": ["gmail", "slack", "github"] }, "label": { "type": "string", "minLength": 1, "title": "Label", "description": "A human-readable name for this connection, e.g. `work email` or `personal email`. Required because Pipedream only returns the app name ('Gmail'), not the account address \u2014 without a label there is no way to distinguish multiple accounts for the same app. This label is carried through to the resulting credential in `GET /credentials` and used when provisioning the credential to a toolkit. Must be non-empty \u2014 no silent fallbacks to app slug or API ID.", "examples": ["work email", "personal email", "main Slack workspace"] }, "api_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Id", "description": "The Jentic catalog API ID this connection maps to (e.g. `googleapis.com/gmail`). If provided, this overrides the automatic slug-map lookup during sync \u2014 the credential will be registered under exactly this API ID. Find the right ID via `GET /catalog?q=`. If omitted, the slug map is used as a fallback (may not match the catalog ID).", "examples": ["googleapis.com/gmail", "slack.com/api", "api.github.com"] } }, "type": "object", "required": ["app", "label"], "title": "ConnectLinkRequest", "description": "Generate a Pipedream Connect Link for authorizing a new OAuth account. Returns URL for user authorization." }, "CredentialBindingOut": { "properties": { "credential_id": { "type": "string", "title": "Credential Id", "description": "Credential ID (format: cred_{12chars})", "examples": ["cred_abc123xyz"] }, "label": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Label", "description": "User-assigned credential label", "examples": ["GitHub PAT for jentic-mini"] }, "api_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Id", "description": "API ID this credential is for", "examples": ["api.github.com"] }, "auth_type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Auth Type", "description": "Auth scheme type: bearer, basic, apiKey, oauth2, etc", "examples": ["bearer"] } }, "additionalProperties": true, "type": "object", "required": ["credential_id"], "title": "CredentialBindingOut", "description": "Credential bound to a toolkit with access control rules. Includes label and API binding info." }, "CredentialCreate": { "properties": { "label": { "type": "string", "title": "Label" }, "value": { "type": "string", "title": "Value", "default": "" }, "identity": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Identity" }, "api_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Id" }, "server_variables": { "anyOf": [ { "additionalProperties": { "type": "string" }, "type": "object" }, { "type": "null" } ], "title": "Server Variables" }, "auth_type": { "anyOf": [ { "type": "string", "enum": ["bearer", "basic", "apiKey", "none"] }, { "type": "null" } ], "title": "Auth Type", "description": "How this credential maps to the upstream API's authentication scheme. The broker uses this to find the right security scheme in the spec \u2014 it resolves by type, not by the bespoke scheme name in the overlay.\n\n| Value | Injects as | When to use |\n|---|---|---|\n| `bearer` | `Authorization: Bearer {value}` | REST APIs, OAuth access tokens, JWTs. GitHub REST API, Deepgram, Slack, etc. |\n| `basic` | `Authorization: Basic base64({identity??'token'}:{value})` | HTTP Basic auth, git-over-HTTPS. Set `identity` to the username; omit for GitHub PATs (any username accepted). |\n| `apiKey` | Custom header or query param `= {value}` | API key in a named header (X-API-Key, Api-Key, X-Auth-Key, etc.). For **compound** schemes (e.g. Discourse Api-Key + Api-Username) where the overlay uses canonical `Secret`/`Identity` scheme names, set `identity` to the username/account \u2014 a single credential covers both headers. |\n| `none` | *(nothing injected)* | No-auth APIs where the credential exists only to carry `server_variables` for routing. |", "examples": ["bearer"] }, "scheme": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Scheme", "description": "Self-describing injection rule. When set, the broker injects the credential directly from this blob without looking up the API spec or overlay at runtime. Format: {\"in\": \"header\", \"name\": \"Authorization\", \"prefix\": \"Bearer \"} or {\"in\": \"header\", \"name\": \"X-Api-Key\"}. Supports encode=base64 for Basic auth: {\"in\": \"header\", \"name\": \"Authorization\", \"prefix\": \"Basic \", \"encode\": \"base64\"}. For compound schemes: {\"secret\": {\"in\": \"header\", ...}, \"identity\": {\"in\": \"header\", ...}}." }, "routes": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Routes", "description": "Hostnames or host+path patterns this credential should be injected into. Each entry is stored as (host, path_prefix) in credential_routes. Example: [\"github.com\", \"api.github.com\"]. " } }, "type": "object", "required": ["label"], "title": "CredentialCreate" }, "CredentialOut": { "properties": { "id": { "type": "string", "title": "Id" }, "label": { "type": "string", "title": "Label" }, "identity": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Identity" }, "api_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Id" }, "auth_type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Auth Type" }, "server_variables": { "anyOf": [ { "additionalProperties": { "type": "string" }, "type": "object" }, { "type": "null" } ], "title": "Server Variables" }, "scheme": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Scheme" }, "routes": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Routes" }, "created_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Created At" }, "updated_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Updated At" }, "account_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Account Id" }, "app_slug": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "App Slug" }, "synced_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Synced At" } }, "type": "object", "required": ["id", "label"], "title": "CredentialOut", "description": "Upstream API credential metadata. Secret values are never returned after creation." }, "CredentialPatch": { "properties": { "label": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Label" }, "value": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Value" }, "identity": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Identity" }, "api_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Id" }, "auth_type": { "anyOf": [ { "type": "string", "enum": ["bearer", "basic", "apiKey", "none"] }, { "type": "null" } ], "title": "Auth Type", "description": "Update the auth type for this credential. See `POST /credentials` for valid values and semantics." }, "server_variables": { "anyOf": [ { "additionalProperties": { "type": "string" }, "type": "object" }, { "type": "null" } ], "title": "Server Variables" }, "scheme": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Scheme", "description": "Update the self-describing injection rule. See POST /credentials for format." }, "routes": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Routes", "description": "Update the host+path routing patterns for this credential." } }, "type": "object", "title": "CredentialPatch" }, "GrantBody": { "properties": { "toolkit_id": { "type": "string", "title": "Toolkit Id", "description": "Toolkit to grant this agent" } }, "type": "object", "required": ["toolkit_id"], "title": "GrantBody" }, "GrantsReplaceBody": { "properties": { "toolkit_ids": { "items": { "type": "string" }, "type": "array", "title": "Toolkit Ids", "description": "The complete set of toolkit_ids the agent should be granted after this call. Existing grants not in this list will be revoked. Toolkits in this list that the agent does not yet have a grant on will be added. Atomic: either all changes apply or none do." } }, "type": "object", "required": ["toolkit_ids"], "title": "GrantsReplaceBody" }, "HTTPErrorDetail": { "properties": { "detail": { "type": "string", "title": "Detail" } }, "type": "object", "required": ["detail"], "title": "HTTPErrorDetail", "description": "Standard FastAPI HTTPException body \u2014 ``{\"detail\": \"...\"}``." }, "HTTPValidationError": { "properties": { "detail": { "items": { "$ref": "#/components/schemas/ValidationError" }, "type": "array", "title": "Detail" } }, "type": "object", "title": "HTTPValidationError" }, "HealthOk": { "properties": { "status": { "type": "string", "const": "ok", "title": "Status", "description": "Instance is operational" }, "version": { "type": "string", "title": "Version" }, "apis_registered": { "type": "integer", "minimum": 0.0, "title": "Apis Registered" } }, "type": "object", "required": ["status", "version", "apis_registered"], "title": "HealthOk", "description": "Health response when the instance is fully set up." }, "HealthSetupRequired": { "properties": { "status": { "type": "string", "const": "setup_required", "title": "Status", "description": "Bootstrap state \u2014 no admin account exists" }, "account_created": { "type": "boolean", "const": false, "title": "Account Created" }, "message": { "type": "string", "title": "Message" }, "next_step": { "type": "string", "title": "Next Step" }, "setup_url": { "type": "string", "title": "Setup Url", "description": "Human-facing URL to create the admin account" }, "oauth_authorization_server_metadata": { "type": "string", "title": "Oauth Authorization Server Metadata", "description": "Discovery document URL for agent DCR (RFC 8414)" }, "registration_endpoint": { "type": "string", "title": "Registration Endpoint" }, "token_endpoint": { "type": "string", "title": "Token Endpoint" }, "version": { "type": "string", "title": "Version" } }, "type": "object", "required": [ "status", "account_created", "message", "next_step", "setup_url", "oauth_authorization_server_metadata", "registration_endpoint", "token_endpoint", "version" ], "title": "HealthSetupRequired", "description": "Health response when no admin account exists yet.\n\nCarries the URLs an agent or human needs to bootstrap: the OAuth metadata\ndocument for agent DCR, the canonical token / registration endpoints, and\nthe human-facing setup_url for admin-account creation." }, "ImportOut": { "properties": { "status": { "type": "string", "title": "Status", "description": "Import status: 'ok' if all sources succeeded, 'partial' if some failed, 'failed' if all failed", "examples": ["imported"] }, "id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Id", "description": "Registered API ID (for OpenAPI specs) or workflow slug (for Arazzo)", "examples": ["api.github.com"] }, "name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Name", "description": "Display name extracted from spec (info.title for APIs, workflow.summary for workflows)", "examples": ["GitHub REST API"] }, "operations_indexed": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Operations Indexed", "description": "Number of operations parsed and indexed in BM25 (OpenAPI specs only)", "examples": [247] }, "type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Type", "description": "Import type: 'api' for OpenAPI specs, 'workflow' for Arazzo documents", "examples": ["api"] } }, "additionalProperties": true, "type": "object", "required": ["status"], "title": "ImportOut", "description": "Result of importing an OpenAPI spec or Arazzo workflow into the catalog.\n\nThe import endpoint (POST /import) accepts specs from URLs, local file paths, or\ninline content. It parses the document, indexes operations/workflows in BM25,\nand stores metadata for broker execution. Returns the registered ID and count\nof indexed operations." }, "ImportRequest": { "properties": { "sources": { "items": { "$ref": "#/components/schemas/ImportSource" }, "type": "array", "title": "Sources", "description": "Array of import sources (OpenAPI specs or Arazzo workflows) to register in the catalog" } }, "type": "object", "required": ["sources"], "title": "ImportRequest", "description": "Batch import request for multiple OpenAPI specs or Arazzo workflows. Sources processed in parallel." }, "ImportSource": { "properties": { "type": { "type": "string", "title": "Type", "description": "Source type: 'path' (local file), 'url' (fetch from URL), or 'inline' (spec content in request)" }, "path": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Path", "description": "Local file system path (required if type='path')" }, "url": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Url", "description": "Remote spec URL (required if type='url')", "examples": ["https://api.example.com/openapi.json"] }, "filename": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Filename", "description": "Override filename for saved spec (optional)", "examples": ["my-api.json"] }, "content": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Content", "description": "Inline spec content as JSON or YAML string (required if type='inline')" }, "force_api_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Force Api Id", "description": "Override derived API ID with catalog canonical ID (optional)", "examples": ["github"] } }, "type": "object", "required": ["type"], "title": "ImportSource", "description": "Single import source for an OpenAPI spec or Arazzo workflow. Can be local file, URL, or inline content." }, "JobListPage": { "properties": { "page": { "type": "integer", "title": "Page", "description": "Current page number (1-indexed)", "examples": [1] }, "limit": { "type": "integer", "title": "Limit", "description": "Results per page", "examples": [50] }, "total": { "type": "integer", "title": "Total", "description": "Total number of items matching query", "examples": [247] }, "total_pages": { "type": "integer", "title": "Total Pages", "description": "Total pages available", "examples": [5] }, "has_more": { "type": "boolean", "title": "Has More", "description": "True if more pages exist after current page", "examples": [true] }, "data": { "items": { "$ref": "#/components/schemas/JobOut" }, "type": "array", "title": "Data", "description": "Array of job records for this page" } }, "additionalProperties": true, "type": "object", "required": ["page", "limit", "total", "total_pages", "has_more", "data"], "title": "JobListPage", "description": "Paginated list of async job handles with status, capability, and timing info." }, "JobOut": { "properties": { "job_id": { "type": "string", "title": "Job Id", "description": "Job ID (format: job_{12chars})", "examples": ["job_abc123xyz"] }, "kind": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Kind", "description": "Job type: 'workflow' or 'broker'", "examples": ["workflow"] }, "capability": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Capability", "description": "Workflow slug or capability ID (the broker operation id or arazzo workflow slug this job runs)", "examples": ["github-create-issue"] }, "toolkit_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Toolkit Id", "description": "Toolkit that initiated this job", "examples": ["default"] }, "agent_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Agent Id", "description": "Agent client_id when the job was created via an agent access token (at_\u2026). Null for toolkit-key callers and admin-initiated jobs.", "examples": ["agnt_abc123"] }, "status": { "type": "string", "title": "Status", "description": "Job status: pending, running, complete, failed, or upstream_async", "examples": ["complete"] }, "result": { "title": "Result", "description": "Job result (only present when status is complete or upstream_async)", "examples": [ { "issue_number": 42, "url": "https://github.com/jentic/jentic-mini/issues/42" } ] }, "error": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Error", "description": "Error message (only present when status is failed)", "examples": [null] }, "http_status": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Http Status", "description": "HTTP status code from upstream API", "examples": [201] }, "upstream_async": { "type": "boolean", "title": "Upstream Async", "description": "True if upstream API itself returned 202 (async)", "default": false, "examples": [false] }, "upstream_job_url": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Upstream Job Url", "description": "Upstream job polling URL (when upstream_async is true)", "examples": [null] }, "trace_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Trace Id", "description": "Execution trace ID for this job", "examples": ["trace_xyz789"] }, "parent_trace_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Parent Trace Id", "description": "Parent workflow trace this job's trace is a child step of. Mirrored from `executions.parent_trace_id` so a child broker job (e.g. an async wait=0 hop spawned inside an arazzo workflow) can render \"part of workflow X\" in the Job drawer without a second fetch. Null for top-level jobs.", "examples": ["exec_abc123xyz"] }, "created_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Created At", "description": "Unix timestamp when job was created", "examples": [1672531200.0] }, "completed_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Completed At", "description": "Unix timestamp when job finished", "examples": [1672531205.0] } }, "additionalProperties": true, "type": "object", "required": ["job_id", "status"], "title": "JobOut", "description": "Async job handle for operations that couldn't complete synchronously. Poll for status and result." }, "KeyCreate": { "properties": { "label": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Label", "description": "Human-readable label, e.g. 'Agent A', 'Staging bot'" }, "allowed_ips": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Allowed Ips", "description": "IP allowlist for this key only. NULL = unrestricted." } }, "type": "object", "title": "KeyCreate", "description": "Create a new API key for this toolkit. The full key value is only returned once at creation time." }, "NoteCreate": { "properties": { "resource": { "type": "string", "title": "Resource", "description": "Resource identifier: operation_id (METHOD/host/path), api_id, or workflow slug" }, "type": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Type", "description": "Note category: 'auth_quirk', 'usage_hint', 'execution_feedback', or 'correction'" }, "note": { "type": "string", "title": "Note", "description": "Note content \u2014 be specific and actionable" }, "execution_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Execution Id", "description": "Link to specific execution for context (optional)" }, "confidence": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Confidence", "description": "Confidence level: 'observed', 'suspected', or 'verified'" }, "source": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Source", "description": "Observation source, e.g. 'test run', 'production', 'documentation'" } }, "type": "object", "required": ["resource", "note"], "title": "NoteCreate", "description": "Create a note on any Jentic resource for knowledge accumulation and catalog improvement." }, "OAuthBrokerCreate": { "properties": { "id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Id", "description": "Optional custom broker ID. Auto-generated from type if omitted." }, "type": { "type": "string", "title": "Type", "description": "Broker backend type. Currently supported: `pipedream`." }, "config": { "additionalProperties": true, "type": "object", "title": "Config", "description": "Provider-specific configuration. For `pipedream`: `client_id`, `client_secret`, `project_id` (all from Pipedream workspace \u2192 API settings \u2192 OAuth clients). Optional: `environment` (`production` or `development`, default `production`), `support_email`, `default_external_user_id` (user identity for initial account sync, default `\"default\"`).", "examples": [ { "client_id": "oa_abc123", "client_secret": "pd_secret_xxxx", "project_id": "proj_abc123", "support_email": "support@example.com" } ] } }, "type": "object", "required": ["type", "config"], "title": "OAuthBrokerCreate", "description": "Register a new OAuth broker for delegated credential management via Pipedream or other providers.", "example": { "config": { "client_id": "oa_abc123", "client_secret": "pd_secret_xxxx", "project_id": "proj_abc123", "support_email": "support@example.com" }, "type": "pipedream" } }, "OAuthBrokerOut": { "properties": { "id": { "type": "string", "title": "Id", "description": "Broker ID (format: broker_{12chars})", "examples": ["broker_abc123xyz"] }, "type": { "type": "string", "title": "Type", "description": "Broker type: 'pipedream' or other provider", "examples": ["pipedream"] }, "config": { "additionalProperties": true, "type": "object", "title": "Config", "description": "Public broker configuration (excludes encrypted secret fields)" }, "created_at": { "type": "number", "title": "Created At", "description": "Unix timestamp when broker was registered", "examples": [1609459200] }, "accounts_discovered": { "type": "integer", "title": "Accounts Discovered", "description": "Number of OAuth accounts discovered from this broker", "default": 0, "examples": [3] } }, "type": "object", "required": ["id", "type", "config", "created_at"], "title": "OAuthBrokerOut", "description": "OAuth broker configuration with discovered accounts count. Config excludes sensitive fields." }, "OAuthBrokerUpdate": { "properties": { "config": { "additionalProperties": true, "type": "object", "title": "Config", "description": "Updated provider-specific configuration. For `pipedream`: `client_id`, `client_secret`, `project_id` are all accepted. Fields not supplied are left unchanged. `client_secret` is write-only \u2014 Fernet-encrypted at rest, never returned.", "examples": [ { "client_id": "oa_abc123", "client_secret": "pd_secret_xxxx", "project_id": "proj_abc123", "support_email": "support@example.com" } ] } }, "type": "object", "required": ["config"], "title": "OAuthBrokerUpdate", "description": "Update OAuth broker configuration. Only provided fields are changed; secrets remain encrypted." }, "OAuthError": { "properties": { "error": { "type": "string", "title": "Error", "description": "OAuth error code (e.g. 'invalid_grant')." }, "error_description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Error Description", "description": "Human-readable description; safe to log, not safe to display." } }, "type": "object", "required": ["error"], "title": "OAuthError", "description": "RFC 6749 \u00a75.2 / RFC 7591 \u00a73.2.2 error response body.\n\nOAuth routes intentionally bypass FastAPI's HTTPException \u2192 ``{\"detail\": ...}``\nconvention so the wire shape matches the spec." }, "OperationListPage": { "properties": { "page": { "type": "integer", "title": "Page", "description": "Current page number (1-indexed)", "examples": [1] }, "limit": { "type": "integer", "title": "Limit", "description": "Results per page", "examples": [50] }, "total": { "type": "integer", "title": "Total", "description": "Total number of items matching query", "examples": [247] }, "total_pages": { "type": "integer", "title": "Total Pages", "description": "Total pages available", "examples": [5] }, "has_more": { "type": "boolean", "title": "Has More", "description": "True if more pages exist after current page", "examples": [true] }, "data": { "items": { "$ref": "#/components/schemas/OperationOut" }, "type": "array", "title": "Data", "description": "Array of operation records for this page" } }, "additionalProperties": true, "type": "object", "required": ["page", "limit", "total", "total_pages", "has_more", "data"], "title": "OperationListPage", "description": "Paginated list of API operations with method, path, and summary." }, "OperationOut": { "properties": { "id": { "type": "string", "title": "Id", "description": "Capability ID in METHOD/host/path format", "examples": ["GET/api.github.com/repos/{owner}/{repo}/issues"] }, "summary": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Summary", "description": "Short description of what this operation does", "examples": ["List repository issues"] }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description", "description": "Detailed description from the OpenAPI spec", "examples": [ "List issues in a repository. Only issues assigned to the authenticated user are returned." ] } }, "additionalProperties": true, "type": "object", "required": ["id"], "title": "OperationOut", "description": "A single API operation. id encodes method/host/path (capability ID format)." }, "OverlaySubmit": { "properties": { "overlay": { "additionalProperties": true, "type": "object", "title": "Overlay", "description": "Full OpenAPI Overlay 1.0 document as a JSON object. Use this to patch the stored spec for any API \u2014 security schemes, base URL corrections, operation metadata, extra extensions, etc.\n\n**Structure:**\n```json\n{\n \"overlay\": \"1.0.0\",\n \"info\": {\"title\": \"\", \"version\": \"1.0.0\"},\n \"actions\": [\n {\n \"target\": \"\",\n \"update\": { }\n }\n ]\n}\n```\n\n**Common targets:**\n- `\"$\"` \u2014 root of the spec (components, info, servers)\n- `\"$.paths[*][*]\"` \u2014 all operations (apply global security)\n- `\"$.paths./foo.get\"` \u2014 a specific operation\n\n**Security scheme example** (adding BearerAuth to an API):\n```json\n{\n \"overlay\": \"1.0.0\",\n \"info\": {\"title\": \"GitHub REST auth\", \"version\": \"1.0.0\"},\n \"actions\": [\n {\n \"target\": \"$\",\n \"update\": {\n \"components\": {\n \"securitySchemes\": {\n \"BearerAuth\": {\"type\": \"http\", \"scheme\": \"bearer\"}\n }\n }\n }\n },\n {\n \"target\": \"$.paths[*][*]\",\n \"update\": {\"security\": [{\"BearerAuth\": []}]}\n }\n ]\n}\n```\n\n**Compound apiKey schemes** (e.g. Discourse \u2014 two separate apiKey headers): name one scheme `Secret` (the primary key) and one `Identity` (the username/ID). The broker resolves these by canonical name without needing further annotation." }, "contributed_by": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Contributed By", "description": "Optional contributor identifier (username, agent ID, etc.) for tracking overlay source" } }, "type": "object", "required": ["overlay"], "title": "OverlaySubmit", "description": "Submit an OpenAPI Overlay 1.0 document to patch an API spec. Commonly used to add missing security schemes." }, "PermissionRule": { "properties": { "effect": { "type": "string", "enum": ["allow", "deny"], "title": "Effect", "description": "`\"allow\"` or `\"deny\"`" }, "methods": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Methods", "description": "HTTP methods to match, e.g. `[\"GET\", \"POST\"]`. Omit to match all methods." }, "path": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Path", "description": "Python regex matched with `re.search()` against the **path component only** of the upstream URL (no host, no query string). Matching is case-insensitive and substring by default \u2014 use `^`/`$` to anchor. `|` is regex OR. Example: `\"^/repos/jentic/jentic-mini/issues/[0-9]+/comments$\"` matches only that exact endpoint; omitting anchors would also match any path containing that substring." }, "operations": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Operations", "description": "List of regexes matched against the operation ID. E.g. `[\"tts\", \"speech\"]`." } }, "additionalProperties": false, "type": "object", "required": ["effect"], "title": "PermissionRule", "description": "A single access control rule. All fields are optional; conditions are AND-combined.\nFirst matching rule wins. Agent rules are evaluated before system safety rules.\n\n**`effect`** \u2014 `\"allow\"` or `\"deny\"` (required)\n\n**`methods`** \u2014 list of HTTP methods to match, e.g. `[\"GET\", \"POST\"]`.\nOmit to match all methods.\n\n**`path`** \u2014 Python regex matched against the **path component only** of the upstream\nrequest URL. The host and query string are never included. Matching uses `re.search()`\n(Python), which means:\n\n- It is always a **regex** \u2014 not a glob, not a prefix string.\n- It is **case-insensitive**.\n- It is a **substring match by default** \u2014 the pattern can match anywhere in the path\n unless you anchor it with `^` and/or `$`.\n- `|` is regex OR (matches either side).\n\n**Anchoring guide:**\n\n| Intent | Pattern | Matches | Does NOT match |\n|--------|---------|---------|----------------|\n| Substring (any path containing word) | `\"issues\"` | `/repos/x/issues`, `/v1/issues/7` | (nothing \u2014 too broad for deny rules) |\n| Prefix (everything under a path) | `\"^/repos/jentic/jentic-mini/\"` | `/repos/jentic/jentic-mini/issues/34` | `/repos/other/repo/issues` |\n| Exact endpoint | `\"^/v1/voices$\"` | `/v1/voices` | `/v1/voices/123` |\n| One endpoint + subresources | `\"^/repos/jentic/jentic-mini/issues/[0-9]+/comments$\"` | `/repos/jentic/jentic-mini/issues/34/comments` | `/repos/jentic/jentic-mini/issues` |\n| Block any sensitive word | `\"admin\\|billing\\|pay\"` | `/v1/admin/users`, `/billing/invoice` | n/a |\n\n**Tip for agents generating rules:** always anchor with `^` to avoid unintentionally\nmatching longer paths, and use `$` to prevent prefix over-permission. An unanchored\npattern like `\"comments\"` would also match `/v1/my-comments-service/admin`.\n\n**`operations`** \u2014 list of regexes matched against the operation ID via `re.search()`.\nE.g. `[\"tts\", \"speech\"]` matches any operation whose ID contains \"tts\" or \"speech\".\n\nSystem safety rules (always active, cannot be removed) are marked `_system: true` in\n`GET .../permissions` responses (see `PermissionRuleOut`). They deny sensitive paths\nand write methods by default. The `_system` and `_comment` fields are response-only\nand will be rejected in request bodies.\n\n**Examples:**\n```json\n{\"effect\": \"allow\", \"methods\": [\"POST\"], \"path\": \"^/v1/text-to-speech$\"}\n{\"effect\": \"allow\", \"methods\": [\"POST\"], \"path\": \"^/repos/jentic/jentic-mini/issues/[0-9]+/comments$\"}\n{\"effect\": \"allow\", \"methods\": [\"GET\", \"POST\"], \"path\": \"^/repos/jentic/jentic-mini/\"}\n{\"effect\": \"deny\", \"path\": \"admin|billing|pay\"}\n{\"effect\": \"allow\", \"operations\": [\"^github_get_repo$\"]}\n```", "examples": [ { "effect": "allow", "methods": ["POST"], "path": "text-to-speech" }, { "effect": "deny", "path": "admin|billing|pay" }, { "effect": "allow", "operations": ["^github_get_repo$"] } ] }, "PermissionRuleOut": { "properties": { "effect": { "type": "string", "enum": ["allow", "deny"], "title": "Effect", "description": "`\"allow\"` or `\"deny\"`" }, "methods": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Methods", "description": "HTTP methods to match, e.g. `[\"GET\", \"POST\"]`. Omit to match all methods." }, "path": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Path", "description": "Python regex matched with `re.search()` against the **path component only** of the upstream URL (no host, no query string). Matching is case-insensitive and substring by default \u2014 use `^`/`$` to anchor. `|` is regex OR. Example: `\"^/repos/jentic/jentic-mini/issues/[0-9]+/comments$\"` matches only that exact endpoint; omitting anchors would also match any path containing that substring." }, "operations": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Operations", "description": "List of regexes matched against the operation ID. E.g. `[\"tts\", \"speech\"]`." }, "_system": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "System", "description": "True if this is a system safety rule (cannot be removed)" }, "_comment": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Comment", "description": "Human-readable explanation of this rule's purpose (system rules only)" } }, "additionalProperties": true, "type": "object", "required": ["effect"], "title": "PermissionRuleOut", "description": "Permission rule as returned by the API \u2014 includes read-only server fields.", "examples": [ { "effect": "allow", "methods": ["POST"], "path": "text-to-speech" }, { "effect": "deny", "path": "admin|billing|pay" }, { "effect": "allow", "operations": ["^github_get_repo$"] } ] }, "PermissionsPatch": { "properties": { "add": { "items": { "$ref": "#/components/schemas/PermissionRule" }, "type": "array", "title": "Add", "description": "Rules to append (deduplicated by exact match)" }, "remove": { "items": { "$ref": "#/components/schemas/PermissionRule" }, "type": "array", "title": "Remove", "description": "Rules to remove by exact match" } }, "type": "object", "title": "PermissionsPatch", "description": "Body for PATCH .../permissions \u2014 incremental rule updates." }, "SearchResult": { "properties": { "type": { "type": "string", "title": "Type", "description": "Result type: 'operation' for API endpoints, 'workflow' for multi-step Arazzo workflows", "examples": ["operation"] }, "id": { "type": "string", "title": "Id", "description": "Capability ID in METHOD/host/path format", "examples": ["GET/api.github.com/repos/{owner}/{repo}/issues"] }, "slug": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Slug", "description": "Workflow slug (workflows only) \u2014 used as path segment in POST /workflows/{slug}", "examples": ["github-list-issues"] }, "summary": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Summary", "description": "Short description of what this capability does", "examples": ["List repository issues"] }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description", "description": "Detailed description from the OpenAPI operation or Arazzo workflow", "examples": ["List issues in a repository"] }, "score": { "type": "number", "title": "Score", "description": "BM25 relevance score (0.0-1.0) \u2014 higher is more relevant to the search query", "examples": [0.85] }, "involved_apis": { "items": { "type": "string" }, "type": "array", "title": "Involved Apis", "description": "List of upstream API hosts involved in this capability (for workflows, may list multiple)", "examples": [["api.github.com"]] }, "matched_on": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Matched On", "description": "Which fields the query matched against \u2014 at least one of `name`, `operation_summary`, `description`, `tag`. Computed via cheap substring checks post-rank; intentionally pragmatic rather than reflecting BM25's internal matched fields.", "examples": [["operation_summary"]] }, "match_snippet": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Match Snippet", "description": "Short text snippet (~80 chars) around the matched substring from the highest-priority field that matched (priority order: `name > operation_summary > description > tag`). The matched span is wrapped in `\\u0001` sentinel characters so the client can render its own highlight without an XSS-prone HTML payload. Null when the result was a BM25 hit without an exact substring match in any field.", "examples": [ "\u2026create a \u0001payment\u0001 intent on the Stripe\u2026" ] } }, "additionalProperties": true, "type": "object", "required": ["type", "id", "score"], "title": "SearchResult", "description": "A search result from the BM25 index \u2014 either an operation or workflow capability.\n\nThe BM25 search index covers both API operations (parsed from OpenAPI specs) and\nworkflows (parsed from Arazzo documents). Results are ranked by relevance score.\nUse GET /inspect/{id} to get the full schema for a result before calling it." }, "SyncRequest": { "properties": { "external_user_id": { "type": "string", "title": "External User Id", "description": "The user identity to sync accounts for. In a single-user setup this is always `default`. In multi-user deployments, pass the Jentic user ID that was used when the user completed OAuth in Pipedream's hosted UI.", "default": "default" } }, "type": "object", "title": "SyncRequest", "description": "Request body for syncing discovered OAuth accounts from a broker into Jentic credentials." }, "ToolkitCreate": { "properties": { "name": { "type": "string", "title": "Name", "description": "Toolkit name for identification" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description", "description": "Optional description of this toolkit's purpose" }, "simulate": { "type": "boolean", "title": "Simulate", "description": "If true, toolkit operates in dry-run mode (no real API calls)", "default": false }, "initial_key_label": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Initial Key Label", "description": "Label for the first key created with this toolkit (e.g. 'Agent A')" }, "initial_key_allowed_ips": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Initial Key Allowed Ips", "description": "IP allowlist for the first key. NULL = unrestricted." } }, "type": "object", "required": ["name"], "title": "ToolkitCreate", "description": "Create a new toolkit with scoped credentials and access control. Optionally generates first API key." }, "ToolkitCredentialAdd": { "properties": { "credential_id": { "type": "string", "title": "Credential Id", "description": "Credential ID to bind to this toolkit (format: cred_{12chars})" } }, "type": "object", "required": ["credential_id"], "title": "ToolkitCredentialAdd", "description": "Bind an existing credential to this toolkit. Agent rules apply; system safety rules are always active." }, "ToolkitKeyCreated": { "properties": { "id": { "type": "string", "title": "Id", "description": "Key ID (format: ck_{8chars})", "examples": ["ck_a1b2c3d4"] }, "name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Name", "description": "User-assigned key name for identification", "examples": ["Production agent key"] }, "prefix": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Prefix", "description": "Key prefix (always 'tk_' for toolkit keys)", "examples": ["tk_"] }, "allowed_ips": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Allowed Ips", "description": "IP CIDR ranges allowed to use this key (null = no IP restriction)", "examples": [["192.168.1.0/24"]] }, "revoked": { "type": "boolean", "title": "Revoked", "description": "True if this key has been revoked and can no longer authenticate", "default": false, "examples": [false] }, "created_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Created At", "description": "Unix timestamp when key was created", "examples": [1672531200.0] }, "key": { "type": "string", "title": "Key", "description": "Full API key value (format: tk_{32chars}) - only shown once at creation", "examples": ["tk_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"] } }, "additionalProperties": true, "type": "object", "required": ["id", "key"], "title": "ToolkitKeyCreated", "description": "Returned only at key creation \u2014 includes the full key value (never returned again)." }, "ToolkitKeyOut": { "properties": { "id": { "type": "string", "title": "Id", "description": "Key ID (format: ck_{8chars})", "examples": ["ck_a1b2c3d4"] }, "name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Name", "description": "User-assigned key name for identification", "examples": ["Production agent key"] }, "prefix": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Prefix", "description": "Key prefix (always 'tk_' for toolkit keys)", "examples": ["tk_"] }, "allowed_ips": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Allowed Ips", "description": "IP CIDR ranges allowed to use this key (null = no IP restriction)", "examples": [["192.168.1.0/24"]] }, "revoked": { "type": "boolean", "title": "Revoked", "description": "True if this key has been revoked and can no longer authenticate", "default": false, "examples": [false] }, "created_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Created At", "description": "Unix timestamp when key was created", "examples": [1672531200.0] } }, "additionalProperties": true, "type": "object", "required": ["id"], "title": "ToolkitKeyOut", "description": "Toolkit API key metadata. The full key value is only returned at creation time." }, "ToolkitOut": { "properties": { "id": { "type": "string", "title": "Id", "description": "Toolkit ID", "examples": ["default"] }, "name": { "type": "string", "title": "Name", "description": "Human-readable toolkit name", "examples": ["Default Toolkit"] }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description", "description": "Optional description of this toolkit's purpose", "examples": ["Default toolkit for general-purpose API access"] }, "created_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Created At", "description": "Unix timestamp when created", "examples": [1672531200.0] }, "disabled": { "type": "boolean", "title": "Disabled", "description": "If true, all API keys for this toolkit are revoked", "default": false, "examples": [false] }, "key_count": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Key Count", "description": "Number of API keys issued for this toolkit", "examples": [3] }, "credential_count": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Credential Count", "description": "Number of credentials bound to this toolkit", "examples": [5] }, "keys": { "items": { "$ref": "#/components/schemas/ToolkitKeyOut" }, "type": "array", "title": "Keys", "description": "API keys for this toolkit (if expanded)", "examples": [[]] }, "credentials": { "items": { "$ref": "#/components/schemas/CredentialBindingOut" }, "type": "array", "title": "Credentials", "description": "Credentials bound to this toolkit (if expanded)", "examples": [[]] }, "permissions": { "items": { "additionalProperties": true, "type": "object" }, "type": "array", "title": "Permissions", "description": "Access control rules for this toolkit", "examples": [ [ { "effect": "allow", "methods": ["GET"] } ] ] } }, "additionalProperties": true, "type": "object", "required": ["id", "name"], "title": "ToolkitOut", "description": "Toolkit configuration with scoped credentials and access control policies." }, "ToolkitPatch": { "properties": { "name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Name", "description": "New toolkit name (optional)" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Description", "description": "New description (optional)" }, "simulate": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Simulate", "description": "Toggle dry-run mode (optional)" }, "disabled": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "title": "Disabled", "description": "Toggle toolkit disabled state (optional)" } }, "type": "object", "title": "ToolkitPatch", "description": "Update toolkit metadata or toggle disabled/simulate flags. Only provided fields are changed." }, "TraceChildOut": { "properties": { "id": { "type": "string", "title": "Id", "description": "Child trace id", "examples": ["exec_abc123xyz"] }, "operation_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Operation Id", "description": "Operation capability id of the broker call (always set \u2014 children are broker traces).", "examples": ["GET/api.github.com/repos/{owner}/{repo}"] }, "status": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status", "description": "Child trace status: success, failed, or pending.", "examples": ["success"] }, "http_status": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Http Status", "description": "Final HTTP status code from the upstream call.", "examples": [200] }, "duration_ms": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Duration Ms", "description": "Child trace duration in milliseconds.", "examples": [412] }, "created_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Created At", "description": "Unix timestamp when the child trace started; the panel orders by this.", "examples": [1672531200.0] }, "api_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Id", "description": "Catalog id of the child trace's upstream API (joined from `executions.api_id`).", "examples": ["api.github.com"] }, "api_name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Name", "description": "Human-readable api name from the catalog; null when api_id is unset or stale.", "examples": ["GitHub"] } }, "additionalProperties": true, "type": "object", "required": ["id"], "title": "TraceChildOut", "description": "Compact child broker trace summary referenced from a workflow's `children[]` panel." }, "TraceListPage": { "properties": { "total": { "type": "integer", "title": "Total", "description": "Total number of traces matching the query", "examples": [247] }, "limit": { "type": "integer", "title": "Limit", "description": "Maximum traces returned in this response", "examples": [50] }, "offset": { "type": "integer", "title": "Offset", "description": "Starting offset for pagination (0-indexed)", "examples": [0] }, "traces": { "items": { "$ref": "#/components/schemas/TraceOut" }, "type": "array", "title": "Traces", "description": "Array of trace records for this page", "examples": [[]] } }, "type": "object", "required": ["total", "limit", "offset", "traces"], "title": "TraceListPage", "description": "Paginated list of execution traces for auditing recent broker and workflow calls." }, "TraceOut": { "properties": { "id": { "type": "string", "title": "Id", "description": "Trace ID (format: exec_{12chars})", "examples": ["trace_abc123xyz"] }, "toolkit_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Toolkit Id", "description": "Toolkit that executed this capability", "examples": ["default"] }, "agent_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Agent Id", "description": "Agent client_id when the call used an agent access token (at_\u2026)", "examples": ["agnt_abc123"] }, "operation_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Operation Id", "description": "Operation capability ID (for single API calls)", "examples": ["GET/api.github.com/repos/{owner}/{repo}"] }, "workflow_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Workflow Id", "description": "Workflow capability ID (for multi-step workflows)", "examples": [null] }, "spec_path": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Spec Path", "description": "Path to the OpenAPI spec or Arazzo workflow file", "examples": ["api.github.com/openapi.json"] }, "status": { "type": "string", "title": "Status", "description": "Execution status: success, failed, or pending", "examples": ["success"] }, "http_status": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Http Status", "description": "Final HTTP status code from upstream", "examples": [200] }, "duration_ms": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Duration Ms", "description": "Total execution duration in milliseconds", "examples": [1234] }, "error": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Error", "description": "Error message if execution failed", "examples": [null] }, "created_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Created At", "description": "Unix timestamp when execution started", "examples": [1672531200.0] }, "completed_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Completed At", "description": "Unix timestamp when execution completed", "examples": [1672531201.0] }, "job_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Job Id", "description": "Async job that owns this trace, when the trace was produced inside a job's lifecycle (Prefer: wait=0 broker call, upstream-202, or async workflow run). Null for synchronous calls. The Monitor page renders a [job \u2197] cross-link in the Execution Log when this is set.", "examples": ["job_abc123xyz"] }, "parent_trace_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Parent Trace Id", "description": "Parent workflow trace this trace is a child step of. Set on broker traces spawned by an arazzo-runner workflow execution; null for top-level broker calls and for the workflow trace itself. Used to render \"part of workflow X\" context in the Execution Detail panel.", "examples": ["exec_abc123xyz"] }, "api_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Id", "description": "Catalog id of the upstream API the broker proxied to (`apis.id`). Set at write time from the matched credential's `api_id`; null for workflow traces (which are multi-API by definition) and for unattributed broker calls where no credential matched. Use this as the join key when correlating traces with the registered API \u2014 the read endpoints already join `apis` and surface `api_name` alongside.", "examples": ["stripe.com"] }, "api_name": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Api Name", "description": "Human-readable API name from the catalog (`apis.name`) joined via `api_id`. Null when `api_id` is null, or when `api_id` references a row that no longer exists (e.g. the API was deleted from the catalog after the trace was written) \u2014 frontend falls back to rendering `api_id` directly.", "examples": ["Stripe API"] }, "inputs": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Inputs", "description": "Workflow inputs captured by the runner when this trace is a workflow execution. Always null for broker (single-operation) traces \u2014 request bodies are not persisted to keep PII out of the trace store. The Monitor drawer renders this in the Inputs panel.", "examples": [ { "owner": "octocat", "repo": "hello" } ] }, "outputs": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Outputs", "description": "Workflow outputs returned by the runner when this trace is a workflow execution. Always null for broker traces (no upstream response body is persisted) and for failed/pending workflow runs. The Monitor drawer renders this in the Outputs panel.", "examples": [ { "issue_url": "https://github.com/.../issues/42" } ] }, "steps": { "items": { "$ref": "#/components/schemas/TraceStepOut" }, "type": "array", "title": "Steps", "description": "Step-by-step execution log (for workflows)", "examples": [[]] }, "children": { "items": { "$ref": "#/components/schemas/TraceChildOut" }, "type": "array", "title": "Children", "description": "Child broker traces spawned by this trace (rows where `executions.parent_trace_id` equals this trace's id). Populated for workflow traces; always empty for broker traces. The Monitor Execution drawer renders these as a `Child broker calls` panel with cross-links into each child's own drawer. Ordered by `created_at` ascending so the rendered list reads in step order.", "examples": [[]] } }, "additionalProperties": true, "type": "object", "required": ["id", "status"], "title": "TraceOut", "description": "Complete execution trace with status, timing, and step-by-step results for debugging." }, "TraceStepOut": { "properties": { "id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Id", "description": "Internal step record ID", "examples": ["step_1"] }, "step_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Step Id", "description": "Step identifier from the Arazzo workflow", "examples": ["getRepo"] }, "operation": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Operation", "description": "Operation capability ID executed in this step", "examples": ["GET/api.github.com/repos/{owner}/{repo}"] }, "status": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status", "description": "Step status: success or failed", "examples": ["success"] }, "http_status": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Http Status", "description": "HTTP status code from this step's API call", "examples": [200] }, "inputs": { "title": "Inputs", "description": "Step input arguments (resolved parameters passed to this step's operation)", "examples": [ { "owner": "jentic", "repo": "jentic-mini" } ] }, "output": { "title": "Output", "description": "Step output data", "examples": [ { "name": "jentic-mini", "stars": 42 } ] }, "error": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Error", "description": "Error message if step failed", "examples": [null] }, "started_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Started At", "description": "Unix timestamp when step started", "examples": [1672531200.0] }, "completed_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Completed At", "description": "Unix timestamp when step completed", "examples": [1672531201.0] } }, "additionalProperties": true, "type": "object", "title": "TraceStepOut", "description": "Individual workflow step execution details including inputs, outputs, and timing." }, "UsageBucket": { "properties": { "ts": { "type": "number", "title": "Ts", "description": "Unix-second start of the bucket", "examples": [1700000000.0] }, "total": { "type": "integer", "title": "Total", "description": "Total traces in bucket", "examples": [42] }, "success": { "type": "integer", "title": "Success", "description": "Successful traces in bucket", "examples": [40] }, "failed": { "type": "integer", "title": "Failed", "description": "Failed traces in bucket", "examples": [2] }, "avg_ms": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Avg Ms", "description": "Mean duration in this bucket", "examples": [395.0] } }, "additionalProperties": true, "type": "object", "required": ["ts", "total", "success", "failed"], "title": "UsageBucket", "description": "One time bucket of trace counts; the UI plots these as a stacked bar chart." }, "UsageResponse": { "properties": { "since": { "type": "number", "title": "Since", "description": "Window start (unix seconds)", "examples": [1699913600.0] }, "until": { "type": "number", "title": "Until", "description": "Window end (unix seconds)", "examples": [1700000000.0] }, "bucket_seconds": { "type": "integer", "title": "Bucket Seconds", "description": "Width of one bucket in seconds (chosen by server)", "examples": [3600] }, "group_by": { "type": "string", "title": "Group By", "description": "Grouping for the `top` list: 'toolkit' | 'api' | 'agent'", "examples": ["toolkit"] }, "stats": { "$ref": "#/components/schemas/UsageStats" }, "buckets": { "items": { "$ref": "#/components/schemas/UsageBucket" }, "type": "array", "title": "Buckets", "description": "Time-bucketed counts" }, "top": { "items": { "$ref": "#/components/schemas/UsageTopRow" }, "type": "array", "title": "Top", "description": "Top groups by total traces, descending. Capped at `limit`." } }, "additionalProperties": true, "type": "object", "required": ["since", "until", "bucket_seconds", "group_by", "stats"], "title": "UsageResponse", "description": "Aggregated trace usage for the Monitor page (HealthStrip + bar chart + breakdown)." }, "UsageStats": { "properties": { "total": { "type": "integer", "title": "Total", "description": "Number of traces in window", "examples": [1234] }, "success": { "type": "integer", "title": "Success", "description": "Traces with status=success", "examples": [980] }, "failed": { "type": "integer", "title": "Failed", "description": "Traces with status=failed", "examples": [20] }, "pending": { "type": "integer", "title": "Pending", "description": "Traces still in flight (status=pending)", "default": 0, "examples": [0] }, "avg_ms": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Avg Ms", "description": "Mean duration in milliseconds (success+failed)", "examples": [412.3] }, "p50_ms": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "P50 Ms", "description": "Median duration in milliseconds", "examples": [210.0] }, "p95_ms": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "P95 Ms", "description": "95th percentile duration in milliseconds", "examples": [1800.0] }, "active_now": { "type": "integer", "title": "Active Now", "description": "Snapshot count of in-flight async jobs (status pending or running) at query time \u2014 not bound by the [since,until) window.", "default": 0, "examples": [3] } }, "additionalProperties": true, "type": "object", "required": ["total", "success", "failed"], "title": "UsageStats", "description": "High-level trace counts and latency for a single time window." }, "UsageTopRow": { "properties": { "key": { "type": "string", "title": "Key", "description": "Group key \u2014 toolkit_id, agent_client_id, or api host (depending on group_by)", "examples": ["api.github.com"] }, "label": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Label", "description": "Human-readable label for the row. For `group_by=agent` this is the agent's `client_name`; for `group_by=api` it is `apis.name` when the API is registered in the catalog (null otherwise \u2014 the frontend falls back to rendering `key`). For `group_by=toolkit` the label is null (toolkit ids are already human-readable slugs).", "examples": ["GitHub"] }, "total": { "type": "integer", "title": "Total", "description": "Total traces in this row", "examples": [500] }, "success": { "type": "integer", "title": "Success", "description": "Successful traces", "examples": [490] }, "failed": { "type": "integer", "title": "Failed", "description": "Failed traces", "examples": [10] }, "avg_ms": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Avg Ms", "description": "Mean duration", "examples": [320.0] }, "trend": { "anyOf": [ { "items": { "type": "integer" }, "type": "array" }, { "type": "null" } ], "title": "Trend", "description": "Compact time-series of trace counts for this row across the window, aligned to a fixed number of equally-sized buckets (12 by default). Used to render per-row sparklines on the Monitor page Breakdown table. Independent of the top-level `buckets` field \u2014 this one always has the same length regardless of window size, while `buckets` width is chosen by the server.", "examples": [[3, 5, 2, 8, 11, 7, 4, 6, 9, 5, 3, 7]] } }, "additionalProperties": true, "type": "object", "required": ["key", "total", "success", "failed"], "title": "UsageTopRow", "description": "One row in the `top` list \u2014 aggregation grouped by toolkit, API host or agent." }, "UserCreate": { "properties": { "username": { "type": "string", "title": "Username", "description": "Admin account username (will be trimmed of whitespace)" }, "password": { "type": "string", "title": "Password", "description": "Admin account password (stored as bcrypt hash)" } }, "type": "object", "required": ["username", "password"], "title": "UserCreate", "description": "Request body for creating the root admin account. One-time only \u2014 POST /user/create returns 410 after first use." }, "UserOut": { "properties": { "logged_in": { "type": "boolean", "title": "Logged In", "description": "True if valid session exists", "default": false, "examples": [true] }, "username": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Username", "description": "Username of authenticated user, null if not logged in", "examples": ["admin"] }, "is_admin": { "type": "boolean", "title": "Is Admin", "description": "True if user has admin privileges", "default": false, "examples": [true] }, "toolkit_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Toolkit Id", "description": "Associated toolkit ID for this user, null if admin", "examples": ["default"] }, "trusted_subnet": { "type": "boolean", "title": "Trusted Subnet", "description": "True if request originated from trusted subnet (127.0.0.0/8 or 10.0.0.0/8)", "default": false, "examples": [true] } }, "additionalProperties": true, "type": "object", "title": "UserOut", "description": "Current session status including authentication method and context (human session, agent key, or trusted subnet)." }, "ValidationError": { "properties": { "loc": { "items": { "anyOf": [ { "type": "string" }, { "type": "integer" } ] }, "type": "array", "title": "Location" }, "msg": { "type": "string", "title": "Message" }, "type": { "type": "string", "title": "Error Type" }, "input": { "title": "Input" }, "ctx": { "type": "object", "title": "Context" } }, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError" } }, "securitySchemes": { "JenticApiKey": { "type": "apiKey", "in": "header", "name": "X-Jentic-API-Key", "description": "Toolkit API key (`tk_xxx`) issued for a toolkit (legacy agent path)." }, "AgentOauthAccessToken": { "type": "http", "scheme": "bearer", "bearerFormat": "opaque", "description": "Agent access token (`at_\u2026`) from `POST /oauth/token`. Used for all agent-authenticated operations." }, "AgentOauthRegistrationToken": { "type": "http", "scheme": "bearer", "bearerFormat": "opaque", "description": "Short-lived registration token (`rat_\u2026`) from `POST /register`. Only valid for `GET /register/{client_id}` to poll approval status." }, "HumanLogin": { "type": "oauth2", "description": "Human admin session. Fill in username + password to get a Bearer JWT.", "flows": { "password": { "tokenUrl": "/user/token", "scopes": {} } } } } }, "tags": [ { "name": "search", "description": "**Start here.** Full-text and semantic search across all registered APIs and operations." }, { "name": "inspect", "description": "Inspect capability details, list APIs and operations." }, { "name": "execute", "description": "Transparent request broker \u2014 runs API operations and Arazzo workflows. Prefix any registered host to route through the broker: `POST /api.stripe.com/v1/payment_intents`. Credential injection, policy enforcement, and simulate mode built-in." }, { "name": "observe", "description": "Read async job handles and execution traces." }, { "name": "toolkits", "description": "Manage toolkits: scoped credential bundles with access keys, permissions, and access requests." }, { "name": "credentials", "description": "Manage upstream API credentials in the vault (humans/admin only). Values are write-only \u2014 never returned after creation." }, { "name": "user", "description": "Human account management: create account, login, logout, and agent key generation." }, { "name": "catalog", "description": "Register APIs, upload specs, manage overlays and notes." } ], "servers": [ { "url": "https://{hostname}:{port}", "description": "Self-hosted instance (HTTPS)", "variables": { "hostname": { "default": "localhost", "description": "Server hostname" }, "port": { "default": "8900", "description": "Server port" } } }, { "url": "http://{hostname}:{port}", "description": "Local development only (HTTP)", "variables": { "hostname": { "default": "localhost", "description": "Server hostname" }, "port": { "default": "8900", "description": "Server port" } } } ], "security": [ { "JenticApiKey": [] }, { "AgentOauthAccessToken": [] }, { "HumanLogin": [] } ] }