Plugin API

For connector developers (Rhino, SketchUp …). Base URL https://zanatio.talivio.com/api/plugin/v1. JSON in, JSON out. Send Accept-Language for messages in the user's language. Breaking changes get /v2; new fields and endpoints stay in v1.

1. Sign in (device code, RFC 8628 field names)

POST /link/start   { "host": "rhino", "device_name": "WORKSTATION-3", "version": "0.15.4" }
→ { "device_code": "…48 chars…", "user_code": "ABCD-2345",
    "verification_uri": "https://zanatio.talivio.com/link",
    "verification_uri_complete": "https://zanatio.talivio.com/link?code=ABCD-2345",
    "expires_in": 600, "interval": 3 }

POST /link/poll    { "device_code": "…" }
→ { "status": "pending" | "expired" | "denied" }
→ { "status": "approved", "token": "1|…", "user": {…}, "entitlements": {…}, "limits": {…}, "latest_version": "0.15.4" }

Show the user_code (and a QR of verification_uri_complete) in the plugin; poll every interval seconds. The token is handed over once. Store it in the OS credential store and send Authorization: Bearer <token>. The token only opens the plugin API.

2. Account and licence

GET /me        → user, teams, entitlements, limits, latest_version, download_url
GET /license   → { "valid": true, "entitlements": { "pro": { "active", "source", "updates_until" }, "assistant", "agent", "plan", "team" },
                   "lease": { "token": "<payload>.<signature>", "expires_at": "…" } | null,
                   "lease_public_key": "…" }
POST /logout   → revokes this token

Call /license once a day. The lease is an Ed25519-signed, base64url JSON payload (sub, host, pro, assistant, agent, updates_until, iat, exp). Verify it with the public key embedded in the plugin and keep Pro features open until exp when offline. 401/403 → sign the user out.

3. Work plan (Assistant)

POST /plan
{
  "message": "Move the shelves 4 mm forward and use a push-button latch",
  "effort": "low" | "normal" | "high",          // → gateway tier cheap | standard | smart
  "locale": "en" | "tr" | "et",
  "context": {
    "protocol": 1,
    "ops": ["hello", "library.list", "dolap.roles", "dolap.propose"],   // engine hello.ops
    "library": {                                                          // engine library.list per category
      "dolap":   [{ "id": "cevahir-ornek-dolap", "name": "…", "params": [{ "id": "raf_on_bosluk", "label": "Shelf front gap", "unit": "mm", "value": 6 }] }],
      "mentese": [{ "id": "…", "name": "…", "params": [] }],
      "mandal":  [{ "id": "mandal-pushbutton", "name": "Push button", "params": [] }]
    },
    "current": { "op": "dolap.propose", "params": { "profile": "cevahir-ornek-dolap", "profile_overrides": { "raf_on_bosluk": 6 } } }
  }
}

Responses: 200 ok with plan; 422 invalid (the plan failed validation twice — nothing to draw); 402 limited / plan_required; 429 limited / limit_reached (see usage.limits); 503 unavailable (gateway down — say so, change nothing). Each step's params already include current: pass them to the engine as they are, run the checks, show the result, and write only after the user presses Apply. See How work plans work.

4. Usage and jobs

GET  /usage   → { "limits": { "five_hours": { used, limit, resets_at, warning }, "week": {…}, "extra": { enabled, points }, "pilot" } }
GET  /jobs    → the team's agent jobs (workshop role: delivered only)
POST /jobs    { "title", "brief", "branch" }   → 201 { job: { id, status, url } } · 402 without the Agent plan