{ "openapi": "3.1.0", "info": { "title": "Jentic Mini", "description": "**Jentic Mini** is the open-source, self-hosted implementation of the Jentic API — 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 — aggregates the collective know-how of agents across API definitions and Arazzo workflows |\n\n## Authentication\n**Agents** — provide `X-Jentic-API-Key: tk_xxx` header.\n**Humans** — [log in here](/login) for a session cookie (required for admin operations).\nFirst time? Call `POST /default-api-key/generate` from a trusted subnet to get your agent key.\n\n## Tag groups\n| Tag | Who uses it | Purpose |\n|-----|-------------|----------|\n| **search** | Agents | Full-text search — the main entrypoint |\n| **inspect** | Agents | Inspect capabilities, list APIs and operations |\n| **execute** | Agents | Transparent request broker — 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.0.0-test", "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": { "/apis": { "get": { "tags": ["catalog"], "summary": "List APIs — browse all available API providers (local and catalog)", "description": "Returns paginated list of API providers — both locally registered and from the Jentic public catalog.\n\nEvery entry has:\n- `source: \"local\"` — spec is indexed locally, operations are searchable and executable\n- `source: \"catalog\"` — available from the Jentic public catalog; add credentials to use\n- `has_credentials: bool` — whether credentials have been configured for this API\n\nUse `?source=local` or `?source=catalog` to filter. Default returns all.\nTo use a catalog API: call `POST /credentials` with `api_id` set — 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" } ], "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 — use GET /apis/{api_id} directly instead. Do not use for natural language capability discovery — use GET /search for that.", "related_operations": [ "GET /apis/{api_id} — get detailed API metadata including security schemes and credential status", "GET /apis/{api_id}/operations — list all operations for a specific API", "GET /search — search for capabilities across all APIs by natural language intent", "POST /credentials — add credentials for an API (imports from catalog if not yet registered)" ] }, "security": [] } }, "/apis/{api_id}": { "get": { "tags": ["catalog"], "summary": "Get API details — 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` — title, version, contact, license, terms of service\n- `servers` — base URLs and variables (merged from spec + confirmed overlays)\n- `security_schemes` — security scheme definitions (merged from spec + confirmed overlays),\n plus `security_required` (global security requirements)\n- `credentials_configured` — 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}` — inspect `security_schemes` and `credentials_configured`\n2. For each unconfigured scheme, determine required fields from the scheme type:\n - `http bearer` → `secret` (token)\n - `http basic` → `secret` (password) + optional `identity` (username)\n - `apiKey` → `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` — tag objects with names and descriptions\n- `paths` — full paths object (can be very large — prefer GET /apis/{api_id}/operations)\n- `components` — all reusable component definitions (schemas, parameters, responses, etc.)\n- `webhooks` — 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 — 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 — use GET /apis/{api_id}/openapi.json for that. Do not use to list operations — use GET /apis/{api_id}/operations instead.", "related_operations": [ "GET /apis — list available APIs to find the api_id", "GET /apis/{api_id}/openapi.json — download full merged OpenAPI spec with overlays applied", "GET /apis/{api_id}/operations — list all operations for this API", "POST /credentials — add credentials after inspecting security_schemes", "GET /credentials?api_id={api_id} — check which credentials are configured" ] }, "security": [] } }, "/apis/{api_id}/openapi.json": { "get": { "tags": ["catalog"], "summary": "Download merged OpenAPI spec as JSON — 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 — use GET /apis/{api_id}?sections=info,servers,security instead. Do not use to browse operations — use GET /apis/{api_id}/operations for paginated operation list.", "related_operations": [ "GET /apis/{api_id} — get API metadata with selective spec sections (no download, lighter weight)", "GET /apis/{api_id}/openapi.yaml — download the same spec in YAML format", "GET /apis/{api_id}/operations — list operations without downloading full spec", "GET /apis/{api_id}/overlays — view overlays that are merged into this spec", "POST /apis/{api_id}/overlays — submit a new overlay to correct security schemes or servers" ] }, "security": [ { "JenticApiKey": [] }, { "HumanLogin": [] } ] } }, "/apis/{api_id}/openapi.yaml": { "get": { "tags": ["catalog"], "summary": "Download merged OpenAPI spec as YAML — 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 — use GET /apis/{api_id}?sections=info,servers,security instead. Do not use to browse operations — use GET /apis/{api_id}/operations for paginated operation list.", "related_operations": [ "GET /apis/{api_id} — get API metadata with selective spec sections (no download, lighter weight)", "GET /apis/{api_id}/openapi.json — download the same spec in JSON format", "GET /apis/{api_id}/operations — list operations without downloading full spec", "GET /apis/{api_id}/overlays — view overlays that are merged into this spec", "POST /apis/{api_id}/overlays — submit a new overlay to correct security schemes or servers" ] }, "security": [ { "JenticApiKey": [] }, { "HumanLogin": [] } ] } }, "/apis/{api_id}/operations": { "get": { "tags": ["catalog"], "summary": "List operations for an API — enumerate all available actions", "description": "Returns paginated list of operations for the given API. Each item has capability id, summary, and description. 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" } ], "responses": { "200": { "description": "Operation list — 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 — use GET /search instead. Do not use to inspect a specific operation's parameters — use GET /inspect/{id} after finding the capability ID.", "related_operations": [ "GET /apis — list available APIs to find the api_id", "GET /inspect/{id} — inspect operation details (parameters, request/response schemas, auth)", "GET /search — search for specific capabilities by natural language intent instead of browsing", "GET /{target} (broker) — execute an operation after finding its capability ID" ] }, "security": [ { "JenticApiKey": [] }, { "HumanLogin": [] } ] } }, "/apis/{api_id}/overlays": { "post": { "tags": ["catalog"], "summary": "Submit an OpenAPI overlay — 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 — 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 — 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 — first add credentials via POST /credentials, then submit overlay if authentication fails with 401/403. Do not submit duplicate overlays — check GET /apis/{api_id}/overlays first.", "related_operations": [ "GET /apis/{api_id}/overlays — list existing overlays to avoid duplicates", "GET /apis/{api_id} — inspect current security_schemes before patching", "POST /credentials — add credentials after overlay is confirmed", "GET /apis/{api_id}/openapi.json — download merged spec to verify overlay was applied" ] }, "security": [ { "HumanLogin": [] } ] }, "get": { "tags": ["catalog"], "summary": "List overlays for an API — 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 — use GET /apis/{api_id}/openapi.json for that (overlays already applied). Do not use to inspect base security schemes — use GET /apis/{api_id} instead.", "related_operations": [ "POST /apis/{api_id}/overlays — submit a new overlay after checking for duplicates", "DELETE /apis/{api_id}/overlays/{overlay_id} — delete an overlay", "GET /apis/{api_id}/openapi.json — download merged spec with all confirmed overlays applied", "GET /apis/{api_id} — 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 — deletion is permanent. Do not delete overlays that other toolkits may depend on without coordination.", "related_operations": [ "GET /apis/{api_id}/overlays — list overlays to find the overlay_id", "POST /apis/{api_id}/overlays — submit a replacement overlay after deleting an incorrect one", "GET /apis/{api_id}/openapi.json — 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 — use GET /apis?source=local instead. Do not use for natural language API discovery — use GET /search for that.", "related_operations": [ "GET /catalog/{api_id} — get spec download URL for a catalog API", "POST /import — import a catalog API after finding it here", "POST /catalog/refresh — refresh catalog manifest from GitHub if empty or stale", "GET /apis — list locally registered APIs (includes both local and catalog sources)" ] }, "security": [ { "JenticApiKey": [] }, { "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 — 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 — safe but unnecessary since manifest auto-refreshes daily. Do not use to import APIs — use POST /import after refreshing.", "related_operations": [ "GET /catalog — list catalog entries after refreshing", "GET /catalog/{api_id} — get spec URL for an API after refreshing", "POST /import — import an API after finding it in the refreshed catalog" ] }, "security": [ { "JenticApiKey": [] }, { "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 — check GET /apis first. Do not use to download the spec directly (use POST /import instead).", "related_operations": [ "GET /catalog — browse catalog to find the api_id", "POST /import — import the API using the spec_url returned here", "GET /apis — check if API is already registered before importing", "POST /credentials — add credentials after importing" ] }, "security": [ { "JenticApiKey": [] }, { "HumanLogin": [] } ] } }, "/credentials": { "post": { "tags": ["credentials"], "summary": "Store an upstream API credential — 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` | ✅ implemented | `Authorization: Bearer {value}` | Token, PAT, or OAuth access token | Not used |\n| `basic` | ✅ implemented | `Authorization: Basic base64({identity or \"token\"}:{value})` | Password or PAT | Username (optional — defaults to `\"token\"` if omitted, works for GitHub PATs) |\n| `apiKey` | ✅ implemented | Custom header or query param `= {value}` | API key | For **compound schemes** (e.g. Discourse `Api-Key` + `Api-Username`): set `identity` to the username — one credential covers both headers when the overlay uses canonical `Secret`/`Identity` scheme names |\n| `oauth2` | ⚠️ partial | `Authorization: Bearer {value}` — token must be pre-obtained | Access token (Pipedream-managed flows only via `pipedream_oauth`) | Not used |\n| `digest` | 🔲 planned | RFC 2617 challenge-response (nonce/HMAC handshake) | Password | Username |\n| `jwt` | 🔲 planned | `Authorization: Bearer {signed_jwt}` — auto-generated from signing key | Private key or secret | Key ID (`kid`) — signing algorithm and claims go in `context` |\n| `aws_sig4` | 🔲 planned | `Authorization: AWS4-HMAC-SHA256 ...` signed headers | AWS Secret Access Key | AWS Access Key ID — region and service go in `context` |\n| `oauth1` | 🔲 planned | HMAC-SHA1 signed request (nonce + timestamp) | OAuth secret | OAuth consumer key |\n| `hawk` | 🔲 planned | `Authorization: Hawk ...` HMAC request signing | Hawk secret | Hawk key ID |\n| `ntlm` | 🔲 not planned | Windows NTLM challenge-response | Password | Username + domain |\n| `akamai_edgegrid` | 🔲 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 — 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}` — 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 — 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 — 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": [] }, { "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": [] }, { "HumanLogin": [] } ] }, "patch": { "tags": ["credentials"], "summary": "Update an upstream API credential — 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 — 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 agent API key", "description": "Issue the default `tk_xxx` agent key bound to the default toolkit.\n\n**First call** — unauthenticated, subnet-restricted:\n- Available only before the key has been claimed\n- Only accessible from trusted subnets (RFC 1918 + loopback by default;\n configure via `JENTIC_TRUSTED_SUBNETS` env var)\n- Returns the key **once only** — it is not recoverable after this response\n- After this call, the endpoint requires a human session\n\n**Subsequent calls** — human session required:\n- Revokes the current default key\n- Issues and returns a fresh key\n\nThe key works immediately — you do not need to wait for the admin account\nto be created before using it.", "operationId": "generate_default_key_default_api_key_generate_post", "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } }, "security": [] } }, "/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 default API key claimed yet → agent should call POST /default-api-key/generate\n- status='account_required': Agent key active, admin account not created → user should visit setup_url\n- status='ok': Fully set up → 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": "Successful Response", "content": { "application/json": { "schema": {} } } } }, "security": [] } }, "/import": { "post": { "tags": ["catalog"], "summary": "Import an API spec or workflow — 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 — 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 — check GET /apis or GET /catalog first. Do not use to add credentials (use POST /credentials). Do not use to update existing specs — delete and re-import instead.", "related_operations": [ "GET /apis — check if API is already registered before importing", "GET /catalog — browse available APIs in public catalog before importing", "POST /credentials — add credentials after importing an API", "GET /search — verify imported operations are searchable" ] }, "security": [ { "JenticApiKey": [] }, { "HumanLogin": [] } ] } }, "/inspect/{capability_id}": { "get": { "tags": ["inspect"], "summary": "Inspect a capability — 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 — 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 — 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 — prefer GET /apis/{api_id}/operations when browsing an entire API's operation list.", "related_operations": [ "GET /search — find capabilities by natural language query first", "GET /{target} — execute the operation after inspecting", "GET /apis/{api_id}/operations — list all operations for an API" ] }, "security": [ { "JenticApiKey": [] }, { "HumanLogin": [] } ] } }, "/jobs": { "get": { "tags": ["observe"], "summary": "List async jobs — paginated handles for outstanding and completed async calls", "description": "Returns async jobs only — 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", "title": "Status" }, "description": "Filter by status" }, { "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)" } ], "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": [] }, { "HumanLogin": [] } ] } }, "/jobs/{job_id}": { "get": { "tags": ["observe"], "summary": "Poll async job — 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 — 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) — those produce traces, not jobs. Do not poll excessively — implement exponential backoff (start at 1s, max 30s).", "related_operations": [ "GET /{target} (broker) — broker call with Prefer: wait=0 returns 202 + job ID", "POST /workflows/{slug} — workflow with Prefer: wait=0 returns 202 + job ID", "GET /traces/{id} — completed jobs reference a trace via trace_id field", "DELETE /jobs/{id} — cancel an outstanding async job" ] }, "security": [ { "JenticApiKey": [] }, { "HumanLogin": [] } ] }, "delete": { "tags": ["observe"], "summary": "Cancel async job — 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": [] }, { "HumanLogin": [] } ] } }, "/notes": { "post": { "tags": ["catalog"], "summary": "Add a note — 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 — use GET /traces instead. Do not use for credential issues — fix credentials via PATCH /credentials.", "related_operations": [ "GET /notes — list existing notes for a resource to avoid duplicates", "DELETE /notes/{id} — remove outdated or incorrect notes", "GET /traces/{id} — link to execution context when reporting feedback", "POST /apis/{api_id}/overlays — submit OpenAPI overlay to fix spec issues" ] }, "security": [ { "JenticApiKey": [] }, { "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 — 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 — use GET /traces instead. Do not use for credential status — use GET /credentials.", "related_operations": [ "POST /notes — add a note after discovering new operational knowledge", "DELETE /notes/{id} — remove outdated notes", "GET /inspect/{id} — inspect operation schema before checking notes", "GET /traces — view execution history for context" ] }, "security": [ { "JenticApiKey": [] }, { "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 — fix the underlying issue instead. Do not delete notes from other users without coordination.", "related_operations": [ "GET /notes — list notes to find the note_id", "POST /notes — add a replacement note after deleting an incorrect one" ] }, "security": [ { "JenticApiKey": [] }, { "HumanLogin": [] } ] } }, "/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 — use GET /oauth-brokers/{broker_id} instead. Do not use to manage OAuth accounts — use POST /oauth-brokers/{broker_id}/connect-link to initiate OAuth.", "related_operations": [ "POST /oauth-brokers — register a new OAuth broker (Pipedream)", "GET /oauth-brokers/{broker_id} — get detailed broker configuration and account statistics", "POST /oauth-brokers/{broker_id}/connect-link — initiate OAuth flow for an API via broker", "POST /oauth-brokers/{broker_id}/sync — pull connected accounts into Jentic after OAuth" ] }, "security": [ { "JenticApiKey": [] }, { "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 — 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) → **API** → click **+ New OAuth Client**.\nName it \"Jentic\". Store the **client ID** and **client secret** safely — 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 → Jentic → Settings** and note the **project ID** (format: `proj_xxx`).\n\nThat's it. Register the broker below — 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 → 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 — it is displayed to end users in the\nPipedream OAuth consent UI.\n\n`client_secret` is write-only — 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 — 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": [] }, { "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": [] }, { "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": [] }, { "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 —\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 — 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": [] }, { "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": [] }, { "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": [] } ] } }, "/search": { "get": { "tags": ["search"], "summary": "Search the catalog — 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 (≤3 sentences), type, score, and _links.\n- `source: \"local\"` — operation or workflow in your local registry\n- `source: \"catalog\"` — API available from the Jentic public catalog; add credentials to use\n\n_links.inspect → GET /inspect/{id} for full schema and auth detail.\n_links.execute → broker URL to call directly once ready.\nTypical flow: search → inspect → 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" } ], "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 — 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 — use GET /inspect/{id} directly instead.", "related_operations": [ "GET /inspect/{id} — get full operation details after finding it via search", "GET /apis — browse APIs by provider when you know the vendor", "GET /workflows — 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": [] }, { "HumanLogin": [] } ] }, "post": { "tags": ["toolkits"], "summary": "Create a toolkit — 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) — 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 — 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 — 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 — 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": [] }, { "HumanLogin": [] } ] }, "patch": { "tags": ["toolkits"], "summary": "Update toolkit — rename or update description", "description": "Update toolkit metadata — 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 — 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 — 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=` — 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": [] }, { "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` — agent is requesting a new credential be bound; `payload` contains `credential_id` and optional `rules`\n- `modify_permissions` — 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": [] }, { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/credentials": { "post": { "tags": ["toolkits"], "summary": "Bind an upstream API credential to this toolkit — 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": [] }, { "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 — 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 — 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 — 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": [] }, { "HumanLogin": [] } ] } }, "/toolkits/{toolkit_id}/access-requests/{req_id}": { "get": { "tags": ["toolkits", "toolkits"], "summary": "Poll an access request — 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` → `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 — `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": [] }, { "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 — 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 — 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 — 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 — 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` — 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": [] }, { "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 — 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 — 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 — 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 — 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" } ], "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) — use GET /traces/{id} directly instead.", "related_operations": [ "GET /traces/{id} — get full trace with step-by-step detail", "GET /{target} (broker) — returns X-Jentic-Execution-Id header pointing to trace", "POST /workflows/{slug} — workflow execution returns trace_id in response body" ] }, "security": [ { "JenticApiKey": [] }, { "HumanLogin": [] } ] } }, "/traces/{trace_id}": { "get": { "tags": ["observe"], "summary": "Get trace detail — 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 — 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 — use GET /traces with pagination instead.", "related_operations": [ "GET /traces — list recent traces when you don't have a specific trace ID yet", "GET /{target} (broker) — execution returns X-Jentic-Execution-Id header", "POST /workflows/{slug} — workflow execution returns trace_id field" ] }, "security": [ { "JenticApiKey": [] }, { "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 — 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 — 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 —\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": [] }, { "HumanLogin": [] } ] } }, "/user/token": { "post": { "tags": ["user"], "summary": "OAuth2 password grant — 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 — 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": [] }, { "HumanLogin": [] } ] } }, "/workflows": { "get": { "tags": ["catalog"], "summary": "List workflows — browse available multi-step Arazzo workflows", "description": "Returns registered workflows (source: local) plus available catalog workflow sources\n(source: catalog) — 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.", "operationId": "list_workflows_workflows_get", "parameters": [ { "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 — use GET /workflows/{slug} directly instead.", "related_operations": [ "GET /workflows/{slug} — get workflow definition and input schema", "POST /workflows/{slug} — execute a workflow via broker", "GET /search — search across operations and workflows by natural language intent", "GET /catalog — browse available APIs when you know workflows exist for a vendor" ] }, "security": [] } }, "/workflows/{slug}": { "get": { "tags": ["catalog"], "summary": "Get workflow definition — 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 — 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 — use POST /workflows/{slug} via broker for execution.", "related_operations": [ "POST /workflows/{slug} — execute this workflow with inputs", "GET /inspect/{id} — get full capability details (use workflow capability ID format: POST/{host}/workflows/{slug})", "GET /workflows — list all workflows when you don't know the slug yet" ] }, "security": [] } }, "/{target}": { "get": { "tags": ["execute", "execute"], "summary": "Broker — 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}` — 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` — validate and preview the call without sending it\n- `X-Jentic-Credential: {alias}` — select a specific credential when multiple exist for an API\n- `X-Jentic-Service: {app_slug}` — select by service name (e.g. `google_calendar`, `gmail`) when multiple credentials share a host\n- `X-Jentic-Dry-Run: true` — 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 — use POST /workflows/{slug} instead. Do not use for Jentic internal endpoints — use direct paths like /apis, /search.", "related_operations": [ "GET /inspect/{id} — inspect operation before calling to see parameters and auth requirements", "GET /traces/{id} — view execution trace after broker call (use X-Jentic-Execution-Id header)", "GET /jobs/{id} — poll async job status when Prefer: wait=0 header is used", "POST /credentials — add credentials before calling", "POST /toolkits/{id}/credentials — bind credentials to toolkit (body: {credential_id})" ] }, "security": [ { "JenticApiKey": [] }, { "HumanLogin": [] } ] } } }, "components": { "schemas": { "AccessRequestBody": { "properties": { "type": { "type": "string", "enum": ["grant", "modify_permissions"], "title": "Type", "description": "`grant` — bind an upstream API credential to this toolkit. Requires `credential_id`; `rules` is optional (defaults to system safety rules only). `modify_permissions` — 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 — 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\"]` — 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()` — **substring match by default**, case-insensitive. Use `^`/`$` to anchor. `|` is regex OR.\n - Unanchored: `\"issues\"` matches any path *containing* the word — often too broad\n - Prefix: `\"^/repos/myorg/myrepo/\"` — everything under that path\n - Exact: `\"^/v1/voices$\"` — 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`** — 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`** — 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` — bind a new upstream API credential to this toolkit (and optionally set permission rules). `modify_permissions` — update the permission rules on a credential already bound to this toolkit. `add_scope` — 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`** — 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`** — 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_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 — 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 — 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 — 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 — 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 — 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 — 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" }, "HTTPValidationError": { "properties": { "detail": { "items": { "$ref": "#/components/schemas/ValidationError" }, "type": "array", "title": "Detail" } }, "type": "object", "title": "HTTPValidationError" }, "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": { "id": { "type": "string", "title": "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"] }, "slug_or_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Slug Or Id", "description": "Workflow slug or capability ID", "examples": ["github-create-issue"] }, "toolkit_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Toolkit Id", "description": "Toolkit that initiated this job", "examples": ["default"] }, "status": { "type": "string", "title": "Status", "description": "Job status: pending, running, complete, failed, or upstream_async", "examples": ["completed"] }, "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"] }, "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": ["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 — 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 → API settings → OAuth clients). Optional: `environment` (`production` or `development`, default `production`), `support_email`.", "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 — 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." }, "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 — 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- `\"$\"` — root of the spec (components, info, servers)\n- `\"$.paths[*][*]\"` — all operations (apply global security)\n- `\"$.paths./foo.get\"` — 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 — 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 — 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`** — `\"allow\"` or `\"deny\"` (required)\n\n**`methods`** — list of HTTP methods to match, e.g. `[\"GET\", \"POST\"]`.\nOmit to match all methods.\n\n**`path`** — 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** — not a glob, not a prefix string.\n- It is **case-insensitive**.\n- It is a **substring match by default** — 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 — 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`** — 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 — 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 — 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 — 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) — 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) — 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"]] } }, "additionalProperties": true, "type": "object", "required": ["type", "id", "score"], "title": "SearchResult", "description": "A search result from the BM25 index — 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 — 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." }, "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"] }, "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] }, "steps": { "items": { "$ref": "#/components/schemas/TraceStepOut" }, "type": "array", "title": "Steps", "description": "Step-by-step execution log (for workflows)", "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] }, "output": { "title": "Output", "description": "Step output data", "examples": [ { "name": "jentic-mini", "stars": 42 } ] }, "detail": { "title": "Detail", "description": "Additional step metadata or runner context", "examples": [null] }, "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." }, "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 — 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": "Agent toolkit key (`tk_xxx`). Issue via `POST /default-api-key/generate`." }, "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 — 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 — 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": [] }, { "HumanLogin": [] } ] }