HTTP API
Governance
29 operations. {prefix} is the route prefix passed to
MapTracon; the template uses /tracon.
GET {prefix}/api/approvals/rules
Section titled “GET {prefix}/api/approvals/rules”Operation ID: TraconListApprovalRules
Lists persistent ‘don’t ask again’ approval rules.
Each rule pre-approves a tool call so it never reaches the approval mailbox again, which makes this list a standing grant worth reviewing. A rule with no agent name applies to every agent in the tenant. When it carries an arguments hash the rule matches only that exact call; without one it matches every call to that tool. Rules do not expire — remove one to start asking again.
Authorization: bearer authentication; Admin role policy when that policy is registered; RunsRead API-key scope.
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → array of ToolApprovalRule |
— |
POST {prefix}/api/approvals/rules
Section titled “POST {prefix}/api/approvals/rules”Operation ID: TraconCreateApprovalRule
Creates a persistent, argument-conditioned approval rule.
Writes a standing ‘don’t ask again’ rule with an admin-authored comparison (for example “amount <= 100”), evaluated on every call. There is no free-text expression field: the operator is a closed set and conditions combine with AND only. A code-defined policy (ITraconBuilder.AddToolApprovalPolicy) always runs first and can override this rule in both directions. For a tool of an MCP server the rule records the fingerprint of the server’s current endpoint (‘sourceFingerprint’) and approves that tool only while the server keeps that endpoint; a tool of a server whose tools are not discovered right now answers 409.
Authorization: bearer authentication; Admin role policy when that policy is registered; SecurityAdmin API-key scope.
Request body (required):
application/json→ToolApprovalRuleRequest
| Response | Body | Headers |
|---|---|---|
| 201 Created | application/json → ToolApprovalRule |
— |
DELETE {prefix}/api/approvals/rules/{ruleId}
Section titled “DELETE {prefix}/api/approvals/rules/{ruleId}”Operation ID: TraconDeleteApprovalRule
Revokes a persistent approval rule.
After the rule is deleted, approval is asked again for that tool.
Authorization: bearer authentication; Admin role policy when that policy is registered; RunsWrite API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
ruleId |
path | yes | string (uuid) |
— |
| Response | Body | Headers |
|---|---|---|
| 204 No Content | — | — |
GET {prefix}/api/audit
Section titled “GET {prefix}/api/audit”Operation ID: TraconListAudit
Lists audit entries, filterable by actor, action, entity, and date range.
Filterable by actor, action, entity, and date range. Runs (an agent processing a message) are not written to this log; the runs table already keeps the full record. The one exception is the ‘content.blocked’ action: an IContentGuard’s block decision is a GOVERNANCE decision, not a run detail, and must remain traceable even after the run record is deleted by retention policy. The entry carries only the guard and rule name, never the blocked TEXT.
Authorization: bearer authentication; Admin role policy when that policy is registered; AuditRead API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
actor |
query | no | string |
— |
action |
query | no | string |
— |
entity |
query | no | string |
— |
after |
query | no | string (date-time) |
— |
before |
query | no | string (date-time) |
— |
limit |
query | no | integer (int32) |
pattern `^-?(?:0\ |
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → array of AuditEntry |
— |
GET {prefix}/api/audit/{entity}
Section titled “GET {prefix}/api/audit/{entity}”Operation ID: TraconGetEntityAudit
Returns a single entity’s change history, newest first.
The path segment is the full entity key as it was recorded, in the form ‘
Authorization: bearer authentication; Admin role policy when that policy is registered; AuditRead API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
entity |
path | yes | string |
— |
limit |
query | no | integer (int32) |
pattern `^-?(?:0\ |
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → array of AuditEntry |
— |
GET {prefix}/api/audit/verify
Section titled “GET {prefix}/api/audit/verify”Operation ID: TraconVerifyAuditChain
Walks the tenant’s audit trail hash chain and reports whether it is intact.
‘Valid’ means every entry’s hash matches its content and links to the one before it. ‘Broken’ means an entry’s stored hash no longer matches its content — it was altered after it was written. ‘Gap’ means a link between two entries is missing — a row was deleted, or a write never completed; ‘firstFailingEntryId’ names where. An entry written before this feature shipped carries no hash and is excluded from the walk, not misreported as broken. Without ‘?after=’/‘?before=’ the whole tenant history is walked; a narrower range is cheaper but cannot judge a break exactly at its own edge, because the entry just before the range is not read.
Authorization: bearer authentication; Admin role policy when that policy is registered; AuditRead API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
after |
query | no | string (date-time) |
— |
before |
query | no | string (date-time) |
— |
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → AuditChainVerification |
— |
DELETE {prefix}/api/data-subjects/{id}
Section titled “DELETE {prefix}/api/data-subjects/{id}”Operation ID: TraconEraseDataSubject
Deletes a data subject’s content.
‘{id}’ is resolved through IDataSubjectResolver; without one this returns 409, never a silent no-op that could be read as ‘already erased’. ‘?dryRun=’ DEFAULTS TO TRUE: a bare call previews the row counts and deletes nothing; ‘?dryRun=false’ deletes for real. The audit trail (audit_log) is never touched — it is deliberately outside a data subject’s erasable content (by design: an audit record is ‘who did what’, not the subject’s own data) — but the erasure ITSELF is written there, with the row count per target; if that write fails, every delete is rolled back and this call fails, the same rule Approval decisions follow. A run of the subject that is still Running or Queued would write its session and checkpoints back after the erasure commits: ‘?dryRun=false’ is refused with 409 that names those runs, and the preview lists them in ‘activeRunIds’. ‘?force=true’ erases anyway, for a row a crashed process left behind; cancel a run that is really running first.
Authorization: bearer authentication; Admin role policy when that policy is registered; SecurityAdmin API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
id |
path | yes | string |
— |
dryRun |
query | no | boolean |
— |
force |
query | no | boolean |
— |
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → DataSubjectErasureResult |
— |
| 409 Conflict | application/problem+json → ProblemDetails |
— |
GET {prefix}/api/data-subjects/{id}/export
Section titled “GET {prefix}/api/data-subjects/{id}/export”Operation ID: TraconExportDataSubject
Exports a data subject’s content as one JSON document.
‘{id}’ is resolved through IDataSubjectResolver, which is registered by the consumer — Tracon does not store personal identity. Without a registered resolver this returns 409, never an empty document. The document holds every column of every matching row, keyed by target table (session state, runs, run inputs, attachment METADATA only — no file bytes, voice session summaries, run scores, workflow checkpoints, conversations, conversation items, and responses); a target with no matching rows is present as an empty array, not omitted.
Authorization: bearer authentication; Admin role policy when that policy is registered; SecurityAdmin API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
id |
path | yes | string |
— |
| Response | Body | Headers |
|---|---|---|
| 200 OK | — | — |
GET {prefix}/api/mcp-servers
Section titled “GET {prefix}/api/mcp-servers”Operation ID: TraconListMcpServers
Lists registered remote MCP servers.
No credential value is stored: ‘headerConfigurationKeys’ carries only the NAME of the configuration key each value is read from, and is returned as stored. Plain ‘headers’ are stored as sent and are returned with their NAMES only: every value is replaced with ‘***’.
Authorization: bearer authentication; Reader role policy when that policy is registered; AgentsRead API-key scope.
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → array of McpServerDefinition |
— |
PUT {prefix}/api/mcp-servers/{name}
Section titled “PUT {prefix}/api/mcp-servers/{name}”Operation ID: TraconSaveMcpServer
Adds or updates a remote MCP server.
SECURITY BOUNDARY. Adding an MCP server means accepting tool definitions from an external source. Only http/https addresses are accepted; local process (stdio) transport is not supported. Tools require approval by default; saving ‘requiresApproval: false’ for a new server, for a server that required approval, or together with a new ‘endpoint’ also requires the ‘SecurityAdmin’ scope when the call uses an API key (403 otherwise). A configuration key name must be under the configured allowed prefix and inside the tenant’s own key space — ‘{prefix}{tenantId}:…’; a flat name directly under the prefix belongs to the default tenant (400 otherwise). A credential header (Authorization, X-Api-Key, Cookie, any name ending in ‘-key’) is declared in ‘headerConfigurationKeys’ as the NAME of the configuration key its value is read from; the same header in plain ‘headers’ is rejected with 400, because plain header values are stored as given. No response returns a plain header value: the saved record comes back with every one replaced by ‘’, and a header whose value is ‘’ is rejected with 400. A header name may appear only once across both maps (case-insensitive, 400 otherwise), and ‘Authorization’ in ‘headerConfigurationKeys’ cannot be combined with OAuth. A body that carries the removed field ‘authorizationConfigurationKey’ is rejected with 400 that names ‘headerConfigurationKeys’ as its replacement. ‘headers’ or ‘headerConfigurationKeys’ left out or null keeps the stored map; ‘{}’ removes it. Every other field is replaced. Changing ‘endpoint’ without sending the maps keeps them, so the stored headers and the resolved credential values go to the NEW address.
Authorization: bearer authentication; Admin role policy when that policy is registered; AgentsAdmin API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
name |
path | yes | string |
— |
Request body (required):
application/json→McpServerRequest
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → McpServerDefinition |
— |
DELETE {prefix}/api/mcp-servers/{name}
Section titled “DELETE {prefix}/api/mcp-servers/{name}”Operation ID: TraconDeleteMcpServer
Deletes a remote MCP server.
The registration is removed, so the tools it contributed stop being offered to agents. Agent definitions that name those tools are not rewritten and will fail validation on their next save — check which agents use the server before removing it. No request is made to the remote server itself. An unknown name returns 404.
Authorization: bearer authentication; Admin role policy when that policy is registered; AgentsAdmin API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
name |
path | yes | string |
— |
| Response | Body | Headers |
|---|---|---|
| 204 No Content | — | — |
GET {prefix}/api/mcp-servers/{name}/oauth/callback
Section titled “GET {prefix}/api/mcp-servers/{name}/oauth/callback”Operation ID: TraconMcpOAuthCallback
Processes the OAuth provider’s callback request.
This endpoint is outside the access layers: the browser redirected by the provider cannot carry our bearer token. Security relies on the single-use ‘state’ value.
Authorization: anonymous.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
name |
path | yes | string |
— |
code |
query | no | string |
— |
state |
query | no | string |
— |
iss |
query | no | string |
— |
error |
query | no | string |
— |
| Response | Body | Headers |
|---|---|---|
| 200 OK | — | — |
POST {prefix}/api/mcp-servers/{name}/oauth/start
Section titled “POST {prefix}/api/mcp-servers/{name}/oauth/start”Operation ID: TraconStartMcpOAuth
Starts the OAuth authorization flow for an MCP server.
The administrator is redirected to the returned ‘authorizationUri’. After approval, the provider redirects back to the ‘/oauth/callback’ endpoint; that endpoint uses the ‘state’ value for CSRF protection.
Authorization: bearer authentication; Admin role policy when that policy is registered; SecurityAdmin API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
name |
path | yes | string |
— |
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → McpOAuthStartResponse |
— |
GET {prefix}/api/mcp-servers/{name}/prompts
Section titled “GET {prefix}/api/mcp-servers/{name}/prompts”Operation ID: TraconListMcpPrompts
Gets an MCP server’s prompt list.
If the server does not advertise the ‘prompts’ capability, the request is never sent.
Authorization: bearer authentication; Admin role policy when that policy is registered; AgentsRead API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
name |
path | yes | string |
— |
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → array of McpPromptSummary |
— |
POST {prefix}/api/mcp-servers/{name}/prompts/{prompt}
Section titled “POST {prefix}/api/mcp-servers/{name}/prompts/{prompt}”Operation ID: TraconGetMcpPrompt
Resolves an MCP prompt’s content with arguments.
The returned content is a SNAPSHOT: it must be copied into the agent’s instructions; it is not re-fetched at runtime. The ‘hash’ field is for tracking changes on the server.
Authorization: bearer authentication; Admin role policy when that policy is registered; AgentsRead API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
name |
path | yes | string |
— |
prompt |
path | yes | string |
— |
Request body (optional):
application/json→McpPromptArgumentsRequest
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → McpPromptContent |
— |
GET {prefix}/api/mcp-servers/{name}/resources
Section titled “GET {prefix}/api/mcp-servers/{name}/resources”Operation ID: TraconListMcpResources
Gets an MCP server’s resource list.
If the server does not advertise the ‘resources’ capability, the request is never sent.
Authorization: bearer authentication; Reader role policy when that policy is registered; AgentsRead API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
name |
path | yes | string |
— |
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → array of McpResourceSummary |
— |
GET {prefix}/api/mcp-servers/{name}/resources/read
Section titled “GET {prefix}/api/mcp-servers/{name}/resources/read”Operation ID: TraconReadMcpResource
Reads an MCP resource.
Only URIs advertised by the server’s ListResourcesAsync are accepted; an arbitrary URI is rejected because it carries an SSRF risk.
Authorization: bearer authentication; Operator role policy when that policy is registered; AgentsRead API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
name |
path | yes | string |
— |
uri |
query | yes | string |
— |
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → McpResourceContent |
— |
POST {prefix}/api/mcp-servers/refresh
Section titled “POST {prefix}/api/mcp-servers/refresh”Operation ID: TraconRefreshMcpTools
Refreshes the tool list of remote MCP servers now.
The refresh normally happens in the background at fixed intervals. This endpoint lets the tools of a newly added server appear without waiting for the next scheduled refresh.
Authorization: bearer authentication; Admin role policy when that policy is registered; AgentsAdmin API-key scope.
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → McpRefreshResponse |
— |
GET {prefix}/api/quotas
Section titled “GET {prefix}/api/quotas”Operation ID: TraconListQuotas
Lists a tenant’s quota rules.
Rules are definitions, not counters — read the counters from the usage endpoint. A rule with no agent name applies to the whole tenant, and a tenant-wide rule and an agent-specific rule can both be in force at once. A rule with ‘enabled: false’ is kept but not enforced. An agent with no matching rule is unlimited.
Authorization: bearer authentication; Admin role policy when that policy is registered; PlatformRead API-key scope.
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → array of QuotaDefinition |
— |
PUT {prefix}/api/quotas
Section titled “PUT {prefix}/api/quotas”Operation ID: TraconSaveQuota
Creates or updates a quota rule.
The scope (tenant + agent + period) is unique: writing a second rule for the same scope overwrites the existing rule. Each limit can also be left empty; only the ones that are set are enforced.
Authorization: bearer authentication; Admin role policy when that policy is registered; PlatformAdmin API-key scope.
Request body (required):
application/json→QuotaSaveRequest
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → QuotaDefinition |
— |
DELETE {prefix}/api/quotas/{id}
Section titled “DELETE {prefix}/api/quotas/{id}”Operation ID: TraconDeleteQuota
Deletes a quota rule.
Removing the last rule that covers an agent makes it unlimited, which is why the removal is written to the audit trail with the rule’s previous values. Usage counters already recorded are not deleted; they simply stop being enforced. To keep the limits but stop enforcing them, save the rule with ‘enabled: false’ instead. An unknown id returns 404.
Authorization: bearer authentication; Admin role policy when that policy is registered; PlatformAdmin API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
id |
path | yes | string (uuid) |
— |
| Response | Body | Headers |
|---|---|---|
| 204 No Content | — | — |
GET {prefix}/api/quotas/usage
Section titled “GET {prefix}/api/quotas/usage”Operation ID: TraconGetQuotaUsage
Returns the current period’s quota usage.
An empty ‘agentName’ value shows the tenant-wide counter. Counters are approximate: the check happens before a run starts, and consumption is written after it finishes.
Authorization: bearer authentication; Reader role policy when that policy is registered; PlatformRead API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
agentName |
query | no | string |
— |
period |
query | no | QuotaPeriod |
— |
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → QuotaUsageResponse |
— |
GET {prefix}/api/skill-script-grants
Section titled “GET {prefix}/api/skill-script-grants”Operation ID: TraconListSkillScriptGrants
Lists the tenant’s script run grants.
A grant is permission to execute code on the server, so this list is the authoritative answer to ‘what may run here’. A grant with no script name covers every script in that skill; one with a script name covers only that script. Entries may carry an expiry, and an expired grant no longer authorizes a run. Grants are also a retention target, so old ones are cleaned up.
Authorization: bearer authentication; Reader role policy when that policy is registered; SecurityAdmin API-key scope.
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → array of SkillScriptGrant |
— |
POST {prefix}/api/skill-script-grants
Section titled “POST {prefix}/api/skill-script-grants”Operation ID: TraconGrantSkillScript
Grants run permission to a skill script.
A grant for a skill stored in the database or registered in code pins the content it is given for: send ‘expectedContentHash’, read from GET /api/skills/{name} (scripts[].contentHash for one script, scriptSetHash when ‘scriptName’ is omitted and the grant covers every script). A missing or malformed hash returns 400, a ‘scriptName’ the skill does not carry 404, and a hash that no longer matches the content 409 - read the skill again and review it; the response never carries the current hash. A script whose content changes after the grant does not run until it is granted again. In a multi-tenant host a grant for a stored skill also needs platform authority (an API key with PlatformAdmin, the static token, or the Tracon.PlatformAdmin policy; 403 otherwise), because the script runs under the server’s own operating-system identity. A name no stored or code skill carries is granted without a pin and authorizes scripts read from disk only. A key needs AgentsRead to read the hash and SecurityAdmin to grant. Granting while script execution is switched off returns 409 rather than succeeding: a grant that reads as active but never allows a run would be misleading. ‘expiresAt’ is optional but must be in the future when given (400 otherwise); without it the grant does not expire. A refused request writes nothing; every grant is written to the audit trail.
Authorization: bearer authentication; Admin role policy when that policy is registered; SecurityAdmin API-key scope.
Request body (required):
application/json→SkillScriptGrantRequest
| Response | Body | Headers |
|---|---|---|
| 201 Created | application/json → SkillScriptGrant |
— |
DELETE {prefix}/api/skill-script-grants/{skillName}
Section titled “DELETE {prefix}/api/skill-script-grants/{skillName}”Operation ID: TraconRevokeSkillScript
Revokes a script run grant.
Revoking takes effect on the next run; a script already executing is not stopped. The optional ‘?scriptName=’ must match how the grant was created — revoking one script does not remove a skill-wide grant, and the skill-wide grant keeps authorizing that script until it too is revoked. When no matching active grant exists the response is 404.
Authorization: bearer authentication; Admin role policy when that policy is registered; SecurityAdmin API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
skillName |
path | yes | string |
— |
scriptName |
query | no | string |
— |
| Response | Body | Headers |
|---|---|---|
| 204 No Content | — | — |
GET {prefix}/api/tenants
Section titled “GET {prefix}/api/tenants”Operation ID: TraconListTenants
Lists registered tenants.
A tenant record is NOT REQUIRED. The tenant_id in other tables is the same text as this record’s slug value, but it is not connected by a foreign key; a tenant with no record does not produce an error at runtime. The list names every tenant of the installation, so it requires platform authority (403 otherwise).
Authorization: bearer authentication; Admin role policy when that policy is registered; PlatformAdmin API-key scope.
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → array of TenantDescriptor |
— |
PUT {prefix}/api/tenants/{slug}
Section titled “PUT {prefix}/api/tenants/{slug}”Operation ID: TraconSaveTenant
Adds or updates a tenant record.
The record is a display name for a tenant key that already works without it; creating one does not create the tenant and deleting one does not remove its data. The slug comes from the path and must be at most 64 characters of letters, digits, dots, underscores, and hyphens (400 otherwise) — it is the same text stored as ‘tenant_id’ on every other row, and it is folded to lower case for the same reason, so ‘Acme’ and ‘acme’ name one record. An empty display name falls back to the slug. A tenant other than the caller’s own requires platform authority (403 otherwise).
Authorization: bearer authentication; Admin role policy when that policy is registered; PlatformAdmin API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
slug |
path | yes | string |
— |
Request body (required):
application/json→TenantRequest
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → TenantDescriptor |
— |
DELETE {prefix}/api/tenants/{slug}
Section titled “DELETE {prefix}/api/tenants/{slug}”Operation ID: TraconDeleteTenant
Deletes a tenant record.
Only the record is deleted; the tenant’s agents, sessions, and runs remain. A tenant other than the caller’s own requires platform authority (403 otherwise).
Authorization: bearer authentication; Admin role policy when that policy is registered; PlatformAdmin API-key scope.
| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
slug |
path | yes | string |
— |
| Response | Body | Headers |
|---|---|---|
| 204 No Content | — | — |
GET {prefix}/api/tenants/current
Section titled “GET {prefix}/api/tenants/current”Operation ID: TraconCurrentTenant
Returns the current request’s tenant.
The tenant is resolved from the request. In a single-tenant setup, it always returns the default tenant. This endpoint is in the protected group; /api/meta does not carry tenant information.
Authorization: bearer authentication; Reader role policy when that policy is registered; no endpoint-specific API-key scope.
| Response | Body | Headers |
|---|---|---|
| 200 OK | application/json → CurrentTenantResponse |
— |