Everything you need to integrate Unaka into your agent.
UNAKA API — MACHINE READABLE SPEC
Version: 2
ENDPOINT: POST https://api.unaka.io/plan
AUTH: X-API-Key: <key> OR Authorization: Bearer <key>
CONTENT-TYPE: application/json
REQUEST (minimal):
intent: string (required)
provider: string (required) — see PROVIDERS below
REQUEST (full):
intent: string
provider: string
context:
plan: (optional) — pre-fetched entity data for resolution
teams[]: { id, name }
members[]: { id, name }
labels[]: { id, name }
cycles[]: { id, name, active }
observe: (optional) — traceability, never affects plan
agent_id, agent_name, session_id,
previous_plan_id, user_id
RESPONSE STATUS VALUES:
ready_to_hydrate — actions[] populated. Substitute
{{context.plan.*}} and {{PROVIDER_API_KEY}}
placeholders then execute.
missing_information — prerequisites[] lists required fields
that cannot be fetched automatically.
Agent must supply.
not_supported — no catalog match. similar[] shows nearby
supported workflows. Gap logged automatically.
parsing_failed — confidence too low. candidates[] shows
closest matches to retry with.
READY_TO_HYDRATE RESPONSE:
plan_id, status, workflow, confidence
actions[]: method, endpoint, headers, body, outputs
suggestions[]: field, hint (optional, non-blocking)
PLACEHOLDER TYPES IN BODY:
{{LINEAR_API_KEY}} — provider auth, from your environment
{{context.plan.team_id}} — resolved from context.plan
"Login timeout bug" — resolved by Unaka from intent
1 — auth-free translation (urgent → 1)
MISSING_INFORMATION RESPONSE:
plan_id, status, workflow, confidence
prerequisites[]: field, type, required, reason, hint, resolution
Unresolved entity refs appear inline in body:
{ "unresolved": true, "hint": "docs", "field": "label_id",
"reason": "needs_workspace_context" }
NOT_SUPPORTED RESPONSE:
status, message
similar[]: workflow, description
PARSING_FAILED RESPONSE:
status, message
candidates[]: workflow, confidence, description
EXECUTION LOOP:
outputs = {}
for i, action in enumerate(plan.actions):
headers = substitute(action.headers, env, outputs)
body = substitute(action.body, env, outputs)
response = http(action.method, action.endpoint,
headers, body)
if response.errors: raise ExecutionError
for name, path in action.outputs:
outputs[i][name] = resolve_dot_path(response, path)
PLACEHOLDER SUBSTITUTION:
{{PROVIDER_API_KEY}} — from environment
{{actions[N].outputs.key}} — output from prior action N
{{context.plan.field}} — from context.plan object
CALLBACK: POST /plan/result
plan_id, success, error_code?, provider_error?
Fire-and-forget. Never block execution on this.
PROVIDERS (19):
linear, github, hubspot, slack, notion, stripe, sentry,
resend, intercom, customerio, attio, airtable, neon,
railway, cloudflare, clerk, posthog, supabase, vercel