{ "openapi": "3.1.0", "info": { "title": "Hanzo Cloud API", "description": "Package guide is a step-by-step checklist that gets your business running on AI.", "version": "v1" }, "servers": [ { "url": "https://api.hanzo.ai" } ], "tags": [ { "name": "guide" } ], "paths": { "/v1/guide": { "get": { "operationId": "get_v1_guide", "summary": "Overview returns the caller org's launch journey: the active curriculum's version and title, every step with its state, whether it is available, what blocks it and whether the Business AI can run it, the done/total/percent progress with the next step to take, and the org's analytics funnel folded in.", "description": "Overview returns the caller org's launch journey: the active curriculum's\nversion and title, every step with its state, whether it is available, what\nblocks it and whether the Business AI can run it, the done/total/percent\nprogress with the next step to take, and the org's analytics funnel folded in.\nAuto-detect runs first, so a step the org has already completed elsewhere reads\ndone without anyone marking it.", "tags": [ "guide" ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/overviewView" } } }, "description": "ok" } } } }, "/v1/guide/actions": { "get": { "operationId": "get_v1_guide_actions", "summary": "Returns the caller org's Business AI action ledger, most recent first: every \"do it for me\" tool call, the arguments it ran with, its result and whether it succeeded.", "description": "Returns the caller org's Business AI action ledger, most recent\nfirst: every \"do it for me\" tool call, the arguments it ran with, its result and\nwhether it succeeded. It is the audit-visible record of what the agent did on\nthe org's behalf, and the backing state for the \"acted\" auto-detect signal.", "tags": [ "guide" ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/actionsView" } } }, "description": "ok" } } } }, "/v1/guide/analytics": { "get": { "operationId": "get_v1_guide_analytics", "summary": "Analytics returns the caller org's funnel from the analytics lens plus the GTM recommendations derived from it.", "description": "Analytics returns the caller org's funnel from the analytics lens plus the GTM\nrecommendations derived from it. It is the Business AI's data-grounded read —\nwhat the funnel is doing, and the next-best action to move its weakest stage. An\nunreachable or silent warehouse answers available=false, never a fabricated\nnumber.", "tags": [ "guide" ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/analyticsView" } } }, "description": "ok" } } } }, "/v1/guide/blueprint": { "get": { "operationId": "get_v1_guide_blueprint", "summary": "Returns the FULL authored brand blueprint — every principle, section, step, strategy and template WITH its enabled flag made explicit, including the disabled items the org-facing reads never see — plus the active version number, the brand key it is stored under and the item counts.", "description": "Returns the FULL authored brand blueprint — every principle,\nsection, step, strategy and template WITH its enabled flag made explicit,\nincluding the disabled items the org-facing reads never see — plus the active\nversion number, the brand key it is stored under and the item counts. It is the\nSuperAdmin authoring view of the platform blueprint, so it is refused 403 for\nanyone else, including a per-org admin: the brand blueprint is shared platform\ncontent, not a per-customer surface.", "tags": [ "guide" ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/blueprintView" } } }, "description": "ok" } } }, "put": { "operationId": "put_v1_guide_blueprint", "summary": "Publish a new version of the brand blueprint", "description": "Replaces the deployment's brand blueprint — the shared journey, sections, strategies and templates every org starts from — as a NEW VERSION, and answers the stored document with its key and version number. The previous versions are kept, so /blueprint/versions is a real recovery trail.\n\nSuperAdmin ONLY. A per-org admin is 403: this is platform content, not a per-customer surface — the per-customer surface is /v1/guide/curriculum. The write is audited.\n\nThe body is a blueprint document accepted as YAML **or** JSON, which is the caller-visible reason it takes a raw body. It must parse AND validate — unique ids throughout, an acyclic step graph with no dangling dependencies, every step's section and every strategy's principle resolving to a real one — or it is 422 and never becomes active, leaving the version already serving authoritative. An empty body is 400 and one over 16 MiB is 413.\n\nEdits are live: the next resolve reads the newest version. A stored document that is itself corrupt or schema-drifted does not block this write — the target is resolved without parsing what is there — so a bad version can always be published over.", "tags": [ "guide" ] } }, "/v1/guide/blueprint/versions": { "get": { "operationId": "get_v1_guide_blueprint_versions", "summary": "Returns the brand blueprint's version history — every stored version's number and edit time, newest first — which is the point-in-time-recovery and audit trail behind the authoring plane.", "description": "Returns the brand blueprint's version history — every\nstored version's number and edit time, newest first — which is the\npoint-in-time-recovery and audit trail behind the authoring plane. Metadata\nonly: the documents are not returned. SuperAdmin only, like the rest of this\nplane. The history is listable even when the current stored document no longer\nparses, so a schema-drifted row can still be diagnosed.", "tags": [ "guide" ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/blueprintVersionsView" } } }, "description": "ok" } } } }, "/v1/guide/blueprint/{collection}/{id}": { "patch": { "operationId": "patch_v1_guide_blueprint_by_collection_by_id", "summary": "Edit — or retire — one item of the brand blueprint", "description": "Edits a single item of the brand blueprint by id and saves it as a NEW VERSION, answering the whole blueprint after the edit. `collection` is one of `sections`, `steps`, `strategies` or `templates`; anything else is 400, and an id that collection does not hold is 404. This is also the retire lever: `{\"enabled\": false}` takes an item out of every org's journey without deleting it or its history.\n\nSuperAdmin ONLY, like the rest of the authoring plane; a per-org admin is 403. The write is audited.\n\nThe patch is a SHALLOW merge over the item's own top-level keys — a key you send replaces that key whole, a key you omit is left alone — and `id` is dropped from the patch before it is applied, so an edit can never rekey an item. That is why the body has no declarable shape: its keys are the patched item's, not this route's.\n\nFail-closed on the WHOLE document, not just the item: the blueprint is re-validated after the merge, so a patch that would dangle a dependency, break the step DAG or empty the journey is 422 and nothing is saved. An empty patch is 400 and one over 16 MiB is 413.", "tags": [ "guide" ], "parameters": [ { "name": "collection", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ] } }, "/v1/guide/chat": { "post": { "operationId": "post_v1_guide_chat", "summary": "Chat answers a founder's question about their launch journey as the Business AI coach: it grounds the reply in the org's REAL progress, its ranked available quests and its analytics funnel, and returns those candidate quests alongside so the caller can act on one.", "description": "Chat answers a founder's question about their launch journey as the Business AI\ncoach: it grounds the reply in the org's REAL progress, its ranked available\nquests and its analytics funnel, and returns those candidate quests alongside so\nthe caller can act on one. READ-ONLY — it advises and never runs a step, so it\ncannot be talked into performing an action; the only executing path is POST\n/v1/guide/steps/{id}/do. One AI completion per call, billed to the caller's own\npayer.", "tags": [ "guide" ], "requestBody": { "content": { "application/json": { "example": { "message": "what should I do next to get my first customers?" }, "schema": { "$ref": "#/components/schemas/chatRequest" } } }, "required": true }, "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/chatResponse" } } }, "description": "ok" } } } }, "/v1/guide/curriculum": { "delete": { "operationId": "delete_v1_guide_curriculum", "summary": "Clears the caller org's curriculum override and returns the journey it falls back to — the brand blueprint, else the embedded fixture.", "description": "Clears the caller org's curriculum override and returns the\njourney it falls back to — the brand blueprint, else the embedded fixture.\nClearing an org that never set one is a no-op that answers the same default.", "tags": [ "guide" ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/curriculumView" } } }, "description": "ok" } } }, "get": { "operationId": "get_v1_guide_curriculum", "summary": "Returns the journey the caller's org is actually running, and whether it comes from the org's OWN override (custom) or from the platform default — the brand blueprint, else the embedded fixture.", "description": "Returns the journey the caller's org is actually running, and\nwhether it comes from the org's OWN override (custom) or from the platform\ndefault — the brand blueprint, else the embedded fixture.", "tags": [ "guide" ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/curriculumView" } } }, "description": "ok" } } }, "put": { "operationId": "put_v1_guide_curriculum", "summary": "Replace your org's journey with a curriculum you author", "description": "Sets the caller org's OWN curriculum — the per-customer override — and answers the journey now in force with `custom: true`. The body is a curriculum document, and it is accepted as YAML **or** JSON: that is the caller-visible reason this takes a raw body rather than a declared shape. Whatever the syntax, the CANONICAL parsed form is what is stored, so the document the engine runs never depends on how it was written.\n\nFail-closed: a body that does not parse, or parses but is not a valid journey (unique step ids, no dangling or cyclic dependencies), is 422 and NEVER becomes active — the org keeps the journey it had. Requires a validated org; 403 without one. An empty body is 400 and one over 256 KiB is 413.\n\nThis is tier one only. It overrides nothing but this org's own journey; the shared brand blueprint is a different surface with a different gate. DELETE the same path to drop the override and fall back to it.", "tags": [ "guide" ] } }, "/v1/guide/profile": { "get": { "operationId": "get_v1_guide_profile", "summary": "Profile returns the caller org's OBSERVED growth profile — the signal set, the classified growth stage, and the org's own key metrics.", "description": "Profile returns the caller org's OBSERVED growth profile — the signal set, the\nclassified growth stage, and the org's own key metrics. It is a pure READ,\nrecomputed from the org's CURRENT state each request (real-time by pull): it\nreuses the reconcile path (snapshotFor runs the detectors) for launch progress\nand runs the growth probes (observe) for the signals — it never caches, never\nruns a billable effect, never targets another org. Org-scoped on the validated\nprincipal; fail-closed without one. It PRODUCES the profile and classifies the\nstage; it decides NO recommendation (that is a later surface).", "tags": [ "guide" ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/profileResponse" } } }, "description": "ok" } } } }, "/v1/guide/steps/{id}/do": { "post": { "operationId": "post_v1_guide_steps_by_id_do", "summary": "Have the Business AI actually do the step for you", "description": "Executes one step of the caller org's journey through that principal's OWN tool plane and answers the action log — `{step, events, state}` — so the caller sees every tool call the agent made and where the step ended up. This is the ONE executing path in guide: suggest and chat advise, this acts, and the work is charged to the calling principal's ledger.\n\nAsk for it live and the same actions arrive as Server-Sent Events instead, on either of two triggers — `Accept: text/event-stream` or `?stream=1`. The stream opens with a comment, emits one frame per action as it happens, and closes with an `end` frame carrying `ok` and the final state. The streamed run is detached and bounded at 120 seconds, so it finishes on its own clock once the response has begun.\n\nAn agent that FAILS is not a failed request: the JSON answer still comes back 200 with `error` beside the events it did manage, and the stream still ends with `ok:false`. The refusals are the ones before the agent runs — 409 with `{error, step, blockedBy}` for a step whose dependencies are unfinished, 404 for an id the journey does not contain, 403 without a validated org.", "tags": [ "guide" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ] } }, "/v1/guide/steps/{id}/done": { "post": { "operationId": "post_v1_guide_steps_by_id_done", "summary": "Mark a step of your org's journey finished", "description": "Moves one step of the caller org's journey to done and answers the whole refreshed journey, which is what unblocks everything downstream of it.\n\nDependency-GATED like start: finishing a step whose prerequisites are themselves unfinished is 409 carrying `{error, step, blockedBy}` naming what is in the way, not a silent success. A step id the org's active journey does not contain is 404. Skipping is the ungated alternative — a founder declaring a step does not apply — and it lives at /skip.\n\nRequires a validated org; 403 without one. The mark is recorded as `manual`, and /reset returns the step to todo.", "tags": [ "guide" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ] } }, "/v1/guide/steps/{id}/reset": { "post": { "operationId": "post_v1_guide_steps_by_id_reset", "summary": "Returns one step of the caller org's journey to todo — clearing a manual mark or a skip — and returns the refreshed journey.", "description": "Returns one step of the caller org's journey to todo — clearing a\nmanual mark or a skip — and returns the refreshed journey. Reset is never\ndependency-gated. Auto-detect runs on the next read, so a step the org has in\nfact completed elsewhere goes straight back to done.", "tags": [ "guide" ], "parameters": [ { "name": "id", "in": "path", "required": true, "description": "ID is the step's id, as it appears in the journey (e.g. \"gsuite\").", "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/overviewView" } } }, "description": "ok" } } } }, "/v1/guide/steps/{id}/skip": { "post": { "operationId": "post_v1_guide_steps_by_id_skip", "summary": "Marks one step of the caller org's journey skipped and returns the refreshed journey.", "description": "Marks one step of the caller org's journey skipped and returns the\nrefreshed journey. Skipping is never dependency-gated — the founder is\ndeclaring the step does not apply to them — so a step whose dependencies are\nunfinished can still be skipped, and a skipped step counts as terminal for\neverything downstream of it.", "tags": [ "guide" ], "parameters": [ { "name": "id", "in": "path", "required": true, "description": "ID is the step's id, as it appears in the journey (e.g. \"gsuite\").", "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/overviewView" } } }, "description": "ok" } } } }, "/v1/guide/steps/{id}/start": { "post": { "operationId": "post_v1_guide_steps_by_id_start", "summary": "Mark a step of your org's journey started", "description": "Moves one step of the caller org's journey to in-progress and answers the whole refreshed journey, so a console needs no second read.\n\nThe transition is dependency-GATED, and that is why the answer set is wider than a success: a step whose prerequisites are unfinished is 409 carrying `{error, step, blockedBy}`, where `blockedBy` names the exact steps in the way — enough to render the blockage rather than merely report it. A step id the org's active journey does not contain is 404.\n\nRequires a validated org; 403 without one, and the journey read and written is that org's alone. The mark is recorded as `manual`, and the journey is reconciled against the auto-detectors on every read, so a step the org has demonstrably completed elsewhere can still be moved to done underneath it.", "tags": [ "guide" ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ] } }, "/v1/guide/strategies": { "get": { "operationId": "get_v1_guide_strategies", "summary": "Strategies returns the ENABLED tactics corpus for the caller's org: the tactics library narrowed by the explicit category/workload filters AND by the org's OBSERVED growth stage and capability signals (a tactic's tags are preconditions, so it surfaces only once the org can act on it).", "description": "Strategies returns the ENABLED tactics corpus for the caller's org: the tactics\nlibrary narrowed by the explicit category/workload filters AND by the org's\nOBSERVED growth stage and capability signals (a tactic's tags are\npreconditions, so it surfaces only once the org can act on it). Passing stage\nPREVIEWS the corpus at that stage instead of the observed one. The content is\nshared platform data — no org's records — and the read is never a billable\neffect.", "tags": [ "guide" ], "parameters": [ { "name": "category", "in": "query", "required": false, "description": "Category filters to tactics in exactly this category.", "schema": { "type": "string" }, "example": "viral-coefficient" }, { "name": "stage", "in": "query", "required": false, "description": "Stage previews the corpus at a chosen growth stage\n(research|formed|launched|activated|scaling), overriding the org's observed\none. An unknown value is ignored and the observed stage stands.", "schema": { "type": "string" }, "example": "scaling" }, { "name": "workload", "in": "query", "required": false, "description": "Workload filters to tactics with exactly this workload.", "schema": { "type": "string" } } ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/corpusView" } } }, "description": "ok" } } } }, "/v1/guide/suggest": { "get": { "operationId": "get_v1_guide_suggest", "summary": "Suggest returns the caller org's next-best quests: the available, non-terminal steps of its journey ranked by how much downstream work each unblocks, each with the grounded reason it is a good next move and whether the Business AI can run it, plus the org's funnel and the GTM recommendations derived from it.", "description": "Suggest returns the caller org's next-best quests: the available, non-terminal\nsteps of its journey ranked by how much downstream work each unblocks, each with\nthe grounded reason it is a good next move and whether the Business AI can run\nit, plus the org's funnel and the GTM recommendations derived from it. A\nbest-effort AI narrative over exactly those quests and numbers is included when\nan AI plane is wired. READ-ONLY: it advises and never runs a step — the only\nexecuting path is POST /v1/guide/steps/{id}/do.", "tags": [ "guide" ], "responses": { "200": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/suggestResponse" } } }, "description": "ok" } } } } }, "components": { "schemas": { "ActionRecord": { "properties": { "args": { "type": "string" }, "createdAt": { "type": "integer" }, "err": { "type": "string" }, "id": { "type": "string" }, "ok": { "type": "boolean" }, "result": { "type": "string" }, "stepId": { "type": "string" }, "tool": { "type": "string" } }, "type": "object" }, "Blog": { "properties": { "caseStudy": { "type": "string" }, "how": { "type": "string" }, "slug": { "type": "string" }, "title": { "type": "string" }, "why": { "type": "string" } }, "type": "object" }, "Blueprint": { "properties": { "brand": { "type": "string" }, "enabled": { "type": "boolean" }, "principles": { "description": "the 64-principle spine (Zen of Hanzo archetypes)", "items": { "$ref": "#/components/schemas/Principle" }, "type": "array" }, "sections": { "items": { "$ref": "#/components/schemas/Section" }, "type": "array" }, "steps": { "items": { "$ref": "#/components/schemas/JourneyStep" }, "type": "array" }, "strategies": { "items": { "$ref": "#/components/schemas/Strategy" }, "type": "array" }, "templates": { "items": { "$ref": "#/components/schemas/Template" }, "type": "array" }, "title": { "type": "string" }, "version": { "type": "string" } }, "type": "object" }, "Curriculum": { "properties": { "steps": { "items": { "$ref": "#/components/schemas/JourneyStep" }, "type": "array" }, "title": { "type": "string" }, "version": { "type": "string" } }, "type": "object" }, "Funnel": { "properties": { "available": { "type": "boolean" }, "orders": { "type": "integer" }, "pageviews": { "type": "integer" }, "revenue": { "type": "number" }, "signups": { "type": "integer" }, "visitors": { "type": "integer" }, "windowDays": { "type": "integer" } }, "type": "object" }, "JourneyStep": { "properties": { "args": { "additionalProperties": { "type": "object" }, "type": "object" }, "deps": { "description": "Dependencies are step ids that must be done/skipped before this step is\navailable. The wire key is `deps` (the blueprint contract); the Go field keeps\nits descriptive name.", "items": { "type": "string" }, "type": "array" }, "detail": { "description": "the prose/juncture — what the Guide asks/explains here", "type": "string" }, "draft": { "type": "string" }, "draftInto": { "type": "string" }, "enabled": { "description": "Enabled is the admin on/off lever. A NIL pointer reads as ENABLED (absence ==\non): a legacy/org curriculum that omits the field keeps every step, and only an\nexplicit `enabled: false` (an admin disable) drops a step from the journey. See\non() in blueprint.go and the Blueprint.Curriculum() projection.", "type": "boolean" }, "id": { "type": "string" }, "section": { "description": "the phase (section id) this step groups under", "type": "string" }, "signal": { "description": "Signal, when set, names a machine detector (detect.go). When the detector\nreports the org's real state present, the step auto-marks done.", "type": "string" }, "title": { "type": "string" }, "tool": { "description": "Tool, when set, is the MCP tool the Business AI runs for \"do it for me\". Args\nare its default arguments; Draft is an optional AI prompt whose output fills the\nDraftInto arg (default \"brief\").", "type": "string" } }, "type": "object" }, "Principle": { "properties": { "change": { "description": "the Book of Changes reading", "type": "string" }, "domain": { "description": "the growth / go-to-market domain it governs", "type": "string" }, "hexagram": { "description": "the I-Ching hexagram (pinyin + gloss)", "type": "string" }, "n": { "description": "1..64, the hexagram number + canonical order", "type": "integer" }, "name": { "description": "the principle's short name", "type": "string" }, "principle": { "description": "the actionable growth law", "type": "string" }, "slug": { "description": "stable identifier a tactic files under", "type": "string" }, "sunTzu": { "description": "the Art of War teaching", "type": "string" } }, "type": "object" }, "Section": { "properties": { "detail": { "type": "string" }, "enabled": { "type": "boolean" }, "id": { "type": "string" }, "order": { "type": "integer" }, "title": { "type": "string" } }, "type": "object" }, "Strategy": { "properties": { "action": { "type": "string" }, "blog": { "$ref": "#/components/schemas/Blog", "description": "long-form explainer (nil for un-blogged tactics)" }, "category": { "type": "string" }, "enabled": { "type": "boolean" }, "era": { "description": "modern | heritage", "type": "string" }, "id": { "type": "string" }, "principle": { "description": "the spine slug this tactic files under", "type": "string" }, "source": { "description": "provenance / attribution", "type": "string" }, "tags": { "items": { "type": "string" }, "type": "array" }, "workload": { "type": "string" } }, "type": "object" }, "Template": { "properties": { "body": { "type": "string" }, "enabled": { "type": "boolean" }, "id": { "type": "string" }, "title": { "type": "string" } }, "type": "object" }, "VersionMeta": { "properties": { "brand": { "type": "string" }, "updatedAt": { "type": "integer" }, "version": { "type": "integer" } }, "type": "object" }, "actionsView": { "properties": { "data": { "description": "Data is the most-recent actions first, capped at listActionsLimit.", "items": { "$ref": "#/components/schemas/ActionRecord" }, "type": "array" } }, "type": "object" }, "analyticsView": { "properties": { "funnel": { "$ref": "#/components/schemas/Funnel", "description": "Funnel is the org's trailing-30-day traffic → signups → orders from the\nshared analytics warehouse; available is false when it has emitted nothing." }, "recommendations": { "description": "Recommendations are the next-best GTM actions derived from that funnel.", "items": { "type": "string" }, "type": "array" } }, "type": "object" }, "blueprintCounts": { "properties": { "principles": { "type": "integer" }, "sections": { "type": "integer" }, "steps": { "type": "integer" }, "strategies": { "type": "integer" }, "templates": { "type": "integer" } }, "type": "object" }, "blueprintVersionsView": { "properties": { "brand": { "description": "Brand is the blueprint key the history belongs to — this deployment's brand,\nor \"\" (the base blueprint) when the brand has no row of its own.", "type": "string" }, "versions": { "description": "Versions are the stored versions, newest first: metadata only, never the\ndocuments.", "items": { "$ref": "#/components/schemas/VersionMeta" }, "type": "array" } }, "type": "object" }, "blueprintView": { "properties": { "blueprint": { "$ref": "#/components/schemas/Blueprint", "description": "Blueprint is the whole authored document, including items disabled for the\norg-facing reads, with every enabled flag written out explicitly." }, "brand": { "description": "Brand is the key this blueprint is stored under — the deployment's brand, or\n\"\" for the shared base blueprint it falls back to.", "type": "string" }, "counts": { "$ref": "#/components/schemas/blueprintCounts", "description": "Counts summarises how many items each collection holds." }, "version": { "description": "Version is the active stored version number (1 is the seed). Each edit\nappends a new one; nothing is ever overwritten.", "type": "integer" } }, "type": "object" }, "chatRequest": { "properties": { "message": { "description": "Message is the founder's question for the Business AI. Required; trimmed,\nand clipped to 4 KiB so a caller cannot amplify the AI prompt.", "type": "string" } }, "type": "object" }, "chatResponse": { "properties": { "funnel": { "$ref": "#/components/schemas/Funnel", "description": "Funnel is the org's trailing-window traffic → signups → orders." }, "reply": { "description": "Reply is the coach's answer, grounded only in the quests and funnel below.\nWhen no AI plane is reachable it is the deterministic reply naming the top\nreal quest — never silence, never invention.", "type": "string" }, "suggestions": { "description": "Suggestions are the current candidate quests, ranked best-first.", "items": { "$ref": "#/components/schemas/suggestion" }, "type": "array" } }, "type": "object" }, "corpusView": { "properties": { "count": { "description": "Count is how many tactics survived every filter.", "type": "integer" }, "stage": { "description": "Stage is the growth stage the tag join ran at — the org's observed stage, or\nthe one ?stage= previewed.", "type": "string" }, "strategies": { "description": "Strategies are the surviving tactics, in corpus authoring order.", "items": { "$ref": "#/components/schemas/strategyView" }, "type": "array" } }, "type": "object" }, "curriculumView": { "properties": { "curriculum": { "$ref": "#/components/schemas/Curriculum", "description": "Curriculum is the enabled journey: its version, title and ordered steps." }, "custom": { "description": "Custom is true when the org's OWN curriculum override is active; false when\nthe journey comes from the brand blueprint or the embedded fixture.", "type": "boolean" } }, "type": "object" }, "overviewView": { "properties": { "custom": { "type": "boolean" }, "funnel": { "$ref": "#/components/schemas/Funnel" }, "progress": { "$ref": "#/components/schemas/progressView" }, "steps": { "items": { "$ref": "#/components/schemas/stepView" }, "type": "array" }, "title": { "type": "string" }, "version": { "type": "string" } }, "type": "object" }, "profileMetrics": { "properties": { "funnel": { "$ref": "#/components/schemas/Funnel" }, "launchProgress": { "$ref": "#/components/schemas/progressView" }, "records": { "type": "integer" }, "revenueCents": { "type": "integer" } }, "type": "object" }, "profileResponse": { "properties": { "keyMetrics": { "$ref": "#/components/schemas/profileMetrics" }, "signals": { "additionalProperties": { "type": "boolean" }, "type": "object" }, "stage": { "type": "string" } }, "type": "object" }, "progressView": { "properties": { "done": { "type": "integer" }, "next": { "type": "string" }, "percent": { "type": "integer" }, "total": { "type": "integer" } }, "type": "object" }, "stepView": { "properties": { "args": { "additionalProperties": { "type": "object" }, "type": "object" }, "automatable": { "description": "Automatable is true when the Business AI can run this step (it names a tool).", "type": "boolean" }, "available": { "description": "Available is true when every dependency is done or skipped.", "type": "boolean" }, "blockedBy": { "description": "BlockedBy lists the unfinished dependencies keeping the step unavailable.", "items": { "type": "string" }, "type": "array" }, "deps": { "description": "Dependencies are step ids that must be done/skipped before this step is\navailable. The wire key is `deps` (the blueprint contract).", "items": { "type": "string" }, "type": "array" }, "detail": { "description": "Detail is the prose/juncture — what the Guide asks or explains here.", "type": "string" }, "draft": { "type": "string" }, "draftInto": { "type": "string" }, "enabled": { "description": "Enabled is the admin on/off lever; absent reads as enabled.", "type": "boolean" }, "id": { "description": "ID is the step's id, as it appears in the journey (e.g. \"gsuite\").", "type": "string" }, "section": { "description": "Section is the phase (section id) this step groups under.", "type": "string" }, "signal": { "description": "Signal names the machine detector that auto-marks this step done.", "type": "string" }, "source": { "description": "Source records what marked the state: manual, auto (detected) or agent.", "type": "string" }, "state": { "description": "State is the step's per-org lifecycle state: todo|in_progress|done|skipped.", "type": "string" }, "title": { "type": "string" }, "tool": { "description": "Tool is the MCP tool the Business AI runs for \"do it for me\"; Args are its\ndefault arguments, Draft an optional AI prompt whose output fills the\nDraftInto arg (default \"brief\").", "type": "string" } }, "type": "object" }, "strategyView": { "properties": { "action": { "type": "string" }, "category": { "type": "string" }, "id": { "type": "string" }, "tags": { "items": { "type": "string" }, "type": "array" }, "workload": { "type": "string" } }, "type": "object" }, "suggestResponse": { "properties": { "funnel": { "$ref": "#/components/schemas/Funnel", "description": "Funnel is the org's trailing-window traffic → signups → orders." }, "narrative": { "description": "Narrative is the AI's grounded prose over those quests and numbers. Absent\nwhen no AI plane is wired or the completion failed — never fabricated.", "type": "string" }, "next": { "description": "Next is the id of the single next step the static journey names — the\nlinear answer the ranked Suggestions refine.", "type": "string" }, "recommendations": { "description": "Recommendations are the next-best GTM actions derived from that funnel.", "items": { "type": "string" }, "type": "array" }, "suggestions": { "description": "Suggestions are the available, non-terminal quests ranked best-first by how\nmuch downstream work each unblocks.", "items": { "$ref": "#/components/schemas/suggestion" }, "type": "array" } }, "type": "object" }, "suggestion": { "properties": { "automatable": { "type": "boolean" }, "detail": { "type": "string" }, "rationale": { "type": "string" }, "stepId": { "type": "string" }, "title": { "type": "string" }, "unlocks": { "description": "Unlocks is how many downstream steps completing this one immediately makes\navailable (its leverage) — the primary ranking key.", "type": "integer" } }, "type": "object" } } } }