Documentation

Everything you need to integrate Unaka into your agent.

For humansFor agents
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