diff --git a/.spec-lock b/.spec-lock index 32433f33a..1b1e189cf 100644 --- a/.spec-lock +++ b/.spec-lock @@ -1,4 +1,4 @@ -ref=e50c01a6c94ef0d7de7876fb55b182f595bbcf50 -sha256=579538863b33b1bb84f710517581b4a40cd71871354f69a3744b995d563e17c8 +ref=11a2361f30c58bd1a7bd742c0147e84445f76956 +sha256=49bbb029bb0b532cdca11a1298959b434e34414b7e85c684cfe17a0cd23e94ef repo=hanzo-inc/cloud path=openapi.yaml diff --git a/LLM.md b/LLM.md index 08aa9e68b..4ecc57e11 100644 --- a/LLM.md +++ b/LLM.md @@ -1343,8 +1343,12 @@ a projection that repairs its source hides the defect at the one place it can be - **A catch-all positional is named `wildcard1` where one exists.** `openapi.translate` names an unnamed fiber `*` `{wildcardN}`, so `hanzo kms secrets get ` is what a person saw where it used to read `` — - that spelling came from the hand-authored master and went with it. Today's - document carries no `{wildcardN}` at all, so no command shows one. The name is + that spelling came from the hand-authored master and went with it. Since cloud + v8.5.1036 the public document carries the TYPED tail ops (hanzo-inc/cloud#559: + only an untyped wildcard is a relay), so `kms secrets get|rm `, + `s3 buckets objects get|rm`, `space drives files get|set|rm` and `sbom get` show + one; `kms secrets get` reads one value and `list` lists. genspec counts + `/v1/sbom/{wildcard1}` as a door because it sits at product depth. The name is honest where it appears (the router really has a nameless catch-all there) and the fix is upstream in zip's translate, which should give the artifact a conventional name. The CLI must not rename it locally: a projection that improves its source's diff --git a/spec/cloud.json b/spec/cloud.json index 85a36a24f..1a0139775 100644 --- a/spec/cloud.json +++ b/spec/cloud.json @@ -1 +1 @@ -{"components":{"schemas":{"Brief":{"properties":{"batch":{"items":{"type":"string"},"type":"array"},"format":{"type":"string"},"glossary":{"additionalProperties":{"type":"string"},"type":"object"},"model":{"type":"string"},"source":{"type":"string"},"target":{"type":"string"},"text":{"type":"string"},"tier":{"type":"string"}},"required":["target"],"type":"object"},"CaptureBatch":{"properties":{"batch":{"items":{"$ref":"#/components/schemas/CaptureEvent"},"type":"array"},"events":{"items":{"$ref":"#/components/schemas/CaptureEvent"},"type":"array"}},"type":"object"},"CaptureEvent":{"properties":{"anonymousId":{"type":"string"},"channel":{"type":"string"},"clip":{"$ref":"#/components/schemas/ClipBody"},"currency":{"type":"string"},"distinctId":{"type":"string"},"environment":{"type":"string"},"error":{"$ref":"#/components/schemas/Exception"},"event":{"type":"string"},"groupId":{"type":"string"},"groupType":{"type":"string"},"kind":{"type":"string"},"lastUtm":{"$ref":"#/components/schemas/UTM"},"level":{"type":"string"},"library":{"type":"string"},"libraryVersion":{"type":"string"},"log":{"$ref":"#/components/schemas/LogBody"},"messageId":{"type":"string"},"metric":{"$ref":"#/components/schemas/MetricBody"},"path":{"type":"string"},"personId":{"type":"string"},"product":{"type":"string"},"productId":{"type":"string"},"properties":{"additionalProperties":{},"type":"object"},"quantity":{"type":"integer"},"refCode":{"type":"string"},"referrer":{"type":"string"},"release":{"type":"string"},"resource":{"type":"string"},"revenue":{"type":"number"},"service":{"type":"string"},"sessionId":{"type":"string"},"signupWeek":{"type":"string"},"site":{"type":"string"},"span":{"$ref":"#/components/schemas/SpanBody"},"spanId":{"type":"string"},"timestamp":{"type":"string"},"traceId":{"type":"string"},"type":{"type":"string"},"url":{"type":"string"},"utm":{"$ref":"#/components/schemas/UTM"}},"type":"object"},"CartItemSet":{"properties":{"id":{"description":"ID is the cart to amend, from the path.","type":"string"},"product":{"description":"Product names the catalog product to set, by its id or its URL slug. Give\nthis or Variant, never both; a request naming neither is refused.","type":"string"},"quantity":{"description":"Quantity is how many of that item the cart should hold AFTER this call — it\nis the resulting count, not a delta, so sending 3 twice leaves 3 and not 6.\nZERO REMOVES the line, which is the only way to take an item out.","format":"int64","type":"integer"},"variant":{"description":"Variant names the specific sellable variant to set, by its id or its SKU.\nPrefer it over Product for anything sold in sizes, colours or tiers — the\nprice and the stock are the variant's, not the product's.","type":"string"}},"type":"object"},"CartOpen":{"properties":{"currency":{"description":"Currency is the ISO 4217 code the cart is priced in, lower-cased. Empty\nmeans usd.","type":"string"},"email":{"description":"Email is the shopper's address, for a cart that belongs to someone who has\nnot signed in. It is what a guest checkout and an abandoned-cart follow-up\nkey on. Empty is fine.","type":"string"},"store":{"description":"Store is the storefront this cart is being filled on. Empty uses the org's\ndefault store, which is what a single-storefront merchant always wants.","type":"string"},"user":{"description":"User is the id of the signed-in shopper this cart belongs to, when there is\none. Empty means a guest cart identified only by its own id.","type":"string"}},"type":"object"},"ChatTurn":{"properties":{"assets":{"items":{"type":"string"},"type":"array"},"brand":{"type":"string"},"message":{"type":"string"},"model":{"type":"string"},"thread":{"type":"string"}},"type":"object"},"ClipBody":{"properties":{"bytes":{"type":"integer"},"duration":{"type":"integer"},"object":{"type":"string"}},"type":"object"},"CorrectIn":{"properties":{"answer":{"description":"Answer is the right option label; a score's level may be named by its\nindex.","type":"string"},"cohort":{"description":"Cohort groups corrections the org files together.","type":"string"},"decision":{"description":"Decision is the decision's id.","type":"string"},"note":{"description":"Note says why, for the person reading it later.","type":"string"},"question":{"description":"Question is the question's key.","type":"string"}},"type":"object"},"Exception":{"properties":{"frames":{"items":{"$ref":"#/components/schemas/Frame"},"type":"array"},"handled":{"type":"boolean"},"message":{"type":"string"},"stack":{"type":"string"},"type":{"type":"string"}},"type":"object"},"Frame":{"properties":{"column":{"type":"integer"},"file":{"type":"string"},"function":{"type":"string"},"line":{"type":"integer"}},"type":"object"},"LogBody":{"properties":{"body":{"type":"string"},"number":{"type":"integer"},"severity":{"type":"string"}},"type":"object"},"MCPRequest":{"properties":{"id":{},"jsonrpc":{"type":"string"},"method":{"type":"string"},"params":{"additionalProperties":{},"type":"object"}},"type":"object"},"MetricBody":{"properties":{"labels":{"additionalProperties":{},"type":"object"},"name":{"type":"string"},"value":{"type":"number"}},"type":"object"},"PagesDeploy":{"properties":{"branch":{"type":"string"}},"type":"object"},"SpanBody":{"properties":{"duration":{"type":"integer"},"id":{"type":"string"},"kind":{"type":"string"},"parent":{"type":"string"},"status":{"type":"string"},"trace":{"type":"string"}},"type":"object"},"UTM":{"properties":{"campaign":{"type":"string"},"content":{"type":"string"},"medium":{"type":"string"},"source":{"type":"string"},"term":{"type":"string"}},"type":"object"},"account.appearance":{"properties":{"accent":{"description":"Accent is the one hue — a CSS colour token (a hex, or a bounded functional\ncolour like rgb()/oklch()). Anything else is dropped rather than stored.","type":"string"},"density":{"description":"Density is the spacing step: \"compact\", \"default\" or \"comfortable\".","type":"string"},"type":{"description":"Type is the text-size multiplier, clamped to the ramp window [0.85, 1.4].\nAbsent (0) leaves the published default.","format":"double","type":"number"}},"type":"object"},"account.keyBudget":{"properties":{"month":{"description":"Month is per calendar month, UTC.","format":"int64","type":"integer"},"total":{"description":"Total is over the key's whole life.","format":"int64","type":"integer"}},"type":"object"},"account.keyEdit":{"properties":{"budget":{"$ref":"#/components/schemas/account.keyBudget","description":"Budget replaces the key's spend caps, in cents; a zero drops that cap."},"expires":{"description":"Expires replaces when the key stops working, RFC 3339. An empty string means\nnever.","type":"string"},"id":{"description":"ID is the key to edit, from the path.","type":"string"},"limit":{"description":"Limit replaces what the key may reach. An empty list makes it unrestricted.","items":{"type":"string"},"type":"array"},"name":{"description":"Name relabels the key.","type":"string"},"rate":{"description":"Rate replaces the key's requests a minute; zero drops the limit.","format":"int64","type":"integer"}},"type":"object"},"account.keyIn":{"properties":{"budget":{"$ref":"#/components/schemas/account.keyBudget","description":"Budget caps what the key may spend on models, in cents, per calendar month\nand in all; a request past either is refused 402. Omitted means no cap."},"expires":{"description":"Expires is when the key stops working, RFC 3339. Omitted means never.","type":"string"},"limit":{"description":"Limit narrows what the key may reach, as `kind:name` entries: `model:zen5`,\n`project:acme`, `product:commerce`, or `model:*` for a whole kind. It only\never NARROWS — a key never reaches further than the person who made it.\nOmitted makes an unrestricted key.\n\nExample: {\"name\": \"ci\", \"limit\": [\"model:zen5\", \"project:acme\"]}","items":{"type":"string"},"type":"array"},"name":{"description":"Name labels the key. Omitted names it \"key N\".","type":"string"},"rate":{"description":"Rate caps the key's requests a minute; past it a request is refused 429.\nOmitted means no limit of its own.","format":"int64","type":"integer"},"type":{"description":"Type is the key class: \"secret\" (sk-, session-equivalent, belongs on a\nserver) or \"publishable\" (pk-, org-identifying, safe in a browser bundle).\nOmitted means secret.","type":"string"}},"type":"object"},"account.onboardReq":{"properties":{"name":{"description":"Name is the organization's display name. Ignored when personal is true, which\nderives the name from the caller's own username instead.","type":"string"},"personal":{"description":"Personal marks the organization as the caller's own space: the name is\nderived from their username and the slug auto-suffixes to stay unique.","type":"boolean"}},"type":"object"},"ad.campaignInput":{"properties":{"account":{"description":"Account is the provider ad-account this campaign runs on (Meta act_). Optional.","type":"string"},"budget":{"description":"Budget is the campaign budget in MINOR units (cents). Negative values clamp to 0.","format":"int64","type":"integer"},"name":{"description":"Name is the campaign's display label. Required; trimmed and bounded to 1024 bytes.","type":"string"},"objective":{"description":"Objective is the campaign goal as the provider names it. Optional, bounded to 1024 bytes.","type":"string"},"platform":{"description":"Platform is the ad network: meta, google, tiktok or x. Empty defaults to meta.","type":"string"},"spend":{"description":"Spend is the amount spent so far in MINOR units (cents). Negative values clamp to 0.","format":"int64","type":"integer"},"status":{"description":"Status is the lifecycle state: draft, active, paused or completed. Empty defaults to draft.","type":"string"}},"type":"object"},"ad.updateCampaignIn":{"properties":{"account":{"description":"Account is the provider ad-account this campaign runs on (Meta act_). Optional.","type":"string"},"budget":{"description":"Budget is the campaign budget in MINOR units (cents). Negative values clamp to 0.","format":"int64","type":"integer"},"name":{"description":"Name is the campaign's display label. Required; trimmed and bounded to 1024 bytes.","type":"string"},"objective":{"description":"Objective is the campaign goal as the provider names it. Optional, bounded to 1024 bytes.","type":"string"},"platform":{"description":"Platform is the ad network: meta, google, tiktok or x. Empty defaults to meta.","type":"string"},"spend":{"description":"Spend is the amount spent so far in MINOR units (cents). Negative values clamp to 0.","format":"int64","type":"integer"},"status":{"description":"Status is the lifecycle state: draft, active, paused or completed. Empty defaults to draft.","type":"string"}},"type":"object"},"affiliate.applyRequest":{"properties":{"requestedCode":{"description":"RequestedCode is the vanity code the applicant asks for; approval may mint\na different one if it is taken. Body-only: the URL cannot supply it.","type":"string"}},"type":"object"},"affiliate.attributeRequest":{"properties":{"code":{"description":"Code is the affiliate code the referred org arrived with. Body-only: the\nURL cannot supply it.","type":"string"}},"type":"object"},"affiliate.clickRequest":{"properties":{"code":{"description":"Code is the share-link code that was clicked. Body-only: the URL cannot\nsupply it.","type":"string"}},"type":"object"},"affiliate.createLinkRequest":{"properties":{"code":{"description":"Code is an optional vanity code; it must be free across the whole\ndirectory, and omitting it mints a random one. Body-only.","type":"string"},"label":{"description":"Label is cosmetic — trimmed, stripped of control characters, capped — and\nnever part of a code. Body-only: the URL cannot supply it.","type":"string"}},"type":"object"},"affiliate.handleRequest":{"properties":{"handle":{"description":"Handle is the public leaderboard display name; empty opts out. Body-only:\nthe URL cannot supply it.","type":"string"}},"type":"object"},"agent.CodingExtendIn":{"properties":{"seconds":{"description":"Seconds is how much to add to the time the run is held to. It is added to\nwhat the run has left, up to the longest a run may be given, so asking for\nmore than that is answered with what the run got.","format":"int64","type":"integer"},"session":{"description":"Session is the run's handle, from the path.","type":"string"}},"type":"object"},"agent.CodingPullIn":{"properties":{"base":{"description":"Base is the branch to propose into. Empty is the branch the run started from.","type":"string"},"body":{"description":"Body is its description. Empty says who it is for, the task, the branch and\nthe run it came from.","type":"string"},"draft":{"description":"Draft opens it as a draft, which a reviewer cannot merge until it is ready.","type":"boolean"},"session":{"description":"Session is the run's handle, from the path.","type":"string"},"title":{"description":"Title is the pull request's title. Empty takes one from the run's task.","type":"string"}},"type":"object"},"agent.CodingStartIn":{"properties":{"after":{"description":"After names a previous run's session, and starts this one from where that\none stopped instead of from the repository's default. It is how a follow-up\ninstruction — \"now add tests for it\" — builds on work already done rather\nthan beginning again on a fresh clone: the follow-up resumes the earlier\nrun's sandbox and works in its tree, files, installs and all, while that\nsandbox is kept; one reaped by then is cloned again from the earlier branch.\n\nThe follow-up writes the SAME branch the earlier run did, on top of its\ncommits, so one piece of work is one branch and one pull request however\nmany instructions it takes. It pushes without force, so it only ever adds to\nthat branch. When the earlier run was on another repository, or kept its work\nlocal, there is no branch to carry on and the follow-up writes a new one.\nBranch names the branch instead.\n\nA caller who already knows the branch may pass Base directly. Base wins if\nboth are given.","type":"string"},"agentRef":{"description":"AgentRef names a configured agent to run as, which is how an org pins a\nharness, a model and a prompt to a name. Empty runs the default agent.","type":"string"},"base":{"description":"Base is the branch to start from. Empty takes the repository's default. The\nrun never writes here — it writes the agent branch it answers with.","type":"string"},"branch":{"description":"Branch names the branch the run writes, as `agent/`: pass the name\nalone, or with the prefix. Runs write only under `agent/`, never to Base or\nto the default branch, so the name is letters, digits, `.`, `_` and `-`.\nEmpty takes `agent/` and the first part of the run's session id, or the\nearlier run's branch when After names one.\n\nA branch that already exists on the repository is carried on, not replaced:\nthe run starts from it and adds commits, and its pull request is the one it\nalready has.","type":"string"},"desktop":{"description":"Desktop asks for a run with a SCREEN — an image carrying an X server — for a\ntask that has to drive a browser or another windowed program. False, the\ndefault, is a headless checkout, which is what writing code needs.","type":"boolean"},"effort":{"description":"Effort is how hard that model reasons: low, medium or high. Empty takes the\nmodel's own default. Taken by the dev and codex harnesses, like Model.","type":"string"},"issue":{"description":"Issue is the number of the issue on Repo this run resolves. Its pull\nrequest says `Closes #`, so merging the work closes the issue. Zero is a\nrun no issue asked for.","format":"int64","type":"integer"},"mode":{"description":"Mode is what the run may do to the repository: `build` edits, commits and\npushes its branch; `plan` reads the repository and answers with a plan,\nwriting nothing — its sandbox is handed a credential that can only read and\nno push step runs, and the plan arrives as the run's final status. `setup`\nis a plan put to one question: its agent explores the checkout, installs and\nchecks what it finds, and ends with the codebase's environment, which is kept\nas the proposal at /v1/environment/{repo} until someone saves it. Empty is\n`build`. A plan or a setup runs in our sandbox only: a claimed machine clones\nand pushes with its own credential, so one routed to a machine is refused.","type":"string"},"model":{"description":"Model is the model the run's agent thinks with, by the id GET /v1/models\nlists. Empty takes the platform's coding model. The dev and codex harnesses\ntake it; the others do not think with a model we name, so naming one for\nthem is refused.","type":"string"},"project":{"description":"Project scopes the run to one board's work when the org keeps more than one.\nEmpty is the org's default.","type":"string"},"prompt":{"description":"Prompt is the task, in the words you would use with a colleague who has the\ncheckout open. It is the whole instruction: there is no second field for\ncontext, and a prompt that names files and the outcome it wants gets a run\nthat does not have to guess either.","type":"string"},"pull":{"description":"Pull is whether the run opens a pull request for what it pushed. Unset, it\npushes the branch and opens none: a pull request is the step after the work,\ntaken when it is ready, and a run resumed with `after` adds to the same branch.\nTrue opens one when the run changed something.","type":"boolean"},"reply":{"$ref":"#/components/schemas/agent.Reply","description":"Reply is WHERE THE RUN NARRATES ITSELF, when the surface that started it has\nsomewhere for it to talk. Empty means nobody is listening and the run simply\ndoes not narrate — which is the app surface's case, because /v1/agent/coding\nhands back a session id and the session stream is a better progress feed than\nany message could be.\n\nIT IS NOT A FIELD A MODEL FILLS IN. A run asked for in a conversation is\ndispatched with the address that conversation is happening at, written over\nwhatever arrived here (apps/agents/replyto.go). A model naming a channel is\na model naming a channel it was not spoken to in, so the value it chose is\ndiscarded rather than argued with — which is the same rule that left the org\nand the subject off this type entirely."},"repo":{"description":"Repo is what to work on: a repository's name, `owner/name` in the caller's\nown org, or the site a repository serves (`hanzo.ai`), as the person said\nit. The engine resolves it against the org's own repositories — a name that\nmatches none is refused with the nearest ones — and finds the clone URL and\nthe push credential from the org itself, so this says WHICH repository and\nnever how to reach it.\n\nA repository on GitHub is named by GitHub's address, `github.com/owner/name`\n— or `owner/name` when the owner is not the org's own — and runs there\ndirectly: it is admitted when the caller's own connected GitHub may push to\nit, or when the caller administers the org and the org's installation holds\nit, and refused otherwise.\n\nA repository the caller can read and not push to — a public repository, or\none their GitHub reads — is cloned read-only: the run works, commits in its\nworkspace, and pushes nothing; its change is kept as the run's artifacts.\n\nEmpty runs in an empty workspace: a fresh git repository in the sandbox,\nwith nothing cloned and nothing pushed.","type":"string"},"targetId":{"description":"TargetID routes the run to a registered machine the org has claimed instead\nof to a sandbox in our cluster. Empty runs it here, which is the usual case.","type":"string"},"task":{"description":"Task is Prompt under the name a caller asking for work tends to reach for.\nThe two are one field: Prompt wins when both are given.","type":"string"},"timeoutSeconds":{"description":"TimeoutSeconds bounds the whole run. Unset takes the default budget; a run\nthat hits the bound is stopped and reports what it had done by then.","format":"int64","type":"integer"},"tool":{"description":"Tool is which harness runs the prompt — dev | claude | codex | python |\nnode — and Desktop is whether the run needs a screen. Both are empty by\ndefault, which is `dev` with no screen, and that default is what every\ncaller gets until it says otherwise.\n\nThey are two fields because they are two questions. The harness decides\nwhat argv starts; the screen decides which image carries an X server. A\ncaller may want claude WITH a browser it can see, and a single enum would\nhave made that combination unsayable.","type":"string"}},"type":"object"},"agent.GPU":{"properties":{"memory":{"description":"VRAM bytes, 0 = unknown","format":"int64","type":"integer"},"model":{"description":"\"GB10\", \"8060S\", \"RTX 4090\"","type":"string"},"vendor":{"description":"nvidia | amd | apple | intel | ...","type":"string"}},"type":"object"},"agent.Metrics":{"properties":{"at":{"description":"unix seconds, server-stamped","format":"int64","type":"integer"},"cpuTemp":{"description":"CPUTemp is the CPU package temperature in °C.","format":"double","type":"number"},"cpuUtil":{"description":"CPUUtil is the busy fraction of all cores over the sample window, 0..1.","format":"double","type":"number"},"decode":{"description":"Decode is generation throughput over the sample window, in tokens per second.","format":"double","type":"number"},"diskRead":{"description":"DiskRead is the block-device read rate in bytes per second.","format":"double","type":"number"},"diskTotal":{"description":"DiskTotal is the size of those filesystems, in bytes.","format":"int64","type":"integer"},"diskUsed":{"description":"DiskUsed is the space used across local block filesystems, in bytes.","format":"int64","type":"integer"},"diskWrite":{"description":"DiskWrite is the block-device write rate in bytes per second.","format":"double","type":"number"},"gpuMemTotal":{"description":"GPUMemTotal is dedicated VRAM in bytes; absent when the GPU shares system memory (unified).","format":"int64","type":"integer"},"gpuMemUsed":{"description":"GPUMemUsed is the memory held by GPU processes, in bytes.","format":"int64","type":"integer"},"gpuPower":{"description":"GPUPower is the total GPU power draw in watts.","format":"double","type":"number"},"gpuPowerLimit":{"description":"GPUPowerLimit is the total enforced GPU power limit in watts; absent when the driver reports none.","format":"double","type":"number"},"gpuTemp":{"description":"GPUTemp is the hottest GPU's temperature in °C.","format":"double","type":"number"},"gpuUtil":{"description":"0..1 aggregate utilization","format":"double","type":"number"},"kvCache":{"description":"KVCache is the KV-cache occupancy, 0..1.","format":"double","type":"number"},"load1":{"description":"Load1 is the machine's own one-minute load average — a count of runnable and\nuninterruptible tasks, NOT a percentage and NOT already divided by core\ncount, so it is read against Spec.CPUs: 8.0 is idle on 16 cores and swamped\non 4. Coerced finite and non-negative on write, so 0 means either genuinely\nidle or nothing reported.","format":"double","type":"number"},"load15":{"description":"Load15 is the same figure over fifteen. The three together are what separate\na machine that is busy right now from one that has been busy all along —\nwhich is the question a dispatcher is really asking.","format":"double","type":"number"},"load5":{"description":"Load5 is the same figure averaged over five minutes.","format":"double","type":"number"},"memFree":{"description":"bytes","format":"int64","type":"integer"},"memUsed":{"description":"bytes","format":"int64","type":"integer"},"model":{"description":"Model is the model id(s) served on this machine, comma-separated, at most 128 bytes.","type":"string"},"netRx":{"description":"NetRx is the receive rate of physical interfaces in bytes per second.","format":"double","type":"number"},"netTx":{"description":"NetTx is the transmit rate of physical interfaces in bytes per second.","format":"double","type":"number"},"prefill":{"description":"Prefill is prompt (prefill) throughput over the sample window, in tokens per second.","format":"double","type":"number"},"running":{"description":"Running is the number of requests being served now.","format":"int64","type":"integer"},"ttft":{"description":"TTFT is the mean time to first token, in seconds, of requests that started in the window.","format":"double","type":"number"},"waiting":{"description":"Waiting is the number of requests queued.","format":"int64","type":"integer"}},"type":"object"},"agent.Reply":{"properties":{"channel":{"description":"Channel is the conversation inside that workspace, and it is what decides whether\nthere is an address at all. Empty is the ordinary case: a caller of\n/v1/agent/coding holds a session id and reads the stream instead.","type":"string"},"provider":{"description":"Provider is the transport the conversation is on — slack, discord,\ntelegram, teams — and it is what decides who can carry the text at all. An\naddress without it names a channel in no particular workspace.","type":"string"},"thread":{"description":"Thread narrows the address to one thread inside the channel — on Slack the\nparent message's ts, the same value a reply carries as thread_ts. Empty\nputs the text at the top level of the channel.","type":"string"},"turn":{"description":"Turn is the turn that renders a run started here: the session whose one\nmessage the run's progress and its outcome are shown in. A run with a Turn\nposts nothing of its own — one question, one message. The dispatcher writes\nit (apps/agents/replyto.go); a model never does.","type":"string"},"user":{"description":"User is the platform's id for the person the conversation is with — whose\nrun it is. A run's buttons name them to anyone else who presses one; it is\nnever what decides who may (that is the chat identity).","type":"string"}},"type":"object"},"agent.Spec":{"properties":{"arch":{"description":"amd64 | arm64 | ...","type":"string"},"cpus":{"description":"logical cores","format":"int64","type":"integer"},"gpus":{"description":"GPUs is every accelerator the machine advertises, one entry each, capped at\n32 on write. Empty means the probe found none — and that is the answer a\nNeed is checked against, so a machine with no entry here clears no\naccelerator floor. The list is not vendor-filtered: what satisfies a job is\ncounts and VRAM, never a brand (see Need).","items":{"$ref":"#/components/schemas/agent.GPU"},"type":"array"},"memory":{"description":"total RAM, bytes","format":"int64","type":"integer"},"os":{"description":"linux | darwin | windows","type":"string"}},"type":"object"},"agent.codingInstruction":{"properties":{"session":{"description":"Session identifies the running or paused coding session from the path.","type":"string"},"text":{"description":"Text is the new instruction to carry into the follow-up run.","type":"string"}},"type":"object"},"agent.controlIn":{"properties":{"id":{"description":"ID is the session to steer, from the path.","type":"string"},"message":{"description":"Message is free text for the running agent, up to 16 KiB. On a stop it is\nrecorded as the cancellation reason.","type":"string"},"payload":{"description":"Payload is a structured argument for the command: any valid JSON up to\n64 KiB, scanned for credentials before it is stored (a hit refuses the\ncommand with 422 and the findings). A task-backed session receives it as\nthe forwarded signal's argument."}},"type":"object"},"agent.createAgentIn":{"properties":{"avatar":{"description":"Avatar and Emoji are how the agent APPEARS. An image wins when both are\ngiven — it is the thing somebody made — and both empty leaves the agent\ndrawn as its initial. Validated by iam/pkg/schema, the same rule a person's\navatar passes, so the 96 KiB bound and the accepted URL forms are stated\nonce for every subject that has a face.","type":"string"},"cap_micro_usd":{"description":"The budget, required. An agent is not creatable without one: a zero cap\nwould mean no limit and no record of its spend, which is what a budget\nexists to remove. Integer micro-USD; the CLI converts dollars before sending.","format":"int64","type":"integer"},"computeRef":{"description":"ComputeRef optionally binds this bot to a visor machine. Opaque here, bounded\nat 256 characters, and not resolved — this package stores the reference and\nthe binding's lifecycle belongs elsewhere.","type":"string"},"description":{"description":"Description is the one line published as the description of the `agent_`\ntool, which is how another agent decides whether to call this one. Optional,\nand worth writing for exactly that reason.","type":"string"},"emoji":{"description":"Emoji is the single glyph shown when there is no image. An image WINS when\nboth are given — it is the thing somebody made — and both empty leaves the\nagent drawn as its initial.","type":"string"},"executionMode":{"description":"ExecutionMode is one-shot or long-running. Empty takes one-shot, which runs\nonly when something POSTs to it. long-running additionally requires Schedule,\nand counts against a per-org cap that answers 409 when it is full.","type":"string"},"instructions":{"description":"Instructions is the system prompt, up to 32 KiB, stored verbatim. This is what\nthe model reads; Description is what other CALLERS read.","type":"string"},"max_task_micro_usd":{"description":"MaxTaskMicroUSD is the ceiling for a single run, in micro-USD. A session\ncannot exceed it even when the period cap still has room, so one runaway\ntask cannot consume a month.","format":"int64","type":"integer"},"model":{"description":"Model names the model to run on. Omit it to take the deployment's configured\ndefault; name one and it is checked against the gateway's served catalogue\nhere, so a model this deployment cannot serve is refused now rather than at\nthe first run. Stored under our own name for it, whatever spelling arrives.","type":"string"},"name":{"description":"Name is the agent's org-unique handle and the only required field. It must\nmatch ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$, and a name already taken in this org\nis a 409 rather than an overwrite. It is permanent: no update route moves it.","type":"string"},"parent":{"description":"Parent is the agent spawning this one — its id or name, in the caller's\norg. The new agent answers to the org its parent answers to, and a parent\noutside the caller's org is not found: an agent is never spawned into a\nprincipal its creator does not answer to. Omitted for an agent a person\ndefines. Set once; no update moves it.","type":"string"},"period":{"description":"Period is the window the cap resets on: day, week or month.","type":"string"},"schedule":{"description":"Schedule is the 5-field cron a long-running agent fires on, parsed here so a\nbad expression is a 400 and not an agent that silently never runs. Required\nwith long-running; DISCARDED for one-shot rather than stored unused.","type":"string"},"serviceAccountId":{"description":"ServiceAccountID optionally names the IAM agent service account (-)\na scheduled run should be billed AS, so an autonomous run is attributable to a\nprincipal rather than only to the org. Same 256-character bound, also\nunresolved here.","type":"string"},"tools":{"description":"Tools are the tool names this agent may call. Omitted or empty grants NONE —\nthat default is the agent's authority and is not widened anywhere. The single\nentry \"*\" means whatever the fleet's MCP server serves at the time of each run.","items":{"type":"string"},"type":"array"}},"type":"object"},"agent.eventIn":{"properties":{"actor":{"description":"Actor is who produced the turn. Empty takes the validated caller, which is\nwhat an agent writing its own transcript wants; naming one is for a surface\nrecording on somebody else's behalf.","type":"string"},"id":{"description":"ID is the session to append to, from the path.","type":"string"},"kind":{"description":"Kind is what this turn IS: message, tool-call, spawn, log, status, control\nor progress. Anything else is refused — the vocabulary is closed so a\nreader can branch on it.","type":"string"},"payload":{"description":"Payload is the turn's own body, any valid JSON up to 64 KiB. It is SCANNED\nfor credentials before it is stored, and a hit refuses the whole append with\n422 and the findings — this plane never redacts a secret into a transcript\nit then keeps.\n\nIts SHAPE is the writer's business for every kind but one: a `progress`\nturn is the run reporting on itself in a shape this surface publishes —\n{\"pct\":0-100 (optional), \"phase\":\"queued|running|blocked|done\",\n\"activity\":\"≤120 chars\"} — so a malformed one is refused with 400 instead\nof being stored as prose nobody reads."}},"type":"object"},"agent.patchSessionIn":{"properties":{"cwd":{"description":"Cwd is where the session is working NOW.\n\nIt was write-once — captured at register and never again — which is right\nfor a run that starts in a directory and stays there, and wrong for a linked\nshell, which is a place a person moves around in. The console showed the\ndirectory `hanzo link` happened to be run from and kept showing it after the\nshell had walked away, so the field answered \"which work is this\" with an\nanswer that was true once. A pointer, so an unchanged path is an omitted\nfield rather than a repeated write.","type":"string"},"id":{"description":"ID is the session to update, from the path.","type":"string"},"project":{"description":"Project tags the product this session built; Published is the author's\ndecision to let anyone read the story (provenance.go). Both are pointers so\n\"absent\" and \"cleared\" are different requests.","type":"string"},"published":{"description":"Published opens the session's story to the public build route; false withdraws\nit, and withdrawing is always allowed. PUBLISHING is refused unless the\nsession names a Project — the one set in this same request, or the one already\nstored — because that route is keyed on (org, project). It widens READ access\nto what is already there and grants nothing else.","type":"boolean"},"status":{"description":"Status moves the session to running, paused, done or error. A session that has\nalready finished refuses any change with 409 — done and error are monotonic —\nand moving INTO one stamps the end time. This is the surface REPORTING what\nhappened; a control command never writes it.","type":"string"},"target":{"description":"Target re-dispatches a session to a run-target (the #48 association). \"\" detaches.","type":"string"},"terminal":{"description":"Terminal publishes (or, with \"\", withdraws) the URL this session's live\nterminal can be watched at. A pointer so \"absent\" and \"withdrawn\" are\ndifferent requests: a session that stops sharing must be able to say so.","type":"string"},"title":{"description":"Title rewrites the human line, up to 512 characters — usually because the work\nturned out to be something other than what it was opened as.","type":"string"}},"type":"object"},"agent.patchTargetIn":{"properties":{"capacity":{"description":"Capacity rewrites the human summary, up to 256 characters. \"\" clears it.","type":"string"},"host":{"description":"Host re-points the hostname sessions are matched by. Moving it moves the load:\nthe session counts follow the new name from the next read.","type":"string"},"id":{"description":"ID is the target to update, from the path.","type":"string"},"kind":{"description":"Kind re-files it under laptop | cloud | gpu | cluster | machine.","type":"string"},"label":{"description":"Label renames the machine, up to 128 characters. Empty STRING is refused — a\ntarget with no name is a row nobody can pick out of a fleet.","type":"string"},"metrics":{"$ref":"#/components/schemas/agent.Metrics","description":"Metrics replaces the live sample, and sending one IS A HEARTBEAT: the server\nstamps the time and appends the point to the fleet series. Sending an all-zero\nsample CLEARS the heartbeat — the machine goes back to having no liveness fact\nat all, and its stored status is taken at face value again."},"spec":{"$ref":"#/components/schemas/agent.Spec","description":"Spec replaces the static capability whole, sanitized and clamped the same way\na register's is."},"status":{"description":"Status sets operator INTENT: online | offline | draining. Draining is how a\nmachine is taken out of dispatch without ending what is already on it. What\ncomes back may still read offline, because the heartbeat outranks the intent.","type":"string"}},"type":"object"},"agent.registerReq":{"properties":{"account":{"description":"Account is which subscription or API account under that provider served the\nrun, up to 256 characters. It is what lets a revoke of that login stop exactly\nthe sessions it was paying for.","type":"string"},"agent":{"description":"Agent is the label the surface opening this session calls itself by\n(\"hanzo-dev\"). REQUIRED, up to 128 characters, and free text — nothing\nresolves it against a defined agent.","type":"string"},"budget_micro_usd":{"description":"BudgetMicroUSD caps what this session may spend, integer micro-USD. Zero\nmeans no cap; a cap can be raised or removed later, never added.","format":"int64","type":"integer"},"channel":{"description":"Channel is the collaborative channel this run was started in (HIP-0523), so a\nspace view can list the sessions of one channel. It is PROVENANCE and is set\nonly here: there is deliberately no way to move a session to another channel, so\nit is absent from the patch input and from UpdateSession's SET list.","type":"string"},"cwd":{"description":"Cwd is the directory the session starts in, up to 1024 characters. It can be\nmoved later, because a linked shell walks around.","type":"string"},"host":{"description":"Execution context — where this session runs (all optional).","type":"string"},"parentSessionId":{"description":"ParentSessionID makes this a subagent of that session: it inherits the\nparent's root, so one flow stays one tree. The parent must exist IN THE SAME\nORG — a foreign or unknown id is a 400, never a tree across tenants. Empty\nopens a root session.","type":"string"},"project":{"description":"The readable build (provenance.go): which product this session builds, and\nwhether its story may be read by the world.","type":"string"},"provider":{"description":"Account tag — the linked AI account this session ran under (login manager).","type":"string"},"published":{"description":"Published opens this session's story to the public build route. It is refused\nwithout a Project, because that route is keyed on (org, project) — a build\nwith no product is not a story anyone can open. False keeps it org-only.","type":"boolean"},"repo":{"description":"Repo is the code being worked on, up to 512 characters. A label the surface\nstates; nothing resolves it against the forge.","type":"string"},"status":{"description":"Status opens the session in one of running, paused, done or error. Empty means\nrunning. A TERMINAL status here (done, error) records a session that has\nalready finished — its end time is stamped now — and nothing can move it\nafterwards.","type":"string"},"target":{"description":"Target names a run-target the org has registered. Unlike Host and Repo it IS\nresolved: a target that does not exist in this org is a 400, so a session can\nnever claim to run on another tenant's machine. Empty names no machine.","type":"string"},"taskRunId":{"description":"TaskRunID is that workflow's particular run, same bound. Recorded, not\nresolved: this surface does not check the workflow exists.","type":"string"},"taskWorkflowId":{"description":"TaskWorkflowID links this session to the hanzoai/tasks workflow that executes\nit, up to 256 characters. Set it and control commands are forwarded to that\nengine; leave it and the running surface polls for them instead.","type":"string"},"terminal":{"description":"Terminal is the URL this session's live terminal is published at, so the\nconsole can watch it. Optional — a session that publishes nothing is still\na session.","type":"string"},"title":{"description":"Title is the human line a card shows, up to 512 characters. Optional, and\nchangeable later.","type":"string"}},"type":"object"},"agent.reportRunIn":{"properties":{"branch":{"description":"Branch, CommitSha and Diffstat describe what the run produced; Error is the\nfailure when OK is false. Each is clamped, never rejected.","type":"string"},"changed":{"description":"Changed says whether the run produced any commit. It is INDEPENDENT of OK: a\nrun can succeed and change nothing (there was nothing to do), and a run can\nfail after committing some of its work. Two questions, two booleans.","type":"boolean"},"commitSha":{"description":"CommitSha is the tip the run pushed, clamped to 128 characters. Empty when it\npushed nothing, which is the same case Changed reports false for.","type":"string"},"diffstat":{"description":"Diffstat is the run's own summary of what it changed, as text, clamped to\n64 KiB. Free-form: it is shown, never parsed.","type":"string"},"error":{"description":"Error is why the run failed, clamped to 64 KiB. It is CLAMPED rather than\nrefused — a truncated reason is worth more than a rejected report, because a\nrejected report leaves the durable workflow waiting forever.","type":"string"},"id":{"description":"ID is the machine reporting, from the path.","type":"string"},"ok":{"description":"OK is whether the run succeeded; Changed whether it produced any commit.","type":"boolean"},"runId":{"description":"RunID is the routed run being completed, from the path.","type":"string"}},"type":"object"},"agent.sessionBudgetIn":{"properties":{"budget_micro_usd":{"description":"BudgetMicroUSD is the new cap, or null to remove the cap for good.","format":"int64","type":"integer"},"id":{"description":"ID is the session, from the path.","type":"string"}},"type":"object"},"agent.targetReq":{"properties":{"capacity":{"description":"Capacity is a human summary of the machine's size, up to 256 characters. Prose\nonly; a scheduler reads Spec.","type":"string"},"host":{"description":"Host is the hostname sessions on this machine will report. It is what makes a\nre-link IDEMPOTENT: the same (org, host, owner) refreshes the existing row and\nanswers 200, while a request with no host always creates a new target and\nanswers 201. It never adopts a row owned by somebody else.","type":"string"},"kind":{"description":"Kind is laptop | cloud | gpu | cluster | machine. Empty registers a `machine`;\nanything outside the five is a 400.","type":"string"},"label":{"description":"Label is the name to show for this machine, up to 128 characters. REQUIRED —\nit is the only field here a person reads.","type":"string"},"metrics":{"$ref":"#/components/schemas/agent.Metrics","description":"Metrics is a live sample, and sending one IS A HEARTBEAT: it refreshes the row\nand starts the 90-second liveness window, and it is appended to the fleet\nseries as one point. Its own `at` is ignored — the server stamps the time, so\na client can never age or backdate its own machine. Omit it to register a\nmachine without claiming it is alive."},"spec":{"$ref":"#/components/schemas/agent.Spec","description":"Spec is the machine's static capability — os, arch, cores, RAM, accelerators.\nEvery field is bounded on write and at most 32 accelerators are accepted, so\nwhat comes back may be clamped. Omit it for a destination nothing probes."},"status":{"description":"Status is online | offline | draining. Empty registers `online`. It states\nINTENT — a heartbeat is what decides whether an online machine is actually\nreachable, so declaring online does not make it so.","type":"string"}},"type":"object"},"agent.updateAgentIn":{"properties":{"avatar":{"description":"Avatar and Emoji re-draw the agent. Sending either replaces the pair, so\nsetting an image clears a glyph and \"\" for both goes back to the initial —\nthere is no state where a row holds two answers.","type":"string"},"cap_micro_usd":{"description":"The budget, any part of it. Changing the period opens a new window.","format":"int64","type":"integer"},"computeRef":{"description":"ComputeRef re-binds (or, with \"\", unbinds) the visor machine. Opaque here.","type":"string"},"description":{"description":"Description replaces the line other agents read in the tool catalogue.","type":"string"},"emoji":{"description":"Emoji re-draws the agent as a glyph. Sending either of the pair replaces\nBOTH, so setting a glyph clears an image and \"\" for both goes back to the\ninitial — there is no state where a row holds two answers.","type":"string"},"executionMode":{"description":"ExecutionMode switches between one-shot and long-running. The RESULTING\nmode+schedule are validated together, so switching to long-running without a\nstored or supplied cron is refused rather than accepted into an agent the\nscheduler would skip forever. A switch INTO long-running counts against the\nper-org cap and can be a 409.","type":"string"},"instructions":{"description":"Instructions replaces the system prompt whole, up to 32 KiB. There is no\nappend: a prompt is one text, and sending \"\" clears it.","type":"string"},"max_task_micro_usd":{"description":"MaxTaskMicroUSD is the ceiling for a single run, in micro-USD. A session\ncannot exceed it even when the period cap still has room, so one runaway\ntask cannot consume a month.","format":"int64","type":"integer"},"model":{"description":"Model re-points the agent at another model, checked against the gateway's\nserved catalogue exactly as create checks it. Empty STRING is refused — say\nnothing to keep the current one. Past runs keep the model that served them.","type":"string"},"period":{"description":"Period is the window the cap resets on: day, week or month.","type":"string"},"ref":{"description":"Ref is the agent to update — its public id or org-unique name, from the path.","type":"string"},"schedule":{"description":"Schedule replaces the cron. It is validated against the mode this update\nleaves behind, and dropped if that mode is one-shot.","type":"string"},"serviceAccountId":{"description":"ServiceAccountID re-points (or, with \"\", clears) the IAM service account a\nscheduled run is billed as. Clearing it puts that spend back on the org.","type":"string"},"tools":{"description":"Tools replaces the whole allow-list, it does not add to it. Sending [] takes\nevery tool away, which is the only way to say that.","items":{"type":"string"},"type":"array"}},"type":"object"},"ai.AnthropicMessage":{"properties":{"content":{},"role":{"type":"string"}},"type":"object"},"ai.AnthropicRequest":{"properties":{"max_tokens":{"type":"integer"},"messages":{"items":{"$ref":"#/components/schemas/ai.AnthropicMessage"},"type":"array"},"model":{"type":"string"},"stream":{"type":"boolean"},"system":{},"temperature":{"type":"number"},"thinking":{},"tool_choice":{},"tools":{"items":{"$ref":"#/components/schemas/ai.AnthropicTool"},"type":"array"}},"type":"object"},"ai.AnthropicTool":{"properties":{"description":{"type":"string"},"input_schema":{},"name":{"type":"string"}},"type":"object"},"ai.DecisionSides":{"properties":{"false":{"description":"A string, an object or an array, kept as written."},"true":{"description":"A string, an object or an array, kept as written."}},"type":"object"},"ai.DecisionsBoolean":{"properties":{"criteria":{"$ref":"#/components/schemas/ai.DecisionSides"},"instructions":{"description":"A string, an object or an array, kept as written."},"labels":{"additionalProperties":{"type":"string"},"type":"object"},"type":{"enum":["boolean"],"type":"string"}},"required":["type"],"type":"object"},"ai.DecisionsChoice":{"properties":{"criteria":{"description":"At least two labels: an object mapping each label to what it means (a string, an object, an array, or null), or an array of labels that need no description."},"instructions":{"description":"A string, an object or an array, kept as written."},"type":{"enum":["choice"],"type":"string"}},"required":["type","criteria"],"type":"object"},"ai.DecisionsNoul":{"properties":{"criteria":{"$ref":"#/components/schemas/ai.DecisionSides"},"instructions":{"description":"A string, an object or an array, kept as written."},"labels":{"additionalProperties":{"type":"string"},"type":"object"},"type":{"enum":["noul"],"type":"string"}},"required":["type"],"type":"object"},"ai.DecisionsQuestion":{"discriminator":{"mapping":{"boolean":"#/components/schemas/ai.DecisionsBoolean","choice":"#/components/schemas/ai.DecisionsChoice","noul":"#/components/schemas/ai.DecisionsNoul","score":"#/components/schemas/ai.DecisionsScore"},"propertyName":"type"},"oneOf":[{"$ref":"#/components/schemas/ai.DecisionsBoolean"},{"$ref":"#/components/schemas/ai.DecisionsNoul"},{"$ref":"#/components/schemas/ai.DecisionsChoice"},{"$ref":"#/components/schemas/ai.DecisionsScore"}]},"ai.DecisionsRequest":{"properties":{"handle":{"type":"string"},"model":{"type":"string"},"observe":{"type":"string"},"provider":{},"questions":{"additionalProperties":{"$ref":"#/components/schemas/ai.DecisionsQuestion"},"maxProperties":100,"minProperties":1,"type":"object"},"session_id":{"type":"string"},"state":{"description":"A string, an object or an array, kept as written."},"trace":{},"user":{"type":"string"}},"required":["model"],"type":"object"},"ai.DecisionsScore":{"properties":{"criteria":{"items":{"description":"A string, an object or an array, kept as written."},"minItems":1,"type":"array"},"instructions":{"description":"A string, an object or an array, kept as written."},"type":{"enum":["score"],"type":"string"}},"required":["type","criteria"],"type":"object"},"ai.RoutingEdit":{"properties":{"base":{"type":"integer"},"catalog":{},"family":{"type":"string"},"model":{"type":"string"},"note":{"type":"string"},"version":{"type":"integer"}},"type":"object"},"ai.RoutingRewardRequest":{"properties":{"rating":{"type":"number"},"request_id":{"type":"string"},"reward":{"type":"number"},"signal":{"enum":["up","accept","regenerate","down","switch","abandon","revert","rating","dismiss"],"type":"string"}},"required":["request_id"],"type":"object"},"aiChatIn":{"properties":{"max_tokens":{"description":"MaxTokens bounds the answer in tokens; 0 leaves it to the model.","format":"int64","type":"integer"},"model":{"description":"Model is the model to answer, by id (zen5, enso, kai, anthropic/claude-sonnet-4.5\n— aiModels lists them). Empty asks the deployment's default Hanzo model.","type":"string"},"prompt":{"description":"Prompt is what to ask.","type":"string"},"system":{"description":"System is the system message ahead of the prompt, when set.","type":"string"}},"type":"object"},"aiDecideIn":{"properties":{"handle":{"description":"Handle decides over a state this org observed earlier, in place of State and\nQuestions.","type":"string"},"model":{"description":"Model is kai, Kai's versioned id kai-<12 hex>, or Jev by its vendor id\n(typesafe/jev-1.13, ~typesafe/jev-latest).","type":"string"},"observe":{"description":"Observe holds the state under this id (1 to 128 of A-Z a-z 0-9 . _ -), so a\nlater decision can name it as its Handle.","type":"string"},"questions":{"additionalProperties":{},"description":"Questions are 1 to 100 named questions, each {\"type\": \"choice\"|\"noul\"|\"score\",\n\"instructions\"?, \"criteria\"?}; a choice names at least 2 labels and a score at\nleast 1 level. Not sent with a Handle.","type":"object"},"state":{"description":"State is what the questions are about: a string, an object or an array, kept\nas written. Not sent with a Handle."}},"type":"object"},"ask.webQuestion":{"properties":{"language":{"description":"Language narrows the search to a locale, BCP-47-ish (\"en\", \"ja\"). Empty\nmeans no narrowing.","type":"string"},"max_sources":{"description":"MaxSources caps how many pages are read. Empty means the mode's own budget.","format":"int64","type":"integer"},"mode":{"description":"Mode is how much work to do: `search` (fast, one pass), `news` (recency\nbiased), `research` (a plan and several rounds) or `deep` (the widest\nsurvey). Empty means research.","type":"string"},"q":{"description":"Q is the question, in plain language. Required.","type":"string"},"sources":{"description":"Sources narrows where the evidence comes from: any of `web`, `news`,\n`academic`, `github`, `reddit`, `x`. Each becomes a site-scoped search, so\n`[\"x\"]` researches X/Twitter posts rather than the open web.","items":{"type":"string"},"type":"array"}},"type":"object"},"askRequest":{"properties":{"followUps":{"type":"boolean"},"language":{"type":"string"},"maxQueries":{"type":"integer"},"maxSources":{"type":"integer"},"mode":{"type":"string"},"model":{"type":"string"},"q":{"type":"string"},"question":{"type":"string"},"sources":{"items":{"type":"string"},"type":"array"},"stream":{"type":"boolean"},"system":{"type":"string"}},"type":"object"},"author.connectRequest":{"properties":{"githubLogin":{"description":"GithubLogin is the account to link. Used only when IAM holds no linked\naccount for the provider — a linked account is stronger proof and always wins.","type":"string"},"login":{"description":"Login is the provider-neutral alias for GithubLogin, preferred when both are\nsent.","type":"string"},"provider":{"description":"Provider is the forge to enrol with: github (the default) or gitlab.","type":"string"}},"type":"object"},"author.deployRequest":{"properties":{"project":{"description":"Project is the deployed project's id. Required.","type":"string"},"repoUrl":{"description":"RepoURL is the source repository the project was built from. Empty means a\nhand-built project with nothing to attribute — an honest no-op, not an error.","type":"string"}},"type":"object"},"author.verifyRequest":{"properties":{"repoUrl":{"description":"RepoURL is what to claim: a repository (github.com/owner/name) or a whole\nOWNER (github.com/owner, no repository segment). gitlab.com is accepted too.","type":"string"}},"type":"object"},"auto.FlowAction":{"properties":{"displayName":{"type":"string"},"name":{"type":"string"},"nextAction":{"$ref":"#/components/schemas/auto.FlowAction"},"settings":{"$ref":"#/components/schemas/auto.StepSettings"},"skip":{"type":"boolean"},"type":{"description":"PIECE | CODE | ROUTER | LOOP_ON_ITEMS","type":"string"},"valid":{"type":"boolean"}},"type":"object"},"auto.FlowTrigger":{"properties":{"displayName":{"type":"string"},"name":{"type":"string"},"nextAction":{"$ref":"#/components/schemas/auto.FlowAction"},"settings":{"$ref":"#/components/schemas/auto.StepSettings"},"strategy":{"type":"string"},"type":{"description":"PIECE_TRIGGER | EMPTY","type":"string"},"valid":{"type":"boolean"}},"type":"object"},"auto.OutcomeTrigger":{"properties":{"name":{"description":"Name is the event, for example improvement.reviewed.","type":"string"},"source":{"description":"Source is the producing capability, for example research.","type":"string"}},"type":"object"},"auto.Schedule":{"properties":{"at":{"description":"At is the local time, HH:MM on a 24-hour clock, for daily, weekdays and\nweekly. Hourly takes its minute, and runs on the hour without one. Once\ntakes a local date and time, YYYY-MM-DDTHH:MM, and runs now without one.","type":"string"},"cron":{"description":"Cron is a five-field cron expression (minute hour day-of-month month\nday-of-week), for kind cron only, read in TZ.","type":"string"},"day":{"description":"Day is the weekday a weekly schedule runs on: mon, tue, wed, thu, fri, sat\nor sun.","type":"string"},"kind":{"description":"Kind is manual, hourly, daily, weekdays, weekly, cron or once. Manual runs\nonly when asked; once runs one time and then switches itself off.","type":"string"},"tz":{"description":"TZ is the IANA time zone every time here is read in. Empty is UTC.","type":"string"}},"type":"object"},"auto.StepSettings":{"properties":{"actionName":{"type":"string"},"input":{"additionalProperties":{},"type":"object"},"pieceName":{"type":"string"},"pieceVersion":{"type":"string"},"triggerName":{"type":"string"}},"type":"object"},"auto.automationIn":{"properties":{"enabled":{"description":"Enabled arms its schedule. Absent is true.","type":"boolean"},"event":{"$ref":"#/components/schemas/auto.OutcomeTrigger","description":"Event arms a product-outcome trigger; it is mutually exclusive with a timed schedule."},"instructions":{"description":"Instructions are what the agent is asked to do each run. Required.","type":"string"},"model":{"description":"Model is the model id to think with. Optional; absent is the default.","type":"string"},"name":{"description":"Name is what it is called. Required.","type":"string"},"notify":{"description":"Notify sends a one-line summary when a run ends.","type":"boolean"},"permissions":{"description":"Permissions is auto (works without stopping) or ask (proposes, changes\nnothing). Absent is ask.","type":"string"},"postTo":{"description":"PostTo are the connected accounts each run's answer is posted to: x,\nlinkedin, facebook. Absent posts nothing.","items":{"type":"string"},"type":"array"},"project":{"description":"Project is a Dev project's slug to work in. Optional.","type":"string"},"schedule":{"$ref":"#/components/schemas/auto.Schedule","description":"Schedule is when it runs. Absent runs it only on demand."},"source":{"description":"Source is the product it is made in: chat, dev, studio or workflow. Absent\nis dev.","type":"string"},"target":{"description":"Target selects a registered execution target for the coding run.","type":"string"}},"type":"object"},"auto.automationPatch":{"properties":{"enabled":{"description":"Enabled arms or disarms its schedule.","type":"boolean"},"event":{"$ref":"#/components/schemas/auto.OutcomeTrigger","description":"Event replaces the trigger with a product outcome; null clears it."},"id":{"description":"ID is the automation, from the path.","type":"string"},"instructions":{"type":"string"},"model":{"type":"string"},"name":{"type":"string"},"notify":{"type":"boolean"},"permissions":{"type":"string"},"postTo":{"items":{"type":"string"},"type":"array"},"project":{"type":"string"},"schedule":{"$ref":"#/components/schemas/auto.Schedule"},"target":{"description":"Target replaces the registered execution target; null clears it.","type":"string"}},"type":"object"},"auto.createFlowReq":{"properties":{"displayName":{"description":"DisplayName names the flow's initial draft version.","type":"string"},"externalId":{"description":"ExternalID is the caller's own id for this flow. Optional.","type":"string"},"folderId":{"description":"FolderID groups the flow in the builder's tree. Optional.","type":"string"},"trigger":{"$ref":"#/components/schemas/auto.FlowTrigger","description":"Trigger is the root of the step tree — how the flow starts, and the action\nchain that follows. Optional: a flow may be created empty and edited later."}},"type":"object"},"auto.createVersionIn":{"properties":{"displayName":{"description":"DisplayName names the new version.","type":"string"},"id":{"description":"ID is the flow to add a version to, from the path.","type":"string"},"trigger":{"$ref":"#/components/schemas/auto.FlowTrigger","description":"Trigger is the root of the version's step tree. Optional: a version with no\ntrigger is created invalid, and cannot run until one is set."}},"type":"object"},"auto.patchFlowIn":{"properties":{"externalId":{"description":"ExternalID sets the caller's own id for this flow.","type":"string"},"folderId":{"description":"FolderID moves the flow in the builder's tree.","type":"string"},"id":{"description":"ID is the flow to update, from the path.","type":"string"},"metadata":{"description":"Metadata replaces the caller's opaque JSON."},"publishedVersionId":{"description":"PublishedVersionID pins the version runs execute. It must name a version OF\nTHIS FLOW; empty clears the pin, so runs take the latest version again.","type":"string"}},"type":"object"},"auto.reviewIn":{"properties":{"id":{"description":"ID is the automation, and Run its run in review, from the path.","type":"string"},"post":{"description":"Post posts it when true and discards it when false.","type":"boolean"},"run":{"type":"string"}},"type":"object"},"auto.runIn":{"properties":{"action":{"description":"Action is the name of the provider action to invoke.","type":"string"},"auth":{"description":"Auth is the caller's resolved credential for the provider, handed to the\naction verbatim. Its shape is whatever the provider's auth descriptor\ndeclares (a token string, an object), so it is opaque here."},"id":{"description":"ID is the provider to run, from the path.","type":"string"},"props":{"additionalProperties":{},"description":"Props are the action's input properties, keyed by property name.","type":"object"}},"type":"object"},"auto.whenIn":{"properties":{"text":{"description":"Text is when it runs, as a person says it: \"every monday at 9am\".","type":"string"},"tz":{"description":"TZ is the IANA zone the words are read in. Empty is UTC.","type":"string"}},"type":"object"},"benchmark.Claim":{"properties":{"benchmark":{"description":"Benchmark is the canonical test id the claim is about, from /catalog.","type":"string"},"evidence":{"description":"Evidence are the evidence uris the claim rests on, at most 64.","items":{"type":"string"},"type":"array"},"model":{"description":"Model is the system the score is claimed for.","type":"string"},"protocol":{"description":"Protocol records HOW it was scored — provider-reported, agentic,\nthird-party-leaderboard — so a provider card is never read as a measurement.","type":"string"},"provider":{"description":"Provider is who the claim belongs to — the lab or leaderboard whose number\nthis is.","type":"string"},"runs":{"description":"Runs are the research run ids the claim rests on, at most 64.","items":{"type":"string"},"type":"array"},"score":{"description":"Score is the reported aggregate, as a percentage.","format":"double","type":"number"},"source":{"description":"Source is the citation the row was read from. Required.","type":"string"}},"type":"object"},"benchmark.Preset":{"properties":{"arms":{"description":"the blend — model ids from the arena","items":{"type":"string"},"type":"array"},"at":{"description":"At is when this version was stored. Set by the server; a value sent is not\nread. Zero on the reference blend.","format":"date-time","type":"string"},"by":{"description":"By is the verified user who stored it. Set by the server; a value sent is\nnot read.","type":"string"},"name":{"description":"the part after enso-: lowercase letters, digits and inner hyphens, at most 64","type":"string"},"note":{"description":"why this blend (audit)","type":"string"},"owner":{"description":"the org the blend belongs to: the writer's verified org, never a value sent","type":"string"},"panel":{"description":"fan-out width (>=1)","format":"int64","type":"integer"},"rank":{"description":"escalation order over arms","items":{"type":"string"},"type":"array"}},"type":"object"},"benchmark.putClaimsIn":{"properties":{"data":{"description":"Data is the claims to record. One row is a correction; many is an import.\nThere is no separate bulk endpoint because there is no separate operation:\nimporting a leaderboard and fixing one number are the same write.","items":{"$ref":"#/components/schemas/benchmark.Claim"},"type":"array"},"visibility":{"description":"Visibility is who may read every row in Data: \"private\", the default, keeps\nthem to the caller's org; \"public\" shows them to anyone. Restating a claim\nwith the other value moves it.","type":"string"}},"type":"object"},"benchmark.suite":{"properties":{"benchmarks":{"description":"Benchmarks are the catalog ids to ask about. At least one is required, and\nevery id must be in the catalog.","items":{"type":"string"},"type":"array"},"model":{"description":"Model is the model to ask about, by the id its attempts are stored under.\nRequired.","type":"string"}},"required":["benchmarks"],"type":"object"},"billing.AlertPatch":{"properties":{"enforce":{"type":"boolean"},"id":{"type":"string"},"project":{"type":"string"},"rateLimitRpm":{"format":"int64","type":"integer"},"service":{"type":"string"},"softPct":{"format":"int64","type":"integer"},"subject":{"type":"string"},"threshold":{"format":"int64","type":"integer"},"title":{"type":"string"}},"type":"object"},"billing.AlertSpec":{"properties":{"currency":{"type":"string"},"enforce":{"type":"boolean"},"project":{"type":"string"},"rateLimitRpm":{"format":"int64","type":"integer"},"service":{"type":"string"},"softPct":{"format":"int64","type":"integer"},"subject":{"type":"string"},"threshold":{"format":"int64","type":"integer"},"title":{"type":"string"}},"type":"object"},"billing.AutoRechargeEdit":{"properties":{"amountCents":{"format":"int64","type":"integer"},"currency":{"type":"string"},"enabled":{"type":"boolean"},"thresholdCents":{"format":"int64","type":"integer"}},"type":"object"},"billing.GatewayAuthorization":{"properties":{"from":{"type":"string"},"nonce":{"type":"string"},"to":{"type":"string"},"validAfter":{"type":"string"},"validBefore":{"type":"string"},"value":{"type":"string"}},"type":"object"},"billing.InvoiceLine":{"properties":{"amount":{"description":"Amount is the line total in whole cents (250000 is $2,500.00).","format":"int64","type":"integer"},"description":{"description":"Description is the human-readable line, e.g. \"Advisory retainer — August\".","type":"string"},"quantity":{"description":"Quantity is the number of units, when the line is metered. Optional.","format":"int64","type":"integer"},"unitPrice":{"description":"UnitPrice is the per-unit price in cents, when the line is metered. Optional.","format":"int64","type":"integer"}},"type":"object"},"billing.InvoiceRef":{"properties":{"brand":{"description":"Brand is the brand that bills (hanzo, lux, zoo, pars), whose mark and\naddress a rendered invoice carries. The edge sets it from the caller's\nissuer; empty is Hanzo.","type":"string"},"id":{"description":"ID is the invoice id.","type":"string"}},"type":"object"},"billing.ModeIn":{"properties":{"testMode":{"type":"boolean"}},"type":"object"},"billing.Money":{"properties":{"currency":{"type":"string"},"decimal":{"type":"string"}},"required":["decimal","currency"],"type":"object"},"billing.RaiseIn":{"properties":{"currency":{"description":"Currency is the ISO 4217 code, lower-cased. Empty means usd.","type":"string"},"customerEmail":{"description":"CustomerEmail is where the invoice is sent. Optional.","type":"string"},"lines":{"description":"Lines are the charges. The invoice subtotal and amount due are COMPUTED\nfrom these — there is no total field to send, because a total that\ndisagreed with its own lines would bill a number nobody could derive.","items":{"$ref":"#/components/schemas/billing.InvoiceLine"},"type":"array"},"userId":{"description":"UserID identifies the customer being billed, within the caller's own org.\nRequired — an invoice with no addressee is not an invoice.","type":"string"}},"type":"object"},"billing.SaleLine":{"properties":{"planId":{"description":"PlanID is the seat type, e.g. \"team-premium\".","type":"string"},"quantity":{"description":"Quantity is the seats of it bought, at least 1.","format":"int64","type":"integer"}},"type":"object"},"billing.SubscriptionSeat":{"properties":{"member":{"description":"Member is the IAM user who holds the seat, as the org's members list names them.","type":"string"},"plan":{"description":"Plan is the seat type held: \"team\" (standard) or \"team-premium\".","type":"string"}},"type":"object"},"billing.assignment":{"properties":{"assigned":{"description":"Assigned is every seat assigned: the member, and the seat type (a plan the\nsubscription holds seats of, \"team\" or \"team-premium\") they hold. It\nreplaces what was assigned; an empty list unassigns every seat.","items":{"$ref":"#/components/schemas/billing.SubscriptionSeat"},"type":"array"}},"type":"object"},"billing.cryptoAsset":{"properties":{"amountCents":{"description":"AmountCents is what the payer intends to send, for the record. Optional —\nthe credit is what actually arrives, never what was announced.","format":"int64","type":"integer"},"chain":{"description":"Chain is the network to receive on, one of GET /v1/billing/crypto/options\nchains. Empty takes the rail's default.","type":"string"},"token":{"description":"Token is the asset on that chain, one of the options' tokens. Empty takes the\nrail's default.","type":"string"}},"type":"object"},"billing.paypalOrderIn":{"properties":{"amountCents":{"description":"AmountCents is the top-up amount in whole cents when PlanID is empty.","format":"int64","type":"integer"},"balanceCents":{"description":"BalanceCents is an organization's optional starting usage balance.","format":"int64","type":"integer"},"coupon":{"description":"Coupon is an optional plan coupon code for a monthly subscription.","type":"string"},"currency":{"description":"Currency is the ISO-4217 code (default usd).","type":"string"},"interval":{"description":"Interval selects the billing term (\"month\" or \"year\").","type":"string"},"level":{"description":"Level selects which published price level of the plan to buy.","format":"int64","type":"integer"},"lines":{"description":"Lines are a team's additional seat types bought on the same subscription.","items":{"$ref":"#/components/schemas/billing.SaleLine"},"type":"array"},"planId":{"description":"PlanID is the plan slug when buying a plan's first period; empty for a top-up.","type":"string"},"quantity":{"description":"Quantity is the seat count for a per-seat plan.","format":"int64","type":"integer"},"storeId":{"description":"StoreID scopes the plan catalog when set.","type":"string"}},"type":"object"},"billing.resize":{"properties":{"lines":{"description":"Lines are the team's other seat types and the seats of each:\n[{\"planId\":\"team-premium\",\"quantity\":2}]. A seat type of the team the\nsubscription does not hold yet is added.","items":{"$ref":"#/components/schemas/billing.SaleLine"},"type":"array"},"quantity":{"description":"Quantity is the seats of the subscription's own seat type; 0 keeps them.","format":"int64","type":"integer"}},"type":"object"},"billing.signedPayment":{"properties":{"authorization":{"$ref":"#/components/schemas/billing.GatewayAuthorization","description":"Authorization is the EIP-3009 TransferWithAuthorization as signed: every\nfield a string, addresses and nonce 0x hex, value in USDC base units."},"network":{"description":"Network is the CAIP-2 network the payment was signed for, one of the\nterms' accepts, e.g. \"eip155:8453\".","type":"string"},"salt":{"description":"Salt is the salt the terms issued with the nonce.","type":"string"},"signature":{"description":"Signature is the 65-byte EIP-712 signature, 0x hex.","type":"string"}},"type":"object"},"billing.subscriptionAct":{"properties":{"atPeriodEnd":{"description":"AtPeriodEnd cancels at the end of the paid period rather than at once. It\ndefaults TRUE, because a customer who cancels has already paid for the\nperiod they are in.","type":"boolean"},"id":{"description":"ID is the subscription, from the path.","type":"string"}},"type":"object"},"billing.topupIn":{"properties":{"amountCents":{"description":"AmountCents is how much to charge, in cents of Currency. Required.","format":"int64","type":"integer"},"currency":{"description":"Currency is the ISO-4217 code to charge in. Empty takes the deployment's\nown default.","type":"string"},"paymentMethodId":{"description":"MethodID names a card the subject already saved, for the saved-card endpoint.","type":"string"},"provider":{"description":"Provider names the explicit payment processor (\"square\" or \"paypal\") when\nSourceID is a provider-specific order/token (e.g. a PayPal v2 Order ID).","type":"string"},"sourceId":{"description":"SourceID is a single-use card token from the payment form, for the token\nendpoint. It is vaulted as part of the charge, so a caller never holds card\nnumbers and this service never sees one.","type":"string"}},"type":"object"},"billing.usageReport":{"properties":{"amount":{"$ref":"#/components/schemas/billing.Money","description":"Amount is what the act costs, as an exact decimal in USD. It must be\ngreater than zero."},"id":{"description":"ID names the act, chosen by the reporting application and stable across its\nretries: the ledger debits one act once. At most 128 printable characters,\nno whitespace. Reusing an ID for a different amount is a 409.","type":"string"},"model":{"description":"Model names the unit the amount prices (a machine size, a model id), and is\nrecorded with the debit.","type":"string"},"org":{"description":"Org is the organization this usage is billed to. It must be the org the\ntoken acts in — the application's own, or one that granted it membership and\nis selected with X-Org-Id — and any other is refused before money moves.","type":"string"},"project":{"description":"Project attributes the debit to one project of the org. Empty is the org's\ndefault project.","type":"string"},"service":{"description":"Service scopes the debit for spend caps and attributes it to a product, as\na lowercase slug. Empty takes the reporting application's name.","type":"string"}},"type":"object"},"books.AskRequest":{"properties":{"from":{"description":"From is the RFC3339 start of the metric window. Empty means all time, treated as a\nsingle reporting period (see monthsBetween).","type":"string"},"question":{"description":"Question is the plain-language question about the org's books, e.g. \"what is my\nMRR?\". Longer than 2000 characters is truncated, never refused.","type":"string"},"to":{"description":"To is the RFC3339 end of the metric window. Empty means up to now.","type":"string"}},"type":"object"},"books.BookRequest":{"properties":{"override":{"description":"Override books this bill even when one of the SAME economic identity\n(vendor, total, issue date) already posted — the explicit human confirmation that a\nsame-looking bill is a genuine second spend, not the same receipt re-scanned.","type":"boolean"},"scanId":{"description":"ScanID is the scanned document's file hash, as GET /v1/books/inbox and the scan\ndraft report it. It is the idempotency key: re-booking the same scan writes nothing.","type":"string"},"voucher":{"$ref":"#/components/schemas/books.Voucher","description":"Voucher is the reviewed voucher to post. Its source is FORCED to (scan, scanId)\nserver-side, so it can never be booked under another source's key."}},"type":"object"},"books.Leg":{"properties":{"account":{"description":"Account is the chart-of-accounts number this side posts to, e.g. \"5300\".","type":"string"},"credit":{"description":"Credit is the leg's credit in exact cents. Set this or Debit, not both.","format":"int64","type":"integer"},"debit":{"description":"Debit is the leg's debit in exact cents. Set this or Credit, not both.","format":"int64","type":"integer"}},"type":"object"},"books.Rule":{"properties":{"category":{"description":"Category is the COA expense account a matching bill books to. An upsert normalizes\na slug (\"cloud\") to its account number.","type":"string"},"pattern":{"description":"Pattern is the merchant substring the rule matches on, case-insensitively. It is\nalso the key an upsert writes by.","type":"string"},"priority":{"description":"Priority breaks ties: when several patterns match, the highest wins.","format":"int64","type":"integer"}},"type":"object"},"books.VendorRow":{"properties":{"aliases":{"description":"Aliases are the other spellings a receipt may print the vendor under; a scan\nmatching any of them resolves to this vendor.","items":{"type":"string"},"type":"array"},"canonical":{"description":"Canonical is the vendor's one true name, and the key an upsert writes by.","type":"string"},"defaultCategory":{"description":"DefaultCategory is the COA expense account new bills from this vendor book to.\nAn upsert normalizes a slug (\"software\") to its account number.","type":"string"}},"type":"object"},"books.Voucher":{"properties":{"description":{"description":"Description is the human line for the event, e.g. the vendor a bill came from.","type":"string"},"legs":{"description":"Legs are the sides of the posting. They must balance: Σdebit == Σcredit, give or\ntake the 2¢ round-off allowance.","items":{"$ref":"#/components/schemas/books.Leg"},"type":"array"},"postingAt":{"description":"PostingAt is the RFC3339 instant the event posts at — the time every statement\nwindow filters on.","type":"string"},"sourceId":{"description":"SourceID is the source event's own id within that namespace. Together with\nSourceKind it is the key that makes a repeat posting a no-op.","type":"string"},"sourceKind":{"description":"SourceKind is the idempotency namespace naming what booked this, e.g. \"scan\".","type":"string"}},"type":"object"},"campaign.ChannelSpec":{"properties":{"account":{"description":"Account is the provider account this channel runs under: an ad-account, a page\nor a mailing-list id. An executor may replace it at launch with the account it\nactually used.","type":"string"},"detail":{"description":"Detail is the last outcome in one secret-free line — the failure reason, or\nwhat the executor reported. Absent when there is nothing to explain.","type":"string"},"externalId":{"description":"ExternalID is the provider-side id of the running execution, recorded by the\norchestrator at launch and handed back verbatim to read spend or to pause.\nServer-owned and absent until this channel has launched; anything a caller\nsends for it is dropped.","type":"string"},"kind":{"description":"Kind is the channel and the identity a campaign holds at most one of: paid,\norganic or email. It picks the executor the launch fans out to.","type":"string"},"platform":{"description":"Platform is the provider within the kind — meta, google, x, instagram, or the\nemail provider.","type":"string"},"status":{"description":"Status is this channel's own launch outcome, not the campaign's: pending (added,\nnever launched), live, paused, failed (Detail says why) or unavailable (no\nexecutor wired on this deployment). Server-owned — a caller can never assert it.","type":"string"}},"type":"object"},"campaign.campaignUpdate":{"properties":{"audience":{"description":"Audience is the segment or audience selector this campaign targets.","type":"string"},"budget":{"description":"Budget is the campaign's total budget in CENTS. Negative reads as 0.","format":"int64","type":"integer"},"channels":{"description":"Channels are the fan-out targets, at most one per kind (paid, organic,\nemail) and at most 12. A channel's status and provider id are server-owned:\nwhatever the caller sends for them is replaced with \"pending\".","items":{"$ref":"#/components/schemas/campaign.ChannelSpec"},"type":"array"},"content":{"description":"Content is the ordered creative set. Content[0] is the active creative and\nthe rest are A/B variants; at most 32, empty entries dropped.","items":{"type":"string"},"type":"array"},"id":{"description":"ID is the campaign to update, from the path.","type":"string"},"name":{"description":"Name is the campaign's display name. Required; trimmed and capped at 2048\ncharacters.","type":"string"},"scheduleAt":{"description":"ScheduleAt is when the campaign should run, in unix seconds. Negative reads\nas 0 (immediately).","format":"int64","type":"integer"}},"type":"object"},"campaign.campaignWrite":{"properties":{"audience":{"description":"Audience is the segment or audience selector this campaign targets.","type":"string"},"budget":{"description":"Budget is the campaign's total budget in CENTS. Negative reads as 0.","format":"int64","type":"integer"},"channels":{"description":"Channels are the fan-out targets, at most one per kind (paid, organic,\nemail) and at most 12. A channel's status and provider id are server-owned:\nwhatever the caller sends for them is replaced with \"pending\".","items":{"$ref":"#/components/schemas/campaign.ChannelSpec"},"type":"array"},"content":{"description":"Content is the ordered creative set. Content[0] is the active creative and\nthe rest are A/B variants; at most 32, empty entries dropped.","items":{"type":"string"},"type":"array"},"name":{"description":"Name is the campaign's display name. Required; trimmed and capped at 2048\ncharacters.","type":"string"},"scheduleAt":{"description":"ScheduleAt is when the campaign should run, in unix seconds. Negative reads\nas 0 (immediately).","format":"int64","type":"integer"}},"type":"object"},"campaign.channelAdd":{"properties":{"account":{"description":"Account is the provider account this channel runs under: an ad-account, a\npage, or a mailing-list id.","type":"string"},"id":{"description":"ID is the campaign to add the channel to, from the path.","type":"string"},"kind":{"description":"Kind is the channel kind and the identity a campaign holds at most one of:\npaid, organic or email.","type":"string"},"platform":{"description":"Platform is the provider within the kind — meta, google, x, instagram, or\nthe email provider.","type":"string"}},"type":"object"},"captable.captableCompanyUpdate":{"properties":{"incorporationCountry":{"description":"IncorporationCountry is the ISO country the entity is incorporated in.\nOptional; omitted, null or empty clears it. Any JSON scalar is accepted\nand stored as its text."},"incorporationState":{"description":"IncorporationState is the state or province of incorporation. Optional;\nomitted, null or empty clears it. Any JSON scalar is accepted and stored\nas its text."},"incorporationType":{"description":"IncorporationType is the entity kind, e.g. LLC or C_CORP. Optional;\nomitted, null or empty clears it. Any JSON scalar is accepted and stored\nas its text."},"name":{"description":"Name is the company's legal name. Required, and it must be a non-empty\nstring — anything else is refused with the cap table's own validation\nerror."}},"type":"object"},"captable.captableConvertibleIn":{"properties":{"additionalTerms":{"description":"AdditionalTerms is free text for anything the fields above do not carry. Optional."},"boardApprovalDate":{"description":"BoardApprovalDate is when the board approved it, YYYY-MM-DD."},"capital":{"description":"Capital is the principal lent, in the company's currency."},"conversionCap":{"description":"ConversionCap is the valuation the note converts at, at most. Optional."},"discountRate":{"description":"DiscountRate is the discount to the next round's price, as a percentage. Optional."},"interestRate":{"description":"InterestRate is the annual interest the principal accrues, as a percentage. Optional."},"issueDate":{"description":"IssueDate is when the note was issued, YYYY-MM-DD."},"publicId":{"description":"PublicID is the note's identifier. It must be UNIQUE within the company; reusing one is refused 409."},"stakeholderId":{"description":"StakeholderID is the lender. It must name a stakeholder of THIS company."},"status":{"description":"Status is DRAFT, ACTIVE, PENDING, EXPIRED or CANCELLED."},"type":{"description":"Type is CCD, OCD or NOTE."}},"type":"object"},"captable.captableEquityPlanIn":{"properties":{"boardApprovalDate":{"description":"BoardApprovalDate is when the board adopted the plan, YYYY-MM-DD."},"comments":{"description":"Comments is a free-text note kept with the plan. Optional."},"defaultCancellatonBehavior":{"description":"DefaultCancellatonBehavior is what happens to cancelled grants: RETIRE, RETURN_TO_POOL, HOLD_AS_CAPITAL_STOCK or DEFINED_PER_PLAN_SECURITY.\n\nThe key is spelled `defaultCancellatonBehavior` — one `l` — because that is\nthe wire, and correcting it here would silently drop the field."},"initialSharesReserved":{"description":"InitialSharesReserved is how many shares the plan may grant. A whole number."},"name":{"description":"Name is the plan's name, e.g. \"2026 Stock Option Plan\"."},"planEffectiveDate":{"description":"PlanEffectiveDate is when the plan takes effect, YYYY-MM-DD. Optional."},"shareClassId":{"description":"ShareClassID is the class the plan grants from. It must name a class of THIS company."}},"type":"object"},"captable.captableInvestmentIn":{"properties":{"amount":{"description":"Amount is the money invested, in the round's own currency. Required and must\nbe positive."},"comments":{"description":"Comments is a free-text note kept with the investment. Optional."},"date":{"description":"Date is when the investment was made, YYYY-MM-DD. Optional: omitted, it is\nrecorded as today."},"id":{"description":"ID is the round to invest in. The URL is the addressing authority — a path\nsegment binds after the body and after the query — so the address decides\nwhich round is written whatever a body claims.","type":"string"},"stakeholderId":{"description":"StakeholderID is the investor. Required, and it must reference a stakeholder\nof the same company."}},"type":"object"},"captable.captableOptionIn":{"properties":{"boardApprovalDate":{"description":"BoardApprovalDate is when the board approved the grant, YYYY-MM-DD."},"cliffYears":{"description":"CliffYears is how long before ANY of the grant vests. A whole number; 0 for no cliff."},"equityPlanId":{"description":"EquityPlanID is the plan the options come from. It must name a plan of THIS company."},"exercisePrice":{"description":"ExercisePrice is the strike price per share, in the company's currency."},"expirationDate":{"description":"ExpirationDate is when unexercised options lapse, YYYY-MM-DD."},"grantId":{"description":"GrantID is the grant's identifier. It must be UNIQUE within the company; reusing one is refused 409."},"issueDate":{"description":"IssueDate is when the grant was made, YYYY-MM-DD."},"notes":{"description":"Notes is a free-text note kept with the grant. Optional."},"quantity":{"description":"Quantity is how many options to grant. A whole number above 0."},"rule144Date":{"description":"Rule144Date is when the Rule 144 holding period starts, YYYY-MM-DD."},"stakeholderId":{"description":"StakeholderID is who receives the grant. It must name a stakeholder of THIS company."},"status":{"description":"Status is DRAFT, ACTIVE, EXERCISED, EXPIRED or CANCELLED."},"type":{"description":"Type is ISO, NSO or RSU."},"vestingStartDate":{"description":"VestingStartDate is when vesting begins, YYYY-MM-DD."},"vestingYears":{"description":"VestingYears is the total vesting period. A whole number."}},"type":"object"},"captable.captableRoundCloseRequest":{"properties":{"closeDate":{"description":"CloseDate is the date to record the round as closed on. Optional: omitted,\nnull or empty records TODAY. Any JSON scalar is accepted and stored as its\ntext, and the text is stored unparsed, so a caller that wants an ISO date\nsends one."},"id":{"description":"ID is the round to close. It is the path segment: the URL is the\naddressing authority, and the org it is resolved in comes from the\ncaller's principal, so an id from another tenant is simply not found.","type":"string"}},"type":"object"},"captable.captableRoundIn":{"properties":{"name":{"description":"Name is the round's name, e.g. \"Series A\"."},"preMoneyValuation":{"description":"PreMoneyValuation is the company's valuation before the new money. Optional."},"pricePerShare":{"description":"PricePerShare is the price investors pay per share. An investment into a round with a price ISSUES the shares it buys; one into a round priced later records the money alone."},"roundType":{"description":"RoundType is PRICED, SAFE or CONVERTIBLE."},"shareClassId":{"description":"ShareClassID is the class investors receive. It must name a class of THIS company."},"targetAmount":{"description":"TargetAmount is how much the round aims to raise, in the company's currency."}},"type":"object"},"captable.captableSafeIn":{"properties":{"additionalTerms":{"description":"AdditionalTerms is free text for anything the fields above do not carry. Optional."},"boardApprovalDate":{"description":"BoardApprovalDate is when the board approved it, YYYY-MM-DD."},"capital":{"description":"Capital is the money invested, in the company's currency."},"discountRate":{"description":"DiscountRate is the discount to the next round's price, as a percentage. Optional."},"issueDate":{"description":"IssueDate is when the SAFE was signed, YYYY-MM-DD."},"publicId":{"description":"PublicID is the SAFE's identifier. It must be UNIQUE within the company; reusing one is refused 409."},"stakeholderId":{"description":"StakeholderID is the investor. It must name a stakeholder of THIS company."},"status":{"description":"Status is DRAFT, ACTIVE, PENDING, EXPIRED or CANCELLED."},"type":{"description":"Type is PRE_MONEY or POST_MONEY — which side of the new money the cap is measured on."},"valuationCap":{"description":"ValuationCap is the valuation the SAFE converts at, at most. Optional; omit for an uncapped SAFE."}},"type":"object"},"captable.captableShareClassAmend":{"properties":{"boardApprovalDate":{"description":"BoardApprovalDate is when the board approved the class, YYYY-MM-DD."},"classType":{"description":"ClassType is COMMON or PREFERRED."},"conversionRights":{"description":"ConversionRights is CONVERTS_TO_FUTURE_ROUND or CONVERTS_TO_SHARE_CLASS_ID. The second requires convertsToShareClassId."},"convertsToShareClassId":{"description":"ConvertsToShareClassID names the class this one converts into. Required when conversionRights is CONVERTS_TO_SHARE_CLASS_ID, ignored otherwise."},"id":{"description":"ID addresses the resource. The URL is the addressing authority — a path\nsegment binds after the body and after the query — so the address decides\nwhich row is written whatever a body claims.","type":"string"},"initialSharesAuthorized":{"description":"InitialSharesAuthorized is how many shares this class may issue. A whole number."},"liquidationPreferenceMultiple":{"description":"LiquidationPreferenceMultiple is the multiple of invested capital paid out before junior classes — 1 for a 1x preference."},"name":{"description":"Name is the share class's name, e.g. \"Series A Preferred\"."},"parValue":{"description":"ParValue is the nominal per-share value on the certificate, in the company's currency."},"participationCapMultiple":{"description":"ParticipationCapMultiple caps participation after the preference is paid, as a multiple of invested capital. 0 for no cap."},"pricePerShare":{"description":"PricePerShare is the issue price for this class, in the company's currency."},"seniority":{"description":"Seniority orders liquidation preference: LOWER is more senior, so 1 is paid before 2."},"stockholderApprovalDate":{"description":"StockholderApprovalDate is when the stockholders approved it, YYYY-MM-DD."},"votesPerShare":{"description":"VotesPerShare is how many votes one share of this class carries. A whole number; 0 for non-voting."}},"type":"object"},"captable.captableShareClassIn":{"properties":{"boardApprovalDate":{"description":"BoardApprovalDate is when the board approved the class, YYYY-MM-DD."},"classType":{"description":"ClassType is COMMON or PREFERRED."},"conversionRights":{"description":"ConversionRights is CONVERTS_TO_FUTURE_ROUND or CONVERTS_TO_SHARE_CLASS_ID. The second requires convertsToShareClassId."},"convertsToShareClassId":{"description":"ConvertsToShareClassID names the class this one converts into. Required when conversionRights is CONVERTS_TO_SHARE_CLASS_ID, ignored otherwise."},"initialSharesAuthorized":{"description":"InitialSharesAuthorized is how many shares this class may issue. A whole number."},"liquidationPreferenceMultiple":{"description":"LiquidationPreferenceMultiple is the multiple of invested capital paid out before junior classes — 1 for a 1x preference."},"name":{"description":"Name is the share class's name, e.g. \"Series A Preferred\"."},"parValue":{"description":"ParValue is the nominal per-share value on the certificate, in the company's currency."},"participationCapMultiple":{"description":"ParticipationCapMultiple caps participation after the preference is paid, as a multiple of invested capital. 0 for no cap."},"pricePerShare":{"description":"PricePerShare is the issue price for this class, in the company's currency."},"seniority":{"description":"Seniority orders liquidation preference: LOWER is more senior, so 1 is paid before 2."},"stockholderApprovalDate":{"description":"StockholderApprovalDate is when the stockholders approved it, YYYY-MM-DD."},"votesPerShare":{"description":"VotesPerShare is how many votes one share of this class carries. A whole number; 0 for non-voting."}},"type":"object"},"captable.captableShareIn":{"properties":{"boardApprovalDate":{"description":"BoardApprovalDate is when the board approved the issuance, YYYY-MM-DD."},"capitalContribution":{"description":"CapitalContribution is cash paid for the shares. Optional."},"certificateId":{"description":"CertificateID is the certificate number. It must be UNIQUE within the company; reusing one is refused 409."},"cliffYears":{"description":"CliffYears is how long before ANY of the grant vests. A whole number; 0 for no cliff."},"companyLegends":{"description":"CompanyLegends are the restrictive legends printed on the certificate.\n\nA LIST, and it must be sent as one: the bundle substitutes an EMPTY list for\nanything that is not an array, so a single string would be accepted and\nsilently discarded — the certificate issued with no legends and nothing\nreporting it.","items":{},"type":"array"},"debtCancelled":{"description":"DebtCancelled is debt forgiven as consideration. Optional."},"ipContribution":{"description":"IPContribution is intellectual property assigned as consideration, valued in the company's currency. Optional."},"issueDate":{"description":"IssueDate is when the shares were issued, YYYY-MM-DD."},"otherContributions":{"description":"OtherContributions is any other consideration, valued in the company's currency. Optional."},"pricePerShare":{"description":"PricePerShare is what was paid per share. Optional."},"quantity":{"description":"Quantity is how many shares to issue. A whole number above 0."},"rule144Date":{"description":"Rule144Date is when the Rule 144 holding period starts, YYYY-MM-DD. Optional."},"shareClassId":{"description":"ShareClassID is the class being issued. It must name a class of THIS company."},"stakeholderId":{"description":"StakeholderID is who receives the shares. It must name a stakeholder of THIS company."},"status":{"description":"Status is ACTIVE, DRAFT, SIGNED or PENDING."},"vestingStartDate":{"description":"VestingStartDate is when vesting begins, YYYY-MM-DD. Optional; defaults to the issue date."},"vestingYears":{"description":"VestingYears is the total vesting period. A whole number; 0 for fully vested at issue."}},"type":"object"},"captable.captableShareTransfer":{"properties":{"certificateId":{"description":"CertificateID names the NEW certificate a partial transfer issues, and is\nrequired for one — a partial transfer without it is refused 400. It is unused\nby a full transfer, which reassigns the existing certificate.\n\nIt must be unique within the company; reusing one is refused 409. Declaring\nit is not optional in the way the tag suggests: omitting this field from the\nGo type would leave `quantity` accepted and every PARTIAL transfer answering\n\"certificateId is required\" with no way for a caller to supply it — the\nsilent-drop failure this whole conversion was blocked on, one field wide."},"quantity":{"description":"Quantity is how many shares to move. OPTIONAL, and its absence is not zero:\nomitted or null transfers the WHOLE certificate. A value outside 1..held is\nrefused, so a partial transfer can never over-issue.\n\nA full transfer REASSIGNS the certificate and mints no new one; a partial\ntransfer splits it and answers with the new share's id. That is the fact a\ncaller needs from the answer, not from this comment."},"shareId":{"description":"ShareID is the certificate being transferred. Required, and it must name a\nshare in the caller org's own company — a share id from another tenant\nresolves to not-found rather than to another company's certificate."},"toStakeholderId":{"description":"ToStakeholderID is who receives them. Required, and it must reference a\nstakeholder of the SAME company; one that does not is refused 400 rather\nthan creating a dangling holder."}},"type":"object"},"captable.captableStakeholderPatch":{"properties":{"city":{"description":"City is the stakeholder's city."},"currentRelationship":{"description":"CurrentRelationship is how the stakeholder relates to the company, e.g.\nFOUNDER, INVESTOR or EMPLOYEE. This route stores it as sent — unlike\nadding a stakeholder, it is not checked against the vocabulary."},"email":{"description":"Email is the stakeholder's email. This route stores it as sent — unlike\nadding a stakeholder, it is not checked for shape or uniqueness."},"id":{"description":"ID is the stakeholder to update. It is the path segment: the URL is the\naddressing authority, and the org it is resolved in comes from the\ncaller's principal, so an id from another tenant is simply not found.","type":"string"},"institutionName":{"description":"InstitutionName names the institution, when the stakeholder is one."},"name":{"description":"Name is the stakeholder's full name."},"stakeholderType":{"description":"StakeholderType is INDIVIDUAL or INSTITUTION. This route stores it as\nsent — unlike adding a stakeholder, it is not checked against the\nvocabulary."},"state":{"description":"State is the stakeholder's state or province."},"streetAddress":{"description":"StreetAddress is the stakeholder's street address."},"taxId":{"description":"TaxID is the stakeholder's tax identifier."},"zipcode":{"description":"Zipcode is the stakeholder's postal code."}},"type":"object"},"cloudflare.D1Query":{"properties":{"params":{"description":"Params are the statement's bound values, in the order its `?` placeholders\nappear — a string, a number, a boolean or null, whatever the column takes.\nAbsent means the statement carries no placeholders; bind values here rather\nthan interpolating them into the statement.","items":{},"type":"array"},"sql":{"description":"SQL is the statement to run. Blank (or absent) is refused before anything\nreaches D1.","type":"string"}},"type":"object"},"cloudflare.PagesBuildConfig":{"properties":{"build_command":{"description":"BuildCommand is what Cloudflare runs to build the site (\"npm run build\").\nOmitted means no build step: the repository is published as it stands.","type":"string"},"destination_dir":{"description":"DestinationDir is the directory the build leaves the site in (\"dist\"),\nrelative to RootDir. It is what gets served.","type":"string"},"root_dir":{"description":"RootDir is where in the repository the build runs, for a project that is not at\nthe repository root. Omitted means the root.","type":"string"}},"type":"object"},"cloudflare.PagesD1Binding":{"properties":{"id":{"description":"ID is the D1 database this binding points at, by Cloudflare's uuid. The binding\nname the Worker code reads it as is the map key, not a field here.","type":"string"}},"type":"object"},"cloudflare.PagesDeploymentConfig":{"properties":{"compatibility_date":{"description":"CompatibilityDate pins which Workers runtime behaviour the functions run under,\nas a date (\"2024-01-01\"). It is a pin, not a version: the runtime keeps that\ndate's semantics for code deployed against it.","type":"string"},"compatibility_flags":{"description":"CompatibilityFlags turn individual runtime behaviours on or off ahead of, or\nbehind, the date above (\"nodejs_compat\").","items":{"type":"string"},"type":"array"},"d1_databases":{"additionalProperties":{"$ref":"#/components/schemas/cloudflare.PagesD1Binding"},"description":"D1Databases binds D1 databases in, keyed by binding name.","type":"object"},"env_vars":{"additionalProperties":{"$ref":"#/components/schemas/cloudflare.PagesEnvVar"},"description":"EnvVars are the environment variables the functions see, KEYED BY VARIABLE NAME.\nThe key is the name; the value carries the value and whether it is a secret.","type":"object"},"kv_namespaces":{"additionalProperties":{"$ref":"#/components/schemas/cloudflare.PagesKVBinding"},"description":"KVNamespaces binds KV namespaces into the functions, KEYED BY THE BINDING NAME\nthe code reads (`env.SESSIONS`). Same shape for the two below.","type":"object"},"r2_buckets":{"additionalProperties":{"$ref":"#/components/schemas/cloudflare.PagesR2Binding"},"description":"R2Buckets binds R2 buckets in, keyed by binding name.","type":"object"}},"type":"object"},"cloudflare.PagesDeploymentConfigs":{"properties":{"preview":{"$ref":"#/components/schemas/cloudflare.PagesDeploymentConfig","description":"Preview is the config every branch build other than the production branch runs\nunder. It is a SEPARATE set of bindings and variables, which is what lets a\npreview point at test data."},"production":{"$ref":"#/components/schemas/cloudflare.PagesDeploymentConfig","description":"Production is the config the production branch builds under."}},"type":"object"},"cloudflare.PagesEnvVar":{"properties":{"type":{"description":"Type is \"plain_text\" or \"secret_text\" and decides that: plain text is readable\nafterwards, secret text is write-only. Empty is Cloudflare's default,\nplain_text — so a secret with no type set is stored in the clear.","type":"string"},"value":{"description":"Value is the variable's value. Under type \"secret_text\" Cloudflare encrypts it\non arrival and never reads it back, so a later read of the project shows the\nvariable without this.","type":"string"}},"type":"object"},"cloudflare.PagesKVBinding":{"properties":{"namespace_id":{"description":"NamespaceID is the KV namespace this binding points at, by Cloudflare's id\nrather than its title. The BINDING NAME — what the Worker code reads it as — is\nthe map key this value sits under, not a field here.","type":"string"}},"type":"object"},"cloudflare.PagesProjectCreate":{"properties":{"build_config":{"$ref":"#/components/schemas/cloudflare.PagesBuildConfig","description":"BuildConfig says how to build the site. Omitted means no build step."},"deployment_configs":{"$ref":"#/components/schemas/cloudflare.PagesDeploymentConfigs","description":"DeploymentConfigs carries the preview and production runtime configs — the\nbindings and variables the built site's functions run with."},"name":{"description":"Name is the project name, and it is also the address: the site answers at\n.pages.dev. Cloudflare will not rename a project afterwards.","type":"string"},"production_branch":{"description":"ProductionBranch is which git branch builds to production; every other branch\nbuilds a preview. Omitted leaves Cloudflare's own default.","type":"string"}},"type":"object"},"cloudflare.PagesR2Binding":{"properties":{"name":{"description":"Name is the R2 bucket this binding points at, by bucket name — R2 addresses\nbuckets by name where KV and D1 use ids. The binding name the Worker code reads\nit as is the map key.","type":"string"}},"type":"object"},"cloudflare.WorkerScriptPut":{"properties":{"bindings":{"description":"Bindings are the resources the script can reach (KV, D1, R2, secrets, …), in\nCloudflare's own binding vocabulary, passed through as written: this plane\ndeliberately does not model Cloudflare's shapes. Absent uploads a script with\nNO bindings, which replaces whatever the previous version had."},"compatibilityDate":{"description":"CompatibilityDate pins which Workers runtime behaviour the script runs under,\nas a plain calendar date (\"2024-01-01\"). Absent leaves the account's own\ndefault in force.","type":"string"},"compatibilityFlags":{"description":"CompatibilityFlags turn individual runtime behaviours on or off around that\ndate (\"nodejs_compat\"), in Cloudflare's own flag vocabulary. Absent means the\ndate alone decides.","items":{"type":"string"},"type":"array"},"mainModule":{"description":"MainModule is the module file the runtime starts at. Absent means \"worker.js\".","type":"string"},"script":{"description":"Script means two things on this route, and the document says so in both places\nit appears: the PATH segment names the Worker to publish, and the BODY field\ncarries that Worker's ES-module source — the code itself, never a name or a\nURL. A blank or absent source is refused; there is no empty Worker.","type":"string"}},"type":"object"},"cloudflare.bucketCreateIn":{"properties":{"name":{"description":"Name is the bucket name to create.","type":"string"}},"type":"object"},"cloudflare.databaseCreateIn":{"properties":{"name":{"description":"Name is the database name to create.","type":"string"}},"type":"object"},"cloudflare.domainAddIn":{"properties":{"name":{"description":"Name is the custom domain to attach, e.g. \"www.acme.com\".","type":"string"},"project":{"description":"Project is the Pages project name, from the path.","type":"string"}},"type":"object"},"cloudflare.namespaceCreateIn":{"properties":{"title":{"description":"Title is the namespace's display title. Cloudflare mints the id.","type":"string"}},"type":"object"},"cloudflare.purgeIn":{"properties":{"files":{"description":"Files purges exactly the listed URLs — at most 30, Cloudflare's per-request cap.","items":{"type":"string"},"type":"array"},"purge_everything":{"description":"Everything drops the zone's entire edge cache.","type":"boolean"},"zone":{"description":"Zone is the 32-hex Cloudflare zone id, from the path.","type":"string"}},"type":"object"},"cloudflare.routeCreateIn":{"properties":{"pattern":{"description":"Pattern is the URL pattern to bind, e.g. \"acme.com/api/*\".","type":"string"},"script":{"description":"Script is the Worker script to dispatch to. Omit it to leave the pattern\nbound to no script, which is how Cloudflare expresses \"bypass the Worker here\".","type":"string"},"zone":{"description":"Zone is the 32-hex Cloudflare zone id, from the path.","type":"string"}},"type":"object"},"cloudflare.subdomainSetIn":{"properties":{"enabled":{"description":"Enabled publishes the script on