Changes one class’s band, target, size range or short size range and
keeps every other rule in the scenario. The same function backs the MCP
server’s save_class_rule and runs the checks the app’s one-rule
dialog runs. A field you leave out keeps its value.
A new rule needs a band or a size range. band_min_pct must be
below band_max_pct, or both 0 for none of the class.
target_pct needs a band and must sit inside it
(TARGET_OUT_OF_BAND).
The size fields are set together, or cleared together with
null. The short size fields (short_size_min_pct and
short_size_max_pct) work the same way.
Both band fields null, with none of the four size fields sent,
removes the class’s rule. With a size field they clear the band
and keep the rule: the class total is no longer judged.
An unknown class name is NOT_FOUND, with the valid names in
valid_values, unless create_class is true.
Saves a restore point first, so POST /rules/restore-points/{id}/restore undoes it like an import.
Requires the API key to have the write permission.
Raw API key shown once when created in the Allocait app (Settings > API keys). Send it verbatim in this header; the server stores and compares only its SHA-256 hash. Allocait generates every key: alc_ followed by 64 lowercase hex characters. Keys issued before 2026-10-10 are 64 hex characters with no prefix and keep working. A key may carry an expiry (90 days or 1 year, or never). A malformed, unknown, revoked or expired key gets 401 with no further detail, and a malformed one is refused before any lookup. Keys cannot be created through this API.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Allocait","description":"Allocait checks a portfolio against the owner's own allocation rules. This site documents the REST API agents call and how to connect Claude, ChatGPT and Codex to it.","colors":{"primary":"#0b0b0b","light":"#ffc629","dark":"#0b0b0b"},"logo":{"light":"https://mintcdn.com/allocait/N9X8GrpLUSiZAKIm/logo/light.svg?fit=max\u0026auto=format\u0026n=N9X8GrpLUSiZAKIm\u0026q=85\u0026s=37c68a7ac5dc3550d24f484060530ea6","dark":"https://mintcdn.com/allocait/N9X8GrpLUSiZAKIm/logo/dark.svg?fit=max\u0026auto=format\u0026n=N9X8GrpLUSiZAKIm\u0026q=85\u0026s=64ac292a0a27672b4ff7d318734b0a5a","href":"https://allocait.app"},"favicon":"https://mintcdn.com/allocait/N9X8GrpLUSiZAKIm/logo/favicon.svg?fit=max\u0026auto=format\u0026n=N9X8GrpLUSiZAKIm\u0026q=85\u0026s=ff094ad764f4dfe37dbf99bdd5c9aaf4","api":{"playground":{"display":"simple"}},"appearance":{"default":"dark"},"background":{"color":{"light":"#ffffff","dark":"#09090b"}},"navbar":{"links":[{"href":"mailto:support@allocait.app","label":"Support"}],"primary":{"type":"button","label":"allocait.app","href":"https://allocait.app"}},"footer":{"links":[{"header":"Product","items":[{"label":"allocait.app","href":"https://allocait.app"},{"label":"Support","href":"mailto:support@allocait.app"}]}]},"icons":{"library":"tabler"},"contextual":{"options":["copy","view","chatgpt","claude","mcp","cursor","vscode"],"display":"header"},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"allocait","hasAudioNarration":false,"actualSubdomain":"allocait","customDomains":["docs.allocait.app"],"gitSource":{"type":"github","owner":"allocait-app","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"entitlements":{"AI_CHAT":{"status":"DISABLED"},"WEB_MCP":{"status":"DISABLED"},"NARRATION":{"status":"DISABLED"}},"buildId":"6af158c3927786a3649023cd","clientVersion":"0.0.4102","searchFilterCounts":[{"language":"default","tag":"API reference","count":95},{"language":"default","tag":"Endpoints","count":84},{"language":"default","tag":"Concepts","count":24},{"language":"default","tag":"Claude \u0026 MCP","count":23},{"language":"default","tag":"Rules","count":22},{"language":"default","tag":"Guides","count":13},{"language":"default","tag":"Tools","count":12},{"language":"default","tag":"Inputs","count":12},{"language":"default","tag":"ChatGPT \u0026 Codex","count":10},{"language":"default","tag":"Watchlists","count":9}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"img.nav-logo{height:1rem!important;width:auto!important}.callout[data-callout-type=\"note\"],.callout[data-callout-type=\"info\"],.callout[data-callout-type=\"tip\"]{background-color:rgb(255 198 41 / 0.2)!important;border-color:rgb(255 198 41 / 0.6)!important}.callout[data-callout-type=\"note\"] *,.callout[data-callout-type=\"info\"] *,.callout[data-callout-type=\"tip\"] *{color:#0b0b0b!important}.callout[data-callout-type=\"note\"] svg,.callout[data-callout-type=\"info\"] svg,.callout[data-callout-type=\"tip\"] svg{fill:#0b0b0b!important}html.dark .callout[data-callout-type=\"note\"],html.dark .callout[data-callout-type=\"info\"],html.dark .callout[data-callout-type=\"tip\"]{background-color:rgb(255 198 41 / 0.1)!important;border-color:rgb(255 198 41 / 0.35)!important}html.dark .callout[data-callout-type=\"note\"] *,html.dark .callout[data-callout-type=\"info\"] *,html.dark .callout[data-callout-type=\"tip\"] *{color:#ffc629!important}html.dark .callout[data-callout-type=\"note\"] svg,html.dark .callout[data-callout-type=\"info\"] svg,html.dark .callout[data-callout-type=\"tip\"] svg{fill:#ffc629!important}"}],"page":{"pagePath":"api-reference/rules/set-one-asset-classs-rule-in-a-scenario","slug":"/api-reference/rules/set-one-asset-classs-rule-in-a-scenario","pageMetadata":{"title":"Set one asset class's rule in a scenario","description":"Changes one class's band, target, size range or short size range and\nkeeps every other rule in the scenario. The same function backs the MCP\nserver's `save_class_rule` and runs the checks the app's one-rule\ndialog runs. A field you leave out keeps its value.\n\n- A new rule needs a band or a size range. `band_min_pct` must be\n below `band_max_pct`, or both 0 for none of the class.\n- `target_pct` needs a band and must sit inside it\n (`TARGET_OUT_OF_BAND`).\n- The size fields are set together, or cleared together with\n `null`. The short size fields (`short_size_min_pct` and\n `short_size_max_pct`) work the same way.\n- Both band fields `null`, with none of the four size fields sent,\n removes the class's rule. With a size field they clear the band\n and keep the rule: the class total is no longer judged.\n- An unknown class name is `NOT_FOUND`, with the valid names in\n `valid_values`, unless `create_class` is `true`.\n\nSaves a restore point first, so `POST\n/rules/restore-points/{id}/restore` undoes it like an import.\n\n**Requires the API key to have the `write` permission.**\n","deprecated":null,"version":null,"openapi":"/openapi.yaml post /scenarios/{id}/position-rules","href":"/api-reference/rules/set-one-asset-classs-rule-in-a-scenario","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n li: \"li\",\n p: \"p\",\n strong: \"strong\",\n ul: \"ul\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsxs(_components.p, {\n children: [\"Changes one class’s band, target, size range or short size range and\\nkeeps every other rule in the scenario. The same function backs the MCP\\nserver’s \", _jsx(_components.code, {\n children: \"save_class_rule\"\n }), \" and runs the checks the app’s one-rule\\ndialog runs. A field you leave out keeps its value.\"]\n }), \"\\n\", _jsxs(_components.ul, {\n children: [\"\\n\", _jsxs(_components.li, {\n children: [\"A new rule needs a band or a size range. \", _jsx(_components.code, {\n children: \"band_min_pct\"\n }), \" must be\\nbelow \", _jsx(_components.code, {\n children: \"band_max_pct\"\n }), \", or both 0 for none of the class.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [_jsx(_components.code, {\n children: \"target_pct\"\n }), \" needs a band and must sit inside it\\n(\", _jsx(_components.code, {\n children: \"TARGET_OUT_OF_BAND\"\n }), \").\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"The size fields are set together, or cleared together with\\n\", _jsx(_components.code, {\n children: \"null\"\n }), \". The short size fields (\", _jsx(_components.code, {\n children: \"short_size_min_pct\"\n }), \" and\\n\", _jsx(_components.code, {\n children: \"short_size_max_pct\"\n }), \") work the same way.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"Both band fields \", _jsx(_components.code, {\n children: \"null\"\n }), \", with none of the four size fields sent,\\nremoves the class’s rule. With a size field they clear the band\\nand keep the rule: the class total is no longer judged.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"An unknown class name is \", _jsx(_components.code, {\n children: \"NOT_FOUND\"\n }), \", with the valid names in\\n\", _jsx(_components.code, {\n children: \"valid_values\"\n }), \", unless \", _jsx(_components.code, {\n children: \"create_class\"\n }), \" is \", _jsx(_components.code, {\n children: \"true\"\n }), \".\"]\n }), \"\\n\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Saves a restore point first, so \", _jsx(_components.code, {\n children: \"POST /rules/restore-points/{id}/restore\"\n }), \" undoes it like an import.\"]\n }), \"\\n\", _jsx(_components.p, {\n children: _jsxs(_components.strong, {\n children: [\"Requires the API key to have the \", _jsx(_components.code, {\n children: \"write\"\n }), \" permission.\"]\n })\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Set one asset class's rule in a scenario","description":"Changes one class's band, target, size range or short size range and\nkeeps every other rule in the scenario. The same function backs the MCP\nserver's `save_class_rule` and runs the checks the app's one-rule\ndialog runs. A field you leave out keeps its value.\n\n- A new rule needs a band or a size range. `band_min_pct` must be\n below `band_max_pct`, or both 0 for none of the class.\n- `target_pct` needs a band and must sit inside it\n (`TARGET_OUT_OF_BAND`).\n- The size fields are set together, or cleared together with\n `null`. The short size fields (`short_size_min_pct` and\n `short_size_max_pct`) work the same way.\n- Both band fields `null`, with none of the four size fields sent,\n removes the class's rule. With a size field they clear the band\n and keep the rule: the class total is no longer judged.\n- An unknown class name is `NOT_FOUND`, with the valid names in\n `valid_values`, unless `create_class` is `true`.\n\nSaves a restore point first, so `POST\n/rules/restore-points/{id}/restore` undoes it like an import.\n\n**Requires the API key to have the `write` permission.**\n","deprecated":null,"version":null,"openapi":"/openapi.yaml post /scenarios/{id}/position-rules","href":"/api-reference/rules/set-one-asset-classs-rule-in-a-scenario","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"tags":["Rules"],"operationId":"savePositionRule","summary":"Set one asset class's rule in a scenario","description":"Changes one class's band, target, size range or short size range and\nkeeps every other rule in the scenario. The same function backs the MCP\nserver's `save_class_rule` and runs the checks the app's one-rule\ndialog runs. A field you leave out keeps its value.\n\n- A new rule needs a band or a size range. `band_min_pct` must be\n below `band_max_pct`, or both 0 for none of the class.\n- `target_pct` needs a band and must sit inside it\n (`TARGET_OUT_OF_BAND`).\n- The size fields are set together, or cleared together with\n `null`. The short size fields (`short_size_min_pct` and\n `short_size_max_pct`) work the same way.\n- Both band fields `null`, with none of the four size fields sent,\n removes the class's rule. With a size field they clear the band\n and keep the rule: the class total is no longer judged.\n- An unknown class name is `NOT_FOUND`, with the valid names in\n `valid_values`, unless `create_class` is `true`.\n\nSaves a restore point first, so `POST\n/rules/restore-points/{id}/restore` undoes it like an import.\n\n**Requires the API key to have the `write` permission.**\n","security":["b8533fd0-f800-40c9-8f27-5e78a8812ba7"],"parameters":["9af074f1-7b47-4200-a175-b210735238e2"],"requestBody":"75a71e78-b053-4619-b817-053bf876c02d","responses":{"200":"f36a6d28-e2c1-40eb-808b-3ff3d8153181","400":"826a1bec-ce09-4d71-8b80-e31112e7c3be","401":"1eb3ab0d-1c49-42b4-9d59-b308aa63cdf2","403":"28da3675-fcb9-4e6a-9d15-fb80c0b1be7c","404":"1cb8dd63-8c6e-4722-984b-4a91ad844c4f","429":"b2a4ee1d-c3a0-4f8e-8e6f-364394cdb951","500":"eea7446e-29a4-4a8e-a2e0-5c94410cb043"},"method":"post","type":"path","servers":["13120e45-325e-41e1-99fd-a11d6f409d02"],"path":"/scenarios/{id}/position-rules","baseUrlOptions":["https://allocait.app/api/v1"],"title":"Set one asset class's rule in a scenario","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"9af074f1-7b47-4200-a175-b210735238e2":{"name":"id","in":"path","required":true,"description":"scenario_id","schema":{"type":"string","format":"uuid","isRequired":true,"description":"scenario_id","uniqueKey":"","typeLabel":"string\u003cuuid>"}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["asset_class"],"properties":{"asset_class":{"type":"string","description":"Class name, rules text alias or id. Resolved own class first, then the system class, then the alias.","isRequired":true,"uniqueKey":"asset_class","typeLabel":"string"},"band_min_pct":{"oneOf":[{"type":"number","minimum":0,"maximum":100,"uniqueKey":"band_min_pct.oneOf.0","typeLabel":"number"},{"type":"null","minimum":0,"maximum":100,"uniqueKey":"band_min_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"band_min_pct","typeLabel":"number | null"},"band_max_pct":{"oneOf":[{"type":"number","minimum":0,"maximum":100,"uniqueKey":"band_max_pct.oneOf.0","typeLabel":"number"},{"type":"null","minimum":0,"maximum":100,"uniqueKey":"band_max_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"band_max_pct","typeLabel":"number | null"},"target_pct":{"oneOf":[{"type":"number","minimum":0,"maximum":100,"uniqueKey":"target_pct.oneOf.0","typeLabel":"number"},{"type":"null","minimum":0,"maximum":100,"uniqueKey":"target_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"target_pct","typeLabel":"number | null"},"size_min_pct":{"oneOf":[{"type":"number","minimum":0,"maximum":100,"uniqueKey":"size_min_pct.oneOf.0","typeLabel":"number"},{"type":"null","minimum":0,"maximum":100,"uniqueKey":"size_min_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"size_min_pct","typeLabel":"number | null"},"size_max_pct":{"oneOf":[{"type":"number","minimum":0,"maximum":100,"uniqueKey":"size_max_pct.oneOf.0","typeLabel":"number"},{"type":"null","minimum":0,"maximum":100,"uniqueKey":"size_max_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"size_max_pct","typeLabel":"number | null"},"short_size_min_pct":{"oneOf":[{"type":"number","minimum":0,"maximum":100,"uniqueKey":"short_size_min_pct.oneOf.0","typeLabel":"number"},{"type":"null","minimum":0,"maximum":100,"uniqueKey":"short_size_min_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"short_size_min_pct","typeLabel":"number | null"},"short_size_max_pct":{"oneOf":[{"type":"number","minimum":0,"maximum":100,"uniqueKey":"short_size_max_pct.oneOf.0","typeLabel":"number"},{"type":"null","minimum":0,"maximum":100,"uniqueKey":"short_size_max_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"short_size_max_pct","typeLabel":"number | null"},"create_class":{"type":"boolean","default":false,"description":"Create a custom class when `asset_class` names none. Set it only when the user asked for a new class.","uniqueKey":"create_class","typeLabel":"boolean"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"asset_class":"\u003cstring>","band_min_pct":50,"band_max_pct":50,"target_pct":50,"size_min_pct":50,"size_max_pct":50,"short_size_min_pct":50,"short_size_max_pct":50,"create_class":false}}},"exampleType":"generated"}},"exampleType":"generated"},"responses":{"f36a6d28-e2c1-40eb-808b-3ff3d8153181":{"description":"The rule was saved","headers":{"X-RateLimit-Limit":{"description":"The per-minute request budget, always `60`. Sent on every response that reaches a route and on the per-minute `429`.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests left in the current one-minute window, after this one. The daily count is not reported until it is reached.","schema":{"type":"integer","example":41}}},"content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","uniqueKey":"success","typeLabel":"boolean"},"scenario_id":{"type":"string","format":"uuid","uniqueKey":"scenario_id","typeLabel":"string\u003cuuid>"},"change":{"type":"string","enum":["added","changed","removed","unchanged"],"uniqueKey":"change","typeLabel":"enum\u003cstring>"},"asset_class":{"type":"string","uniqueKey":"asset_class","typeLabel":"string"},"asset_class_id":{"type":"string","format":"uuid","uniqueKey":"asset_class_id","typeLabel":"string\u003cuuid>"},"before":{"oneOf":[{"type":"object","description":"The class's rule before this call, or null when it had none.","properties":{"band_min_pct":{"oneOf":[{"type":"number","uniqueKey":"before.oneOf.0.band_min_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"before.oneOf.0.band_min_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"before.oneOf.0.band_min_pct","typeLabel":"number | null"},"band_max_pct":{"oneOf":[{"type":"number","uniqueKey":"before.oneOf.0.band_max_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"before.oneOf.0.band_max_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"before.oneOf.0.band_max_pct","typeLabel":"number | null"},"target_pct":{"oneOf":[{"type":"number","uniqueKey":"before.oneOf.0.target_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"before.oneOf.0.target_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"before.oneOf.0.target_pct","typeLabel":"number | null"},"size_min_pct":{"oneOf":[{"type":"number","uniqueKey":"before.oneOf.0.size_min_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"before.oneOf.0.size_min_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"before.oneOf.0.size_min_pct","typeLabel":"number | null"},"size_max_pct":{"oneOf":[{"type":"number","uniqueKey":"before.oneOf.0.size_max_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"before.oneOf.0.size_max_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"before.oneOf.0.size_max_pct","typeLabel":"number | null"},"short_size_min_pct":{"oneOf":[{"type":"number","uniqueKey":"before.oneOf.0.short_size_min_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"before.oneOf.0.short_size_min_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"before.oneOf.0.short_size_min_pct","typeLabel":"number | null"},"short_size_max_pct":{"oneOf":[{"type":"number","uniqueKey":"before.oneOf.0.short_size_max_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"before.oneOf.0.short_size_max_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"before.oneOf.0.short_size_max_pct","typeLabel":"number | null"}},"uniqueKey":"before.oneOf.0","typeLabel":"object"},{"type":"null","description":"The class's rule before this call, or null when it had none.","uniqueKey":"before.oneOf.1","typeLabel":"null"}],"uniqueKey":"before","typeLabel":"object | null"},"after":{"oneOf":[{"type":"object","description":"The class's rule after this call, or null when the call removed it.","properties":{"band_min_pct":{"oneOf":[{"type":"number","uniqueKey":"after.oneOf.0.band_min_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"after.oneOf.0.band_min_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"after.oneOf.0.band_min_pct","typeLabel":"number | null"},"band_max_pct":{"oneOf":[{"type":"number","uniqueKey":"after.oneOf.0.band_max_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"after.oneOf.0.band_max_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"after.oneOf.0.band_max_pct","typeLabel":"number | null"},"target_pct":{"oneOf":[{"type":"number","uniqueKey":"after.oneOf.0.target_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"after.oneOf.0.target_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"after.oneOf.0.target_pct","typeLabel":"number | null"},"size_min_pct":{"oneOf":[{"type":"number","uniqueKey":"after.oneOf.0.size_min_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"after.oneOf.0.size_min_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"after.oneOf.0.size_min_pct","typeLabel":"number | null"},"size_max_pct":{"oneOf":[{"type":"number","uniqueKey":"after.oneOf.0.size_max_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"after.oneOf.0.size_max_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"after.oneOf.0.size_max_pct","typeLabel":"number | null"},"short_size_min_pct":{"oneOf":[{"type":"number","uniqueKey":"after.oneOf.0.short_size_min_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"after.oneOf.0.short_size_min_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"after.oneOf.0.short_size_min_pct","typeLabel":"number | null"},"short_size_max_pct":{"oneOf":[{"type":"number","uniqueKey":"after.oneOf.0.short_size_max_pct.oneOf.0","typeLabel":"number"},{"type":"null","uniqueKey":"after.oneOf.0.short_size_max_pct.oneOf.1","typeLabel":"null"}],"uniqueKey":"after.oneOf.0.short_size_max_pct","typeLabel":"number | null"}},"uniqueKey":"after.oneOf.0","typeLabel":"object"},{"type":"null","description":"The class's rule after this call, or null when the call removed it.","uniqueKey":"after.oneOf.1","typeLabel":"null"}],"uniqueKey":"after","typeLabel":"object | null"},"restore_point_id":{"type":"string","format":"uuid","uniqueKey":"restore_point_id","typeLabel":"string\u003cuuid>"},"created_class":{"type":"boolean","description":"True when `create_class` created the class.","uniqueKey":"created_class","typeLabel":"boolean"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"success":true,"scenario_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","change":"added","asset_class":"\u003cstring>","asset_class_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","before":{"band_min_pct":123,"band_max_pct":123,"target_pct":123,"size_min_pct":123,"size_max_pct":123,"short_size_min_pct":123,"short_size_max_pct":123},"after":{"band_min_pct":123,"band_max_pct":123,"target_pct":123,"size_min_pct":123,"size_max_pct":123,"short_size_min_pct":123,"short_size_max_pct":123},"restore_point_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","created_class":true}}},"exampleType":"generated"}},"exampleType":"generated"},"826a1bec-ce09-4d71-8b80-e31112e7c3be":{"description":"A band field alone, a band minimum not below its maximum, one size field or one short size field alone (`INVALID_INPUT`), or a target outside the band (`TARGET_OUT_OF_BAND`)","content":{"application/json":{"schema":{"type":"object","description":"Uniform error envelope returned by every non-2xx response. `error` is\na human-readable message, safe to show the user. A refusal also\ncarries `error_code`, a stable string from the catalog in the info\nblock's Error codes section, to branch on; the HTTP status follows\nthe code (ADR-134). Only `401`, the no-plan `403`, the `403` for a\nkey without `read` and the `429` for the request budget have none.\nA `500` carries `request_id`. Extra fields by code:\nTIER_LIMIT_EXCEEDED carries `limit_type`, `current_count` and\n`max_allowed`, so a caller can branch on how many it has versus the\ncap without a second call. Its `error` text names no plan. It covers\nthe portfolio and scenario limits and the account caps: 20 webhook endpoints, 50\nwatchlists, 200 symbols on one watchlist and 50 custom symbols on one\nmonitor. Don't retry it. RULES_INVALID (`POST\n/scenarios/{id}/rules`) carries `issues`. ALREADY_EXISTS carries\n`existing_id`, plus `duplicate_ids` where older duplicates exist.\nCONFIRMATION_REQUIRED carries `would_remove`; from `POST /setup/apply` it\ncarries a fresh preview instead (`digest`, `file`, `items` and the rest of\n`SetupPreview`). INVALID_INPUT from the setup routes carries `issues`, and\nIN_USE from `POST /setup/receipts/{id}/undo` carries `later_receipt_id`.\nNOT_FOUND on a name, and\nINVALID_INPUT on a CHOICE value, carry `valid_values`. INVALID_INPUT on a\nmonitor whose level input is not a number type carries `input_id`.\nIN_USE on an input whose type would change while a monitor uses it\ncarries `monitors`. IN_USE on `PATCH /portfolios/{id}` that turns\nAllow shorts off while a short is held carries `short_count` and\n`symbols`. INVALID_INPUT on the holdings writes (`POST\n/positions/{symbol}`, `POST /portfolios/{id}/positions/apply`) that\nrefuses a negative `shares`, a `moves` other than 1 on an Options\nholding, or a `mark` on a holding outside the Options class, carries\n`symbols`, the holdings it refused. (`symbols` also appears on `WOULD_CLOSE_POSITIONS`, MCP\nonly, where it lists the holdings a full list left out.)\n","required":["error"],"example":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"},"properties":{"error":{"type":"string","description":"Human-readable error message.","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"error_code":{"type":"string","enum":["INVALID_INPUT","NOT_FOUND","ALREADY_EXISTS","IN_USE","CONFIRMATION_REQUIRED","PRICES_INCOMPLETE","PRICES_INVALID","WOULD_CLOSE_POSITIONS","INSUFFICIENT_CASH","RULES_INVALID","TARGET_OUT_OF_BAND","TIER_LIMIT_EXCEEDED","FEATURE_NOT_AVAILABLE","IDEMPOTENCY_KEY_CONFLICT","DAILY_LIMIT_EXCEEDED","READ_ONLY_KEY","OAUTH_WRITE_NOT_GRANTED","TOOL_REMOVED","INTERNAL_ERROR"],"description":"Stable machine-readable code from the closed catalog. Present on every refusal a route produces; absent on `401`, the no-plan `403`, the `403` for a key without `read`, and the `429` for the request budget.","uniqueKey":"error_code","typeLabel":"enum\u003cstring>"},"request_id":{"type":"string","format":"uuid","description":"Present on a `500` (`INTERNAL_ERROR`). The same id is in Allocait's logs next to the real cause; quote it when you report the failure.","uniqueKey":"request_id","typeLabel":"string\u003cuuid>"},"issues":{"type":"array","items":{"oneOf":[{"type":"object","description":"One problem or note found while reading rules text. A file\ncarrying any `error`-level issue is never applied; `POST\n/scenarios/{id}/rules` 400s with `error_code: RULES_INVALID` and\nthe full `issues` list instead. A file with only `warning`-level\nissues still applies; those ride along on the 200 response.\n","required":["level","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.level","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.message","typeLabel":"string"},"class":{"type":"string","description":"The asset class name this issue is about, when it is about one class rather than the whole file.","uniqueKey":"issues.items.[INDEX].oneOf.0.class","typeLabel":"string"}},"uniqueKey":"issues.items.[INDEX].oneOf.0","typeLabel":"object"},{"type":"object","description":"One thing the file's text got wrong (`error`) or one note about it (`warning`, such as a web address in a description).","required":["level","where","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.level","typeLabel":"enum\u003cstring>"},"where":{"oneOf":[{"type":"string","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.0","typeLabel":"string"},{"type":"null","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where","typeLabel":"string | null"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.message","typeLabel":"string"},"line":{"type":"integer","description":"The line of the file the issue is on, when it is known.","uniqueKey":"issues.items.[INDEX].oneOf.1.line","typeLabel":"integer"}},"uniqueKey":"issues.items.[INDEX].oneOf.1","typeLabel":"object"}],"uniqueKey":"issues.items.[INDEX]","typeLabel":"object"},"description":"Every error and warning found while reading the rules text, when error_code is RULES_INVALID. From the setup routes (`POST /setup/preview`, `POST /setup/apply`) it is `SetupIssue` rows, on INVALID_INPUT.","uniqueKey":"issues","typeLabel":"object[]"},"later_receipt_id":{"type":"string","format":"uuid","description":"The newer import of the same setup file that blocks this undo. Present on IN_USE from `POST /setup/receipts/{id}/undo`; undo that receipt first.","uniqueKey":"later_receipt_id","typeLabel":"string\u003cuuid>"},"limit_type":{"type":"string","description":"Which cap was hit, e.g. \"portfolios\", \"scenarios\", \"webhook_endpoints\", \"watchlists\", \"asset_classes\", \"input_entries\" or \"input_entries_per_input\". Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"limit_type","typeLabel":"string"},"current_count":{"type":"number","description":"How many of limit_type the caller has right now. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"current_count","typeLabel":"number"},"max_allowed":{"type":"number","description":"The cap for limit_type on this account. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"max_allowed","typeLabel":"number"},"existing_id":{"type":"string","format":"uuid","description":"The record that already has this name. Present only when error_code is ALREADY_EXISTS; change it with that id instead of creating another.","uniqueKey":"existing_id","typeLabel":"string\u003cuuid>"},"duplicate_ids":{"type":"array","items":{"type":"string","format":"uuid","uniqueKey":"duplicate_ids.items.[INDEX]","typeLabel":"string\u003cuuid>"},"description":"Other records with the same name, created before duplicates were refused. Present only on ALREADY_EXISTS, and only when such records exist.","uniqueKey":"duplicate_ids","typeLabel":"string\u003cuuid>[]"},"would_remove":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","uniqueKey":"would_remove.additionalProperties.items.[INDEX]","typeLabel":"string"},"uniqueKey":"would_remove.additionalProperties","typeLabel":"string[]"},"description":"What the call would drop, keyed by list field, for example the `items` that a watchlist save would remove. Present only when error_code is CONFIRMATION_REQUIRED; resend with those members in `remove`.","uniqueKey":"would_remove","typeLabel":"object"},"valid_values":{"type":"array","items":{"type":"string","uniqueKey":"valid_values.items.[INDEX]","typeLabel":"string"},"description":"The names or options the field accepts. Present on NOT_FOUND for a name, and on INVALID_INPUT for a CHOICE value.","uniqueKey":"valid_values","typeLabel":"string[]"},"input_id":{"type":"string","format":"uuid","description":"The level input that is not a NUMBER, DECIMAL or PERCENTAGE input. Present on INVALID_INPUT from a monitor create or update (`POST /monitors`, `PATCH /monitors/{id}`, MCP `save_monitor`); point the monitor at a number-type input instead.","uniqueKey":"input_id","typeLabel":"string\u003cuuid>"},"short_count":{"type":"integer","description":"How many shorts the portfolio holds. Present on IN_USE from `PATCH /portfolios/{id}` (MCP `save_portfolio`) that turns Allow shorts off while a short is held; close them first.","uniqueKey":"short_count","typeLabel":"integer"},"symbols":{"type":"array","items":{"type":"string","uniqueKey":"symbols.items.[INDEX]","typeLabel":"string"},"description":"Holdings the call names. On IN_USE from `PATCH /portfolios/{id}`, the shorts still held (up to 20, by symbol). On INVALID_INPUT from the holdings writes, the holdings whose negative `shares` was refused (Allow shorts is off, or the holding is in Options), or whose `moves` other than 1 was refused (the holding is in Options). On WOULD_CLOSE_POSITIONS (MCP only), the holdings a full list left out.","uniqueKey":"symbols","typeLabel":"string[]"},"monitors":{"type":"array","description":"The monitors that use this input as a level. Present on IN_USE from an input update (`PATCH /inputs/{id}`, MCP `save_input`) that would change `data_type` to TEXT or CHOICE; move those monitors to another input first.","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"name":{"type":"string","uniqueKey":"monitors.items.[INDEX].name","typeLabel":"string"},"portfolio_id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].portfolio_id","typeLabel":"string\u003cuuid>"}},"uniqueKey":"monitors.items.[INDEX]","typeLabel":"object"},"uniqueKey":"monitors","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"}}},"exampleType":"generated"}},"exampleType":"generated"},"1eb3ab0d-1c49-42b4-9d59-b308aa63cdf2":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"type":"object","description":"Uniform error envelope returned by every non-2xx response. `error` is\na human-readable message, safe to show the user. A refusal also\ncarries `error_code`, a stable string from the catalog in the info\nblock's Error codes section, to branch on; the HTTP status follows\nthe code (ADR-134). Only `401`, the no-plan `403`, the `403` for a\nkey without `read` and the `429` for the request budget have none.\nA `500` carries `request_id`. Extra fields by code:\nTIER_LIMIT_EXCEEDED carries `limit_type`, `current_count` and\n`max_allowed`, so a caller can branch on how many it has versus the\ncap without a second call. Its `error` text names no plan. It covers\nthe portfolio and scenario limits and the account caps: 20 webhook endpoints, 50\nwatchlists, 200 symbols on one watchlist and 50 custom symbols on one\nmonitor. Don't retry it. RULES_INVALID (`POST\n/scenarios/{id}/rules`) carries `issues`. ALREADY_EXISTS carries\n`existing_id`, plus `duplicate_ids` where older duplicates exist.\nCONFIRMATION_REQUIRED carries `would_remove`; from `POST /setup/apply` it\ncarries a fresh preview instead (`digest`, `file`, `items` and the rest of\n`SetupPreview`). INVALID_INPUT from the setup routes carries `issues`, and\nIN_USE from `POST /setup/receipts/{id}/undo` carries `later_receipt_id`.\nNOT_FOUND on a name, and\nINVALID_INPUT on a CHOICE value, carry `valid_values`. INVALID_INPUT on a\nmonitor whose level input is not a number type carries `input_id`.\nIN_USE on an input whose type would change while a monitor uses it\ncarries `monitors`. IN_USE on `PATCH /portfolios/{id}` that turns\nAllow shorts off while a short is held carries `short_count` and\n`symbols`. INVALID_INPUT on the holdings writes (`POST\n/positions/{symbol}`, `POST /portfolios/{id}/positions/apply`) that\nrefuses a negative `shares`, a `moves` other than 1 on an Options\nholding, or a `mark` on a holding outside the Options class, carries\n`symbols`, the holdings it refused. (`symbols` also appears on `WOULD_CLOSE_POSITIONS`, MCP\nonly, where it lists the holdings a full list left out.)\n","required":["error"],"example":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"},"properties":{"error":{"type":"string","description":"Human-readable error message.","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"error_code":{"type":"string","enum":["INVALID_INPUT","NOT_FOUND","ALREADY_EXISTS","IN_USE","CONFIRMATION_REQUIRED","PRICES_INCOMPLETE","PRICES_INVALID","WOULD_CLOSE_POSITIONS","INSUFFICIENT_CASH","RULES_INVALID","TARGET_OUT_OF_BAND","TIER_LIMIT_EXCEEDED","FEATURE_NOT_AVAILABLE","IDEMPOTENCY_KEY_CONFLICT","DAILY_LIMIT_EXCEEDED","READ_ONLY_KEY","OAUTH_WRITE_NOT_GRANTED","TOOL_REMOVED","INTERNAL_ERROR"],"description":"Stable machine-readable code from the closed catalog. Present on every refusal a route produces; absent on `401`, the no-plan `403`, the `403` for a key without `read`, and the `429` for the request budget.","uniqueKey":"error_code","typeLabel":"enum\u003cstring>"},"request_id":{"type":"string","format":"uuid","description":"Present on a `500` (`INTERNAL_ERROR`). The same id is in Allocait's logs next to the real cause; quote it when you report the failure.","uniqueKey":"request_id","typeLabel":"string\u003cuuid>"},"issues":{"type":"array","items":{"oneOf":[{"type":"object","description":"One problem or note found while reading rules text. A file\ncarrying any `error`-level issue is never applied; `POST\n/scenarios/{id}/rules` 400s with `error_code: RULES_INVALID` and\nthe full `issues` list instead. A file with only `warning`-level\nissues still applies; those ride along on the 200 response.\n","required":["level","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.level","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.message","typeLabel":"string"},"class":{"type":"string","description":"The asset class name this issue is about, when it is about one class rather than the whole file.","uniqueKey":"issues.items.[INDEX].oneOf.0.class","typeLabel":"string"}},"uniqueKey":"issues.items.[INDEX].oneOf.0","typeLabel":"object"},{"type":"object","description":"One thing the file's text got wrong (`error`) or one note about it (`warning`, such as a web address in a description).","required":["level","where","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.level","typeLabel":"enum\u003cstring>"},"where":{"oneOf":[{"type":"string","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.0","typeLabel":"string"},{"type":"null","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where","typeLabel":"string | null"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.message","typeLabel":"string"},"line":{"type":"integer","description":"The line of the file the issue is on, when it is known.","uniqueKey":"issues.items.[INDEX].oneOf.1.line","typeLabel":"integer"}},"uniqueKey":"issues.items.[INDEX].oneOf.1","typeLabel":"object"}],"uniqueKey":"issues.items.[INDEX]","typeLabel":"object"},"description":"Every error and warning found while reading the rules text, when error_code is RULES_INVALID. From the setup routes (`POST /setup/preview`, `POST /setup/apply`) it is `SetupIssue` rows, on INVALID_INPUT.","uniqueKey":"issues","typeLabel":"object[]"},"later_receipt_id":{"type":"string","format":"uuid","description":"The newer import of the same setup file that blocks this undo. Present on IN_USE from `POST /setup/receipts/{id}/undo`; undo that receipt first.","uniqueKey":"later_receipt_id","typeLabel":"string\u003cuuid>"},"limit_type":{"type":"string","description":"Which cap was hit, e.g. \"portfolios\", \"scenarios\", \"webhook_endpoints\", \"watchlists\", \"asset_classes\", \"input_entries\" or \"input_entries_per_input\". Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"limit_type","typeLabel":"string"},"current_count":{"type":"number","description":"How many of limit_type the caller has right now. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"current_count","typeLabel":"number"},"max_allowed":{"type":"number","description":"The cap for limit_type on this account. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"max_allowed","typeLabel":"number"},"existing_id":{"type":"string","format":"uuid","description":"The record that already has this name. Present only when error_code is ALREADY_EXISTS; change it with that id instead of creating another.","uniqueKey":"existing_id","typeLabel":"string\u003cuuid>"},"duplicate_ids":{"type":"array","items":{"type":"string","format":"uuid","uniqueKey":"duplicate_ids.items.[INDEX]","typeLabel":"string\u003cuuid>"},"description":"Other records with the same name, created before duplicates were refused. Present only on ALREADY_EXISTS, and only when such records exist.","uniqueKey":"duplicate_ids","typeLabel":"string\u003cuuid>[]"},"would_remove":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","uniqueKey":"would_remove.additionalProperties.items.[INDEX]","typeLabel":"string"},"uniqueKey":"would_remove.additionalProperties","typeLabel":"string[]"},"description":"What the call would drop, keyed by list field, for example the `items` that a watchlist save would remove. Present only when error_code is CONFIRMATION_REQUIRED; resend with those members in `remove`.","uniqueKey":"would_remove","typeLabel":"object"},"valid_values":{"type":"array","items":{"type":"string","uniqueKey":"valid_values.items.[INDEX]","typeLabel":"string"},"description":"The names or options the field accepts. Present on NOT_FOUND for a name, and on INVALID_INPUT for a CHOICE value.","uniqueKey":"valid_values","typeLabel":"string[]"},"input_id":{"type":"string","format":"uuid","description":"The level input that is not a NUMBER, DECIMAL or PERCENTAGE input. Present on INVALID_INPUT from a monitor create or update (`POST /monitors`, `PATCH /monitors/{id}`, MCP `save_monitor`); point the monitor at a number-type input instead.","uniqueKey":"input_id","typeLabel":"string\u003cuuid>"},"short_count":{"type":"integer","description":"How many shorts the portfolio holds. Present on IN_USE from `PATCH /portfolios/{id}` (MCP `save_portfolio`) that turns Allow shorts off while a short is held; close them first.","uniqueKey":"short_count","typeLabel":"integer"},"symbols":{"type":"array","items":{"type":"string","uniqueKey":"symbols.items.[INDEX]","typeLabel":"string"},"description":"Holdings the call names. On IN_USE from `PATCH /portfolios/{id}`, the shorts still held (up to 20, by symbol). On INVALID_INPUT from the holdings writes, the holdings whose negative `shares` was refused (Allow shorts is off, or the holding is in Options), or whose `moves` other than 1 was refused (the holding is in Options). On WOULD_CLOSE_POSITIONS (MCP only), the holdings a full list left out.","uniqueKey":"symbols","typeLabel":"string[]"},"monitors":{"type":"array","description":"The monitors that use this input as a level. Present on IN_USE from an input update (`PATCH /inputs/{id}`, MCP `save_input`) that would change `data_type` to TEXT or CHOICE; move those monitors to another input first.","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"name":{"type":"string","uniqueKey":"monitors.items.[INDEX].name","typeLabel":"string"},"portfolio_id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].portfolio_id","typeLabel":"string\u003cuuid>"}},"uniqueKey":"monitors.items.[INDEX]","typeLabel":"object"},"uniqueKey":"monitors","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"}}},"exampleType":"generated"}},"exampleType":"generated"},"28da3675-fcb9-4e6a-9d15-fb80c0b1be7c":{"description":"Key lacks `write` permission (`READ_ONLY_KEY`; a Core account's keys read only), or API access needs an active plan","content":{"application/json":{"schema":{"type":"object","description":"Uniform error envelope returned by every non-2xx response. `error` is\na human-readable message, safe to show the user. A refusal also\ncarries `error_code`, a stable string from the catalog in the info\nblock's Error codes section, to branch on; the HTTP status follows\nthe code (ADR-134). Only `401`, the no-plan `403`, the `403` for a\nkey without `read` and the `429` for the request budget have none.\nA `500` carries `request_id`. Extra fields by code:\nTIER_LIMIT_EXCEEDED carries `limit_type`, `current_count` and\n`max_allowed`, so a caller can branch on how many it has versus the\ncap without a second call. Its `error` text names no plan. It covers\nthe portfolio and scenario limits and the account caps: 20 webhook endpoints, 50\nwatchlists, 200 symbols on one watchlist and 50 custom symbols on one\nmonitor. Don't retry it. RULES_INVALID (`POST\n/scenarios/{id}/rules`) carries `issues`. ALREADY_EXISTS carries\n`existing_id`, plus `duplicate_ids` where older duplicates exist.\nCONFIRMATION_REQUIRED carries `would_remove`; from `POST /setup/apply` it\ncarries a fresh preview instead (`digest`, `file`, `items` and the rest of\n`SetupPreview`). INVALID_INPUT from the setup routes carries `issues`, and\nIN_USE from `POST /setup/receipts/{id}/undo` carries `later_receipt_id`.\nNOT_FOUND on a name, and\nINVALID_INPUT on a CHOICE value, carry `valid_values`. INVALID_INPUT on a\nmonitor whose level input is not a number type carries `input_id`.\nIN_USE on an input whose type would change while a monitor uses it\ncarries `monitors`. IN_USE on `PATCH /portfolios/{id}` that turns\nAllow shorts off while a short is held carries `short_count` and\n`symbols`. INVALID_INPUT on the holdings writes (`POST\n/positions/{symbol}`, `POST /portfolios/{id}/positions/apply`) that\nrefuses a negative `shares`, a `moves` other than 1 on an Options\nholding, or a `mark` on a holding outside the Options class, carries\n`symbols`, the holdings it refused. (`symbols` also appears on `WOULD_CLOSE_POSITIONS`, MCP\nonly, where it lists the holdings a full list left out.)\n","required":["error"],"example":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"},"properties":{"error":{"type":"string","description":"Human-readable error message.","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"error_code":{"type":"string","enum":["INVALID_INPUT","NOT_FOUND","ALREADY_EXISTS","IN_USE","CONFIRMATION_REQUIRED","PRICES_INCOMPLETE","PRICES_INVALID","WOULD_CLOSE_POSITIONS","INSUFFICIENT_CASH","RULES_INVALID","TARGET_OUT_OF_BAND","TIER_LIMIT_EXCEEDED","FEATURE_NOT_AVAILABLE","IDEMPOTENCY_KEY_CONFLICT","DAILY_LIMIT_EXCEEDED","READ_ONLY_KEY","OAUTH_WRITE_NOT_GRANTED","TOOL_REMOVED","INTERNAL_ERROR"],"description":"Stable machine-readable code from the closed catalog. Present on every refusal a route produces; absent on `401`, the no-plan `403`, the `403` for a key without `read`, and the `429` for the request budget.","uniqueKey":"error_code","typeLabel":"enum\u003cstring>"},"request_id":{"type":"string","format":"uuid","description":"Present on a `500` (`INTERNAL_ERROR`). The same id is in Allocait's logs next to the real cause; quote it when you report the failure.","uniqueKey":"request_id","typeLabel":"string\u003cuuid>"},"issues":{"type":"array","items":{"oneOf":[{"type":"object","description":"One problem or note found while reading rules text. A file\ncarrying any `error`-level issue is never applied; `POST\n/scenarios/{id}/rules` 400s with `error_code: RULES_INVALID` and\nthe full `issues` list instead. A file with only `warning`-level\nissues still applies; those ride along on the 200 response.\n","required":["level","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.level","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.message","typeLabel":"string"},"class":{"type":"string","description":"The asset class name this issue is about, when it is about one class rather than the whole file.","uniqueKey":"issues.items.[INDEX].oneOf.0.class","typeLabel":"string"}},"uniqueKey":"issues.items.[INDEX].oneOf.0","typeLabel":"object"},{"type":"object","description":"One thing the file's text got wrong (`error`) or one note about it (`warning`, such as a web address in a description).","required":["level","where","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.level","typeLabel":"enum\u003cstring>"},"where":{"oneOf":[{"type":"string","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.0","typeLabel":"string"},{"type":"null","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where","typeLabel":"string | null"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.message","typeLabel":"string"},"line":{"type":"integer","description":"The line of the file the issue is on, when it is known.","uniqueKey":"issues.items.[INDEX].oneOf.1.line","typeLabel":"integer"}},"uniqueKey":"issues.items.[INDEX].oneOf.1","typeLabel":"object"}],"uniqueKey":"issues.items.[INDEX]","typeLabel":"object"},"description":"Every error and warning found while reading the rules text, when error_code is RULES_INVALID. From the setup routes (`POST /setup/preview`, `POST /setup/apply`) it is `SetupIssue` rows, on INVALID_INPUT.","uniqueKey":"issues","typeLabel":"object[]"},"later_receipt_id":{"type":"string","format":"uuid","description":"The newer import of the same setup file that blocks this undo. Present on IN_USE from `POST /setup/receipts/{id}/undo`; undo that receipt first.","uniqueKey":"later_receipt_id","typeLabel":"string\u003cuuid>"},"limit_type":{"type":"string","description":"Which cap was hit, e.g. \"portfolios\", \"scenarios\", \"webhook_endpoints\", \"watchlists\", \"asset_classes\", \"input_entries\" or \"input_entries_per_input\". Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"limit_type","typeLabel":"string"},"current_count":{"type":"number","description":"How many of limit_type the caller has right now. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"current_count","typeLabel":"number"},"max_allowed":{"type":"number","description":"The cap for limit_type on this account. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"max_allowed","typeLabel":"number"},"existing_id":{"type":"string","format":"uuid","description":"The record that already has this name. Present only when error_code is ALREADY_EXISTS; change it with that id instead of creating another.","uniqueKey":"existing_id","typeLabel":"string\u003cuuid>"},"duplicate_ids":{"type":"array","items":{"type":"string","format":"uuid","uniqueKey":"duplicate_ids.items.[INDEX]","typeLabel":"string\u003cuuid>"},"description":"Other records with the same name, created before duplicates were refused. Present only on ALREADY_EXISTS, and only when such records exist.","uniqueKey":"duplicate_ids","typeLabel":"string\u003cuuid>[]"},"would_remove":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","uniqueKey":"would_remove.additionalProperties.items.[INDEX]","typeLabel":"string"},"uniqueKey":"would_remove.additionalProperties","typeLabel":"string[]"},"description":"What the call would drop, keyed by list field, for example the `items` that a watchlist save would remove. Present only when error_code is CONFIRMATION_REQUIRED; resend with those members in `remove`.","uniqueKey":"would_remove","typeLabel":"object"},"valid_values":{"type":"array","items":{"type":"string","uniqueKey":"valid_values.items.[INDEX]","typeLabel":"string"},"description":"The names or options the field accepts. Present on NOT_FOUND for a name, and on INVALID_INPUT for a CHOICE value.","uniqueKey":"valid_values","typeLabel":"string[]"},"input_id":{"type":"string","format":"uuid","description":"The level input that is not a NUMBER, DECIMAL or PERCENTAGE input. Present on INVALID_INPUT from a monitor create or update (`POST /monitors`, `PATCH /monitors/{id}`, MCP `save_monitor`); point the monitor at a number-type input instead.","uniqueKey":"input_id","typeLabel":"string\u003cuuid>"},"short_count":{"type":"integer","description":"How many shorts the portfolio holds. Present on IN_USE from `PATCH /portfolios/{id}` (MCP `save_portfolio`) that turns Allow shorts off while a short is held; close them first.","uniqueKey":"short_count","typeLabel":"integer"},"symbols":{"type":"array","items":{"type":"string","uniqueKey":"symbols.items.[INDEX]","typeLabel":"string"},"description":"Holdings the call names. On IN_USE from `PATCH /portfolios/{id}`, the shorts still held (up to 20, by symbol). On INVALID_INPUT from the holdings writes, the holdings whose negative `shares` was refused (Allow shorts is off, or the holding is in Options), or whose `moves` other than 1 was refused (the holding is in Options). On WOULD_CLOSE_POSITIONS (MCP only), the holdings a full list left out.","uniqueKey":"symbols","typeLabel":"string[]"},"monitors":{"type":"array","description":"The monitors that use this input as a level. Present on IN_USE from an input update (`PATCH /inputs/{id}`, MCP `save_input`) that would change `data_type` to TEXT or CHOICE; move those monitors to another input first.","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"name":{"type":"string","uniqueKey":"monitors.items.[INDEX].name","typeLabel":"string"},"portfolio_id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].portfolio_id","typeLabel":"string\u003cuuid>"}},"uniqueKey":"monitors.items.[INDEX]","typeLabel":"object"},"uniqueKey":"monitors","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"}}},"exampleType":"generated"}},"exampleType":"generated"},"1cb8dd63-8c6e-4722-984b-4a91ad844c4f":{"description":"An unknown class or scenario (`NOT_FOUND`, with the valid names in `valid_values`)","content":{"application/json":{"schema":{"type":"object","description":"Uniform error envelope returned by every non-2xx response. `error` is\na human-readable message, safe to show the user. A refusal also\ncarries `error_code`, a stable string from the catalog in the info\nblock's Error codes section, to branch on; the HTTP status follows\nthe code (ADR-134). Only `401`, the no-plan `403`, the `403` for a\nkey without `read` and the `429` for the request budget have none.\nA `500` carries `request_id`. Extra fields by code:\nTIER_LIMIT_EXCEEDED carries `limit_type`, `current_count` and\n`max_allowed`, so a caller can branch on how many it has versus the\ncap without a second call. Its `error` text names no plan. It covers\nthe portfolio and scenario limits and the account caps: 20 webhook endpoints, 50\nwatchlists, 200 symbols on one watchlist and 50 custom symbols on one\nmonitor. Don't retry it. RULES_INVALID (`POST\n/scenarios/{id}/rules`) carries `issues`. ALREADY_EXISTS carries\n`existing_id`, plus `duplicate_ids` where older duplicates exist.\nCONFIRMATION_REQUIRED carries `would_remove`; from `POST /setup/apply` it\ncarries a fresh preview instead (`digest`, `file`, `items` and the rest of\n`SetupPreview`). INVALID_INPUT from the setup routes carries `issues`, and\nIN_USE from `POST /setup/receipts/{id}/undo` carries `later_receipt_id`.\nNOT_FOUND on a name, and\nINVALID_INPUT on a CHOICE value, carry `valid_values`. INVALID_INPUT on a\nmonitor whose level input is not a number type carries `input_id`.\nIN_USE on an input whose type would change while a monitor uses it\ncarries `monitors`. IN_USE on `PATCH /portfolios/{id}` that turns\nAllow shorts off while a short is held carries `short_count` and\n`symbols`. INVALID_INPUT on the holdings writes (`POST\n/positions/{symbol}`, `POST /portfolios/{id}/positions/apply`) that\nrefuses a negative `shares`, a `moves` other than 1 on an Options\nholding, or a `mark` on a holding outside the Options class, carries\n`symbols`, the holdings it refused. (`symbols` also appears on `WOULD_CLOSE_POSITIONS`, MCP\nonly, where it lists the holdings a full list left out.)\n","required":["error"],"example":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"},"properties":{"error":{"type":"string","description":"Human-readable error message.","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"error_code":{"type":"string","enum":["INVALID_INPUT","NOT_FOUND","ALREADY_EXISTS","IN_USE","CONFIRMATION_REQUIRED","PRICES_INCOMPLETE","PRICES_INVALID","WOULD_CLOSE_POSITIONS","INSUFFICIENT_CASH","RULES_INVALID","TARGET_OUT_OF_BAND","TIER_LIMIT_EXCEEDED","FEATURE_NOT_AVAILABLE","IDEMPOTENCY_KEY_CONFLICT","DAILY_LIMIT_EXCEEDED","READ_ONLY_KEY","OAUTH_WRITE_NOT_GRANTED","TOOL_REMOVED","INTERNAL_ERROR"],"description":"Stable machine-readable code from the closed catalog. Present on every refusal a route produces; absent on `401`, the no-plan `403`, the `403` for a key without `read`, and the `429` for the request budget.","uniqueKey":"error_code","typeLabel":"enum\u003cstring>"},"request_id":{"type":"string","format":"uuid","description":"Present on a `500` (`INTERNAL_ERROR`). The same id is in Allocait's logs next to the real cause; quote it when you report the failure.","uniqueKey":"request_id","typeLabel":"string\u003cuuid>"},"issues":{"type":"array","items":{"oneOf":[{"type":"object","description":"One problem or note found while reading rules text. A file\ncarrying any `error`-level issue is never applied; `POST\n/scenarios/{id}/rules` 400s with `error_code: RULES_INVALID` and\nthe full `issues` list instead. A file with only `warning`-level\nissues still applies; those ride along on the 200 response.\n","required":["level","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.level","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.message","typeLabel":"string"},"class":{"type":"string","description":"The asset class name this issue is about, when it is about one class rather than the whole file.","uniqueKey":"issues.items.[INDEX].oneOf.0.class","typeLabel":"string"}},"uniqueKey":"issues.items.[INDEX].oneOf.0","typeLabel":"object"},{"type":"object","description":"One thing the file's text got wrong (`error`) or one note about it (`warning`, such as a web address in a description).","required":["level","where","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.level","typeLabel":"enum\u003cstring>"},"where":{"oneOf":[{"type":"string","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.0","typeLabel":"string"},{"type":"null","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where","typeLabel":"string | null"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.message","typeLabel":"string"},"line":{"type":"integer","description":"The line of the file the issue is on, when it is known.","uniqueKey":"issues.items.[INDEX].oneOf.1.line","typeLabel":"integer"}},"uniqueKey":"issues.items.[INDEX].oneOf.1","typeLabel":"object"}],"uniqueKey":"issues.items.[INDEX]","typeLabel":"object"},"description":"Every error and warning found while reading the rules text, when error_code is RULES_INVALID. From the setup routes (`POST /setup/preview`, `POST /setup/apply`) it is `SetupIssue` rows, on INVALID_INPUT.","uniqueKey":"issues","typeLabel":"object[]"},"later_receipt_id":{"type":"string","format":"uuid","description":"The newer import of the same setup file that blocks this undo. Present on IN_USE from `POST /setup/receipts/{id}/undo`; undo that receipt first.","uniqueKey":"later_receipt_id","typeLabel":"string\u003cuuid>"},"limit_type":{"type":"string","description":"Which cap was hit, e.g. \"portfolios\", \"scenarios\", \"webhook_endpoints\", \"watchlists\", \"asset_classes\", \"input_entries\" or \"input_entries_per_input\". Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"limit_type","typeLabel":"string"},"current_count":{"type":"number","description":"How many of limit_type the caller has right now. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"current_count","typeLabel":"number"},"max_allowed":{"type":"number","description":"The cap for limit_type on this account. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"max_allowed","typeLabel":"number"},"existing_id":{"type":"string","format":"uuid","description":"The record that already has this name. Present only when error_code is ALREADY_EXISTS; change it with that id instead of creating another.","uniqueKey":"existing_id","typeLabel":"string\u003cuuid>"},"duplicate_ids":{"type":"array","items":{"type":"string","format":"uuid","uniqueKey":"duplicate_ids.items.[INDEX]","typeLabel":"string\u003cuuid>"},"description":"Other records with the same name, created before duplicates were refused. Present only on ALREADY_EXISTS, and only when such records exist.","uniqueKey":"duplicate_ids","typeLabel":"string\u003cuuid>[]"},"would_remove":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","uniqueKey":"would_remove.additionalProperties.items.[INDEX]","typeLabel":"string"},"uniqueKey":"would_remove.additionalProperties","typeLabel":"string[]"},"description":"What the call would drop, keyed by list field, for example the `items` that a watchlist save would remove. Present only when error_code is CONFIRMATION_REQUIRED; resend with those members in `remove`.","uniqueKey":"would_remove","typeLabel":"object"},"valid_values":{"type":"array","items":{"type":"string","uniqueKey":"valid_values.items.[INDEX]","typeLabel":"string"},"description":"The names or options the field accepts. Present on NOT_FOUND for a name, and on INVALID_INPUT for a CHOICE value.","uniqueKey":"valid_values","typeLabel":"string[]"},"input_id":{"type":"string","format":"uuid","description":"The level input that is not a NUMBER, DECIMAL or PERCENTAGE input. Present on INVALID_INPUT from a monitor create or update (`POST /monitors`, `PATCH /monitors/{id}`, MCP `save_monitor`); point the monitor at a number-type input instead.","uniqueKey":"input_id","typeLabel":"string\u003cuuid>"},"short_count":{"type":"integer","description":"How many shorts the portfolio holds. Present on IN_USE from `PATCH /portfolios/{id}` (MCP `save_portfolio`) that turns Allow shorts off while a short is held; close them first.","uniqueKey":"short_count","typeLabel":"integer"},"symbols":{"type":"array","items":{"type":"string","uniqueKey":"symbols.items.[INDEX]","typeLabel":"string"},"description":"Holdings the call names. On IN_USE from `PATCH /portfolios/{id}`, the shorts still held (up to 20, by symbol). On INVALID_INPUT from the holdings writes, the holdings whose negative `shares` was refused (Allow shorts is off, or the holding is in Options), or whose `moves` other than 1 was refused (the holding is in Options). On WOULD_CLOSE_POSITIONS (MCP only), the holdings a full list left out.","uniqueKey":"symbols","typeLabel":"string[]"},"monitors":{"type":"array","description":"The monitors that use this input as a level. Present on IN_USE from an input update (`PATCH /inputs/{id}`, MCP `save_input`) that would change `data_type` to TEXT or CHOICE; move those monitors to another input first.","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"name":{"type":"string","uniqueKey":"monitors.items.[INDEX].name","typeLabel":"string"},"portfolio_id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].portfolio_id","typeLabel":"string\u003cuuid>"}},"uniqueKey":"monitors.items.[INDEX]","typeLabel":"object"},"uniqueKey":"monitors","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"}}},"exampleType":"generated"}},"exampleType":"generated"},"b2a4ee1d-c3a0-4f8e-8e6f-364394cdb951":{"description":"Rate limit exceeded: maximum 60 requests per minute per account,\nor 10,000 per UTC day (see the info block's Rate limits section).\nThe per-minute refusal carries `Retry-After: 60` and the\n`X-RateLimit-*` headers; the daily refusal carries `Retry-After`\nset to the seconds until 00:00 UTC and no `X-RateLimit-*` headers.\nNeither has an `error_code`. `POST /support-requests` and\n`POST /agent-feedback` also return `429` with `error_code:\nDAILY_LIMIT_EXCEEDED` past 20 filed per rolling 24 hours; that one\ncarries the `X-RateLimit-*` headers and no `Retry-After`.\n","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Sent only on the request budget's own `429`s, never on a per-route cap (`DAILY_LIMIT_EXCEEDED`) or any other status.","schema":{"type":"integer","example":60}},"X-RateLimit-Limit":{"description":"The per-minute request budget, always `60`. Sent on every response that reaches a route and on the per-minute `429`.","schema":{"type":"integer","example":60}},"X-RateLimit-Remaining":{"description":"Requests left in the current one-minute window, after this one. The daily count is not reported until it is reached.","schema":{"type":"integer","example":41}}},"content":{"application/json":{"schema":{"type":"object","description":"Uniform error envelope returned by every non-2xx response. `error` is\na human-readable message, safe to show the user. A refusal also\ncarries `error_code`, a stable string from the catalog in the info\nblock's Error codes section, to branch on; the HTTP status follows\nthe code (ADR-134). Only `401`, the no-plan `403`, the `403` for a\nkey without `read` and the `429` for the request budget have none.\nA `500` carries `request_id`. Extra fields by code:\nTIER_LIMIT_EXCEEDED carries `limit_type`, `current_count` and\n`max_allowed`, so a caller can branch on how many it has versus the\ncap without a second call. Its `error` text names no plan. It covers\nthe portfolio and scenario limits and the account caps: 20 webhook endpoints, 50\nwatchlists, 200 symbols on one watchlist and 50 custom symbols on one\nmonitor. Don't retry it. RULES_INVALID (`POST\n/scenarios/{id}/rules`) carries `issues`. ALREADY_EXISTS carries\n`existing_id`, plus `duplicate_ids` where older duplicates exist.\nCONFIRMATION_REQUIRED carries `would_remove`; from `POST /setup/apply` it\ncarries a fresh preview instead (`digest`, `file`, `items` and the rest of\n`SetupPreview`). INVALID_INPUT from the setup routes carries `issues`, and\nIN_USE from `POST /setup/receipts/{id}/undo` carries `later_receipt_id`.\nNOT_FOUND on a name, and\nINVALID_INPUT on a CHOICE value, carry `valid_values`. INVALID_INPUT on a\nmonitor whose level input is not a number type carries `input_id`.\nIN_USE on an input whose type would change while a monitor uses it\ncarries `monitors`. IN_USE on `PATCH /portfolios/{id}` that turns\nAllow shorts off while a short is held carries `short_count` and\n`symbols`. INVALID_INPUT on the holdings writes (`POST\n/positions/{symbol}`, `POST /portfolios/{id}/positions/apply`) that\nrefuses a negative `shares`, a `moves` other than 1 on an Options\nholding, or a `mark` on a holding outside the Options class, carries\n`symbols`, the holdings it refused. (`symbols` also appears on `WOULD_CLOSE_POSITIONS`, MCP\nonly, where it lists the holdings a full list left out.)\n","required":["error"],"example":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"},"properties":{"error":{"type":"string","description":"Human-readable error message.","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"error_code":{"type":"string","enum":["INVALID_INPUT","NOT_FOUND","ALREADY_EXISTS","IN_USE","CONFIRMATION_REQUIRED","PRICES_INCOMPLETE","PRICES_INVALID","WOULD_CLOSE_POSITIONS","INSUFFICIENT_CASH","RULES_INVALID","TARGET_OUT_OF_BAND","TIER_LIMIT_EXCEEDED","FEATURE_NOT_AVAILABLE","IDEMPOTENCY_KEY_CONFLICT","DAILY_LIMIT_EXCEEDED","READ_ONLY_KEY","OAUTH_WRITE_NOT_GRANTED","TOOL_REMOVED","INTERNAL_ERROR"],"description":"Stable machine-readable code from the closed catalog. Present on every refusal a route produces; absent on `401`, the no-plan `403`, the `403` for a key without `read`, and the `429` for the request budget.","uniqueKey":"error_code","typeLabel":"enum\u003cstring>"},"request_id":{"type":"string","format":"uuid","description":"Present on a `500` (`INTERNAL_ERROR`). The same id is in Allocait's logs next to the real cause; quote it when you report the failure.","uniqueKey":"request_id","typeLabel":"string\u003cuuid>"},"issues":{"type":"array","items":{"oneOf":[{"type":"object","description":"One problem or note found while reading rules text. A file\ncarrying any `error`-level issue is never applied; `POST\n/scenarios/{id}/rules` 400s with `error_code: RULES_INVALID` and\nthe full `issues` list instead. A file with only `warning`-level\nissues still applies; those ride along on the 200 response.\n","required":["level","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.level","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.message","typeLabel":"string"},"class":{"type":"string","description":"The asset class name this issue is about, when it is about one class rather than the whole file.","uniqueKey":"issues.items.[INDEX].oneOf.0.class","typeLabel":"string"}},"uniqueKey":"issues.items.[INDEX].oneOf.0","typeLabel":"object"},{"type":"object","description":"One thing the file's text got wrong (`error`) or one note about it (`warning`, such as a web address in a description).","required":["level","where","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.level","typeLabel":"enum\u003cstring>"},"where":{"oneOf":[{"type":"string","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.0","typeLabel":"string"},{"type":"null","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where","typeLabel":"string | null"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.message","typeLabel":"string"},"line":{"type":"integer","description":"The line of the file the issue is on, when it is known.","uniqueKey":"issues.items.[INDEX].oneOf.1.line","typeLabel":"integer"}},"uniqueKey":"issues.items.[INDEX].oneOf.1","typeLabel":"object"}],"uniqueKey":"issues.items.[INDEX]","typeLabel":"object"},"description":"Every error and warning found while reading the rules text, when error_code is RULES_INVALID. From the setup routes (`POST /setup/preview`, `POST /setup/apply`) it is `SetupIssue` rows, on INVALID_INPUT.","uniqueKey":"issues","typeLabel":"object[]"},"later_receipt_id":{"type":"string","format":"uuid","description":"The newer import of the same setup file that blocks this undo. Present on IN_USE from `POST /setup/receipts/{id}/undo`; undo that receipt first.","uniqueKey":"later_receipt_id","typeLabel":"string\u003cuuid>"},"limit_type":{"type":"string","description":"Which cap was hit, e.g. \"portfolios\", \"scenarios\", \"webhook_endpoints\", \"watchlists\", \"asset_classes\", \"input_entries\" or \"input_entries_per_input\". Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"limit_type","typeLabel":"string"},"current_count":{"type":"number","description":"How many of limit_type the caller has right now. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"current_count","typeLabel":"number"},"max_allowed":{"type":"number","description":"The cap for limit_type on this account. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"max_allowed","typeLabel":"number"},"existing_id":{"type":"string","format":"uuid","description":"The record that already has this name. Present only when error_code is ALREADY_EXISTS; change it with that id instead of creating another.","uniqueKey":"existing_id","typeLabel":"string\u003cuuid>"},"duplicate_ids":{"type":"array","items":{"type":"string","format":"uuid","uniqueKey":"duplicate_ids.items.[INDEX]","typeLabel":"string\u003cuuid>"},"description":"Other records with the same name, created before duplicates were refused. Present only on ALREADY_EXISTS, and only when such records exist.","uniqueKey":"duplicate_ids","typeLabel":"string\u003cuuid>[]"},"would_remove":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","uniqueKey":"would_remove.additionalProperties.items.[INDEX]","typeLabel":"string"},"uniqueKey":"would_remove.additionalProperties","typeLabel":"string[]"},"description":"What the call would drop, keyed by list field, for example the `items` that a watchlist save would remove. Present only when error_code is CONFIRMATION_REQUIRED; resend with those members in `remove`.","uniqueKey":"would_remove","typeLabel":"object"},"valid_values":{"type":"array","items":{"type":"string","uniqueKey":"valid_values.items.[INDEX]","typeLabel":"string"},"description":"The names or options the field accepts. Present on NOT_FOUND for a name, and on INVALID_INPUT for a CHOICE value.","uniqueKey":"valid_values","typeLabel":"string[]"},"input_id":{"type":"string","format":"uuid","description":"The level input that is not a NUMBER, DECIMAL or PERCENTAGE input. Present on INVALID_INPUT from a monitor create or update (`POST /monitors`, `PATCH /monitors/{id}`, MCP `save_monitor`); point the monitor at a number-type input instead.","uniqueKey":"input_id","typeLabel":"string\u003cuuid>"},"short_count":{"type":"integer","description":"How many shorts the portfolio holds. Present on IN_USE from `PATCH /portfolios/{id}` (MCP `save_portfolio`) that turns Allow shorts off while a short is held; close them first.","uniqueKey":"short_count","typeLabel":"integer"},"symbols":{"type":"array","items":{"type":"string","uniqueKey":"symbols.items.[INDEX]","typeLabel":"string"},"description":"Holdings the call names. On IN_USE from `PATCH /portfolios/{id}`, the shorts still held (up to 20, by symbol). On INVALID_INPUT from the holdings writes, the holdings whose negative `shares` was refused (Allow shorts is off, or the holding is in Options), or whose `moves` other than 1 was refused (the holding is in Options). On WOULD_CLOSE_POSITIONS (MCP only), the holdings a full list left out.","uniqueKey":"symbols","typeLabel":"string[]"},"monitors":{"type":"array","description":"The monitors that use this input as a level. Present on IN_USE from an input update (`PATCH /inputs/{id}`, MCP `save_input`) that would change `data_type` to TEXT or CHOICE; move those monitors to another input first.","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"name":{"type":"string","uniqueKey":"monitors.items.[INDEX].name","typeLabel":"string"},"portfolio_id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].portfolio_id","typeLabel":"string\u003cuuid>"}},"uniqueKey":"monitors.items.[INDEX]","typeLabel":"object"},"uniqueKey":"monitors","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"}}},"exampleType":"generated"}},"exampleType":"generated"},"eea7446e-29a4-4a8e-a2e0-5c94410cb043":{"description":"Unexpected server error. `error_code` is `INTERNAL_ERROR` and\n`request_id` names this failure: quote it in `POST /agent-feedback`.\nThe body never carries a schema, column or constraint name.\n","content":{"application/json":{"schema":{"type":"object","description":"Uniform error envelope returned by every non-2xx response. `error` is\na human-readable message, safe to show the user. A refusal also\ncarries `error_code`, a stable string from the catalog in the info\nblock's Error codes section, to branch on; the HTTP status follows\nthe code (ADR-134). Only `401`, the no-plan `403`, the `403` for a\nkey without `read` and the `429` for the request budget have none.\nA `500` carries `request_id`. Extra fields by code:\nTIER_LIMIT_EXCEEDED carries `limit_type`, `current_count` and\n`max_allowed`, so a caller can branch on how many it has versus the\ncap without a second call. Its `error` text names no plan. It covers\nthe portfolio and scenario limits and the account caps: 20 webhook endpoints, 50\nwatchlists, 200 symbols on one watchlist and 50 custom symbols on one\nmonitor. Don't retry it. RULES_INVALID (`POST\n/scenarios/{id}/rules`) carries `issues`. ALREADY_EXISTS carries\n`existing_id`, plus `duplicate_ids` where older duplicates exist.\nCONFIRMATION_REQUIRED carries `would_remove`; from `POST /setup/apply` it\ncarries a fresh preview instead (`digest`, `file`, `items` and the rest of\n`SetupPreview`). INVALID_INPUT from the setup routes carries `issues`, and\nIN_USE from `POST /setup/receipts/{id}/undo` carries `later_receipt_id`.\nNOT_FOUND on a name, and\nINVALID_INPUT on a CHOICE value, carry `valid_values`. INVALID_INPUT on a\nmonitor whose level input is not a number type carries `input_id`.\nIN_USE on an input whose type would change while a monitor uses it\ncarries `monitors`. IN_USE on `PATCH /portfolios/{id}` that turns\nAllow shorts off while a short is held carries `short_count` and\n`symbols`. INVALID_INPUT on the holdings writes (`POST\n/positions/{symbol}`, `POST /portfolios/{id}/positions/apply`) that\nrefuses a negative `shares`, a `moves` other than 1 on an Options\nholding, or a `mark` on a holding outside the Options class, carries\n`symbols`, the holdings it refused. (`symbols` also appears on `WOULD_CLOSE_POSITIONS`, MCP\nonly, where it lists the holdings a full list left out.)\n","required":["error"],"example":{"error":"Portfolio not found or access denied","error_code":"NOT_FOUND"},"properties":{"error":{"type":"string","description":"Human-readable error message.","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"error_code":{"type":"string","enum":["INVALID_INPUT","NOT_FOUND","ALREADY_EXISTS","IN_USE","CONFIRMATION_REQUIRED","PRICES_INCOMPLETE","PRICES_INVALID","WOULD_CLOSE_POSITIONS","INSUFFICIENT_CASH","RULES_INVALID","TARGET_OUT_OF_BAND","TIER_LIMIT_EXCEEDED","FEATURE_NOT_AVAILABLE","IDEMPOTENCY_KEY_CONFLICT","DAILY_LIMIT_EXCEEDED","READ_ONLY_KEY","OAUTH_WRITE_NOT_GRANTED","TOOL_REMOVED","INTERNAL_ERROR"],"description":"Stable machine-readable code from the closed catalog. Present on every refusal a route produces; absent on `401`, the no-plan `403`, the `403` for a key without `read`, and the `429` for the request budget.","uniqueKey":"error_code","typeLabel":"enum\u003cstring>"},"request_id":{"type":"string","format":"uuid","description":"Present on a `500` (`INTERNAL_ERROR`). The same id is in Allocait's logs next to the real cause; quote it when you report the failure.","uniqueKey":"request_id","typeLabel":"string\u003cuuid>"},"issues":{"type":"array","items":{"oneOf":[{"type":"object","description":"One problem or note found while reading rules text. A file\ncarrying any `error`-level issue is never applied; `POST\n/scenarios/{id}/rules` 400s with `error_code: RULES_INVALID` and\nthe full `issues` list instead. A file with only `warning`-level\nissues still applies; those ride along on the 200 response.\n","required":["level","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.level","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.0.message","typeLabel":"string"},"class":{"type":"string","description":"The asset class name this issue is about, when it is about one class rather than the whole file.","uniqueKey":"issues.items.[INDEX].oneOf.0.class","typeLabel":"string"}},"uniqueKey":"issues.items.[INDEX].oneOf.0","typeLabel":"object"},{"type":"object","description":"One thing the file's text got wrong (`error`) or one note about it (`warning`, such as a web address in a description).","required":["level","where","message"],"properties":{"level":{"type":"string","enum":["error","warning"],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.level","typeLabel":"enum\u003cstring>"},"where":{"oneOf":[{"type":"string","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.0","typeLabel":"string"},{"type":"null","description":"Where in the file, or null for the file as a whole.","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.where","typeLabel":"string | null"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].oneOf.1.message","typeLabel":"string"},"line":{"type":"integer","description":"The line of the file the issue is on, when it is known.","uniqueKey":"issues.items.[INDEX].oneOf.1.line","typeLabel":"integer"}},"uniqueKey":"issues.items.[INDEX].oneOf.1","typeLabel":"object"}],"uniqueKey":"issues.items.[INDEX]","typeLabel":"object"},"description":"Every error and warning found while reading the rules text, when error_code is RULES_INVALID. From the setup routes (`POST /setup/preview`, `POST /setup/apply`) it is `SetupIssue` rows, on INVALID_INPUT.","uniqueKey":"issues","typeLabel":"object[]"},"later_receipt_id":{"type":"string","format":"uuid","description":"The newer import of the same setup file that blocks this undo. Present on IN_USE from `POST /setup/receipts/{id}/undo`; undo that receipt first.","uniqueKey":"later_receipt_id","typeLabel":"string\u003cuuid>"},"limit_type":{"type":"string","description":"Which cap was hit, e.g. \"portfolios\", \"scenarios\", \"webhook_endpoints\", \"watchlists\", \"asset_classes\", \"input_entries\" or \"input_entries_per_input\". Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"limit_type","typeLabel":"string"},"current_count":{"type":"number","description":"How many of limit_type the caller has right now. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"current_count","typeLabel":"number"},"max_allowed":{"type":"number","description":"The cap for limit_type on this account. Present only when error_code is TIER_LIMIT_EXCEEDED.","uniqueKey":"max_allowed","typeLabel":"number"},"existing_id":{"type":"string","format":"uuid","description":"The record that already has this name. Present only when error_code is ALREADY_EXISTS; change it with that id instead of creating another.","uniqueKey":"existing_id","typeLabel":"string\u003cuuid>"},"duplicate_ids":{"type":"array","items":{"type":"string","format":"uuid","uniqueKey":"duplicate_ids.items.[INDEX]","typeLabel":"string\u003cuuid>"},"description":"Other records with the same name, created before duplicates were refused. Present only on ALREADY_EXISTS, and only when such records exist.","uniqueKey":"duplicate_ids","typeLabel":"string\u003cuuid>[]"},"would_remove":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string","uniqueKey":"would_remove.additionalProperties.items.[INDEX]","typeLabel":"string"},"uniqueKey":"would_remove.additionalProperties","typeLabel":"string[]"},"description":"What the call would drop, keyed by list field, for example the `items` that a watchlist save would remove. Present only when error_code is CONFIRMATION_REQUIRED; resend with those members in `remove`.","uniqueKey":"would_remove","typeLabel":"object"},"valid_values":{"type":"array","items":{"type":"string","uniqueKey":"valid_values.items.[INDEX]","typeLabel":"string"},"description":"The names or options the field accepts. Present on NOT_FOUND for a name, and on INVALID_INPUT for a CHOICE value.","uniqueKey":"valid_values","typeLabel":"string[]"},"input_id":{"type":"string","format":"uuid","description":"The level input that is not a NUMBER, DECIMAL or PERCENTAGE input. Present on INVALID_INPUT from a monitor create or update (`POST /monitors`, `PATCH /monitors/{id}`, MCP `save_monitor`); point the monitor at a number-type input instead.","uniqueKey":"input_id","typeLabel":"string\u003cuuid>"},"short_count":{"type":"integer","description":"How many shorts the portfolio holds. Present on IN_USE from `PATCH /portfolios/{id}` (MCP `save_portfolio`) that turns Allow shorts off while a short is held; close them first.","uniqueKey":"short_count","typeLabel":"integer"},"symbols":{"type":"array","items":{"type":"string","uniqueKey":"symbols.items.[INDEX]","typeLabel":"string"},"description":"Holdings the call names. On IN_USE from `PATCH /portfolios/{id}`, the shorts still held (up to 20, by symbol). On INVALID_INPUT from the holdings writes, the holdings whose negative `shares` was refused (Allow shorts is off, or the holding is in Options), or whose `moves` other than 1 was refused (the holding is in Options). On WOULD_CLOSE_POSITIONS (MCP only), the holdings a full list left out.","uniqueKey":"symbols","typeLabel":"string[]"},"monitors":{"type":"array","description":"The monitors that use this input as a level. Present on IN_USE from an input update (`PATCH /inputs/{id}`, MCP `save_input`) that would change `data_type` to TEXT or CHOICE; move those monitors to another input first.","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"name":{"type":"string","uniqueKey":"monitors.items.[INDEX].name","typeLabel":"string"},"portfolio_id":{"type":"string","format":"uuid","uniqueKey":"monitors.items.[INDEX].portfolio_id","typeLabel":"string\u003cuuid>"}},"uniqueKey":"monitors.items.[INDEX]","typeLabel":"object"},"uniqueKey":"monitors","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"example":{"error":"Internal error","error_code":"INTERNAL_ERROR","request_id":"5b1e7c52-3f4a-4d0e-9a55-2d5cbe6f0a11"},"examples":{"Example":{"title":"Example","value":{"error":"Internal error","error_code":"INTERNAL_ERROR","request_id":"5b1e7c52-3f4a-4d0e-9a55-2d5cbe6f0a11"}}},"exampleType":"examples"}},"exampleType":"examples"}},"security":{"b8533fd0-f800-40c9-8f27-5e78a8812ba7":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Raw API key shown once when created in the Allocait app (Settings > API keys). Send it verbatim in this header; the server stores and compares only its SHA-256 hash. Allocait generates every key: `alc_` followed by 64 lowercase hex characters. Keys issued before 2026-10-10 are 64 hex characters with no prefix and keep working. A key may carry an expiry (90 days or 1 year, or never). A malformed, unknown, revoked or expired key gets `401` with no further detail, and a malformed one is refused before any lookup. Keys cannot be created through this API.","scopes":[],"schemeName":"ApiKeyAuth"}}},"servers":{"13120e45-325e-41e1-99fd-a11d6f409d02":{"url":"https://allocait.app/api/v1","description":"Hosted Allocait API"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"apiKey","in":"header","name":"x-api-key","description":"Raw API key shown once when created in the Allocait app (Settings > API keys). Send it verbatim in this header; the server stores and compares only its SHA-256 hash. Allocait generates every key: `alc_` followed by 64 lowercase hex characters. Keys issued before 2026-10-10 are 64 hex characters with no prefix and keep working. A key may carry an expiry (90 days or 1 year, or never). A malformed, unknown, revoked or expired key gets `401` with no further detail, and a malformed one is refused before any lookup. Keys cannot be created through this API.","scopes":[],"schemeName":"ApiKeyAuth"},"schema":{"title":"x-api-key","type":"string","description":"Raw API key shown once when created in the Allocait app (Settings > API keys). Send it verbatim in this header; the server stores and compares only its SHA-256 hash. Allocait generates every key: `alc_` followed by 64 lowercase hex characters. Keys issued before 2026-10-10 are 64 hex characters with no prefix and keep working. A key may carry an expiry (90 days or 1 year, or never). A malformed, unknown, revoked or expired key gets `401` with no further detail, and a malformed one is refused before any lookup. Keys cannot be created through this API.","isRequired":true,"typeLabel":"string","deprecated":false},"schemeName":"ApiKeyAuth","name":"x-api-key"}],"title":"ApiKeyAuth"}]},"originalFileLocation":"openapi.yaml"},"subdomain":"allocait","siteName":"Allocait","title":"Set one asset class's rule in a scenario - Allocait","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-09T05:23:21.780Z","originalFileLocation":"api-reference/rules/set-one-asset-classs-rule-in-a-scenario.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"dark\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Changes one class\u0026#x27;s band, target, size range or short size range and keeps every other rule in the scenario. The same function backs the MCP server\u0026#x27;s save_class_rule and runs the checks the app\u0026#x27;s one-rule dialog runs. A field you leave out keeps its value. - A new rule needs a band or a size range. band_min_pct must be below band_max_pct, or both 0 for none of the class. - target_pct needs a band and must sit inside it (TARGET_OUT_OF_BAND). - The size fields are set together, or cleared together with null. The short size fields (short_size_min_pct and short_size_max_pct) work the same way. - Both band fields null, with none of the four size fields sent, removes the class\u0026#x27;s rule. With a size field they clear the band and keep the rule: the class total is no longer judged. - An unknown class name is NOT_FOUND, with the valid names in valid_values, unless create_class is true. Saves a restore point first, so POST /rules/restore-points/{id}/restore undoes it like an import. Requires the API key to have the write permission.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Allocait\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/allocait/8WDpZ9h0WNasoRjb/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/allocait/8WDpZ9h0WNasoRjb/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/allocait/8WDpZ9h0WNasoRjb/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/allocait/8WDpZ9h0WNasoRjb/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/allocait/8WDpZ9h0WNasoRjb/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/allocait/8WDpZ9h0WNasoRjb/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/allocait/8WDpZ9h0WNasoRjb/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/allocait/8WDpZ9h0WNasoRjb/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/allocait/8WDpZ9h0WNasoRjb/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Set one asset class\u0026#x27;s rule in a scenario - Allocait\">\u003cmeta data-mint-head property=\"og:description\" content=\"Changes one class\u0026#x27;s band, target, size range or short size range and keeps every other rule in the scenario. The same function backs the MCP server\u0026#x27;s save_class_rule and runs the checks the app\u0026#x27;s one-rule dialog runs. A field you leave out keeps its value. - A new rule needs a band or a size range. band_min_pct must be below band_max_pct, or both 0 for none of the class. - target_pct needs a band and must sit inside it (TARGET_OUT_OF_BAND). - The size fields are set together, or cleared together with null. The short size fields (short_size_min_pct and short_size_max_pct) work the same way. - Both band fields null, with none of the four size fields sent, removes the class\u0026#x27;s rule. With a size field they clear the band and keep the rule: the class total is no longer judged. - An unknown class name is NOT_FOUND, with the valid names in valid_values, unless create_class is true. Saves a restore point first, so POST /rules/restore-points/{id}/restore undoes it like an import. Requires the API key to have the write permission.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Allocait\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.allocait.app/api-reference/rules/set-one-asset-classs-rule-in-a-scenario\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://allocait.mintlify.site/_mintlify/api/og/v2?division=Rules\u0026amp;title=Set+one+asset+class%27s+rule+in+a+scenario\u0026amp;description=Changes+one+class%27s+band%2C+target%2C+size+range+or+short+size+range+and%0Akeeps+every+other+rule+in+the+scenario.+The+same+function+backs+the+MCP%0Aserver%27s+%60save_clas\u0026amp;theme=f4ffca4ae92cd96f3d29a15e\u0026amp;signature=f18b883086bde680bd85af7d7862a1e4afe89186ef38348ed618bf4c8de12c07\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Set one asset class\u0026#x27;s rule in a scenario - Allocait\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Changes one class\u0026#x27;s band, target, size range or short size range and keeps every other rule in the scenario. The same function backs the MCP server\u0026#x27;s save_class_rule and runs the checks the app\u0026#x27;s one-rule dialog runs. A field you leave out keeps its value. - A new rule needs a band or a size range. band_min_pct must be below band_max_pct, or both 0 for none of the class. - target_pct needs a band and must sit inside it (TARGET_OUT_OF_BAND). - The size fields are set together, or cleared together with null. The short size fields (short_size_min_pct and short_size_max_pct) work the same way. - Both band fields null, with none of the four size fields sent, removes the class\u0026#x27;s rule. With a size field they clear the band and keep the rule: the class total is no longer judged. - An unknown class name is NOT_FOUND, with the valid names in valid_values, unless create_class is true. Saves a restore point first, so POST /rules/restore-points/{id}/restore undoes it like an import. Requires the API key to have the write permission.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://allocait.mintlify.site/_mintlify/api/og/v2?division=Rules\u0026amp;title=Set+one+asset+class%27s+rule+in+a+scenario\u0026amp;description=Changes+one+class%27s+band%2C+target%2C+size+range+or+short+size+range+and%0Akeeps+every+other+rule+in+the+scenario.+The+same+function+backs+the+MCP%0Aserver%27s+%60save_clas\u0026amp;theme=f4ffca4ae92cd96f3d29a15e\u0026amp;signature=f18b883086bde680bd85af7d7862a1e4afe89186ef38348ed618bf4c8de12c07\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/allocait/8WDpZ9h0WNasoRjb/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Allocait\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0b0b0b\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.allocait.app/api-reference/rules/set-one-asset-classs-rule-in-a-scenario\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/rules/set-one-asset-classs-rule-in-a-scenario.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.allocait.app/#organization\",\"name\":\"Allocait\",\"url\":\"https://docs.allocait.app\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/allocait/N9X8GrpLUSiZAKIm/logo/light.svg?fit=max\u0026auto=format\u0026n=N9X8GrpLUSiZAKIm\u0026q=85\u0026s=37c68a7ac5dc3550d24f484060530ea6\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.allocait.app#website\",\"name\":\"Allocait\",\"url\":\"https://docs.allocait.app\",\"publisher\":{\"@id\":\"https://docs.allocait.app/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.allocait.app/api-reference/rules/set-one-asset-classs-rule-in-a-scenario#webpage\",\"url\":\"https://docs.allocait.app/api-reference/rules/set-one-asset-classs-rule-in-a-scenario\",\"name\":\"Set one asset class's rule in a scenario\",\"description\":\"Changes one class's band, target, size range or short size range and keeps every other rule in the scenario. The same function backs the MCP server's save_class_rule and runs the checks the app's one-rule dialog runs. A field you leave out keeps its value. - A new rule needs a band or a size range. band_min_pct must be below band_max_pct, or both 0 for none of the class. - target_pct needs a band and must sit inside it (TARGET_OUT_OF_BAND). - The size fields are set together, or cleared together with null. The short size fields (short_size_min_pct and short_size_max_pct) work the same way. - Both band fields null, with none of the four size fields sent, removes the class's rule. With a size field they clear the band and keep the rule: the class total is no longer judged. - An unknown class name is NOT_FOUND, with the valid names in valid_values, unless create_class is true. Saves a restore point first, so POST /rules/restore-points/{id}/restore undoes it like an import. Requires the API key to have the write permission.\",\"dateModified\":\"2026-11-09T05:23:21.780Z\",\"isPartOf\":{\"@id\":\"https://docs.allocait.app#website\"},\"breadcrumb\":{\"@id\":\"https://docs.allocait.app/api-reference/rules/set-one-asset-classs-rule-in-a-scenario#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.allocait.app/api-reference/rules/set-one-asset-classs-rule-in-a-scenario#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Endpoints\",\"item\":\"https://docs.allocait.app/api-reference/checks/check-compliance-with-your-prices\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Rules\",\"item\":\"https://docs.allocait.app/api-reference/rules/list-scenarios\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Set one asset class's rule in a scenario\",\"item\":\"https://docs.allocait.app/api-reference/rules/set-one-asset-classs-rule-in-a-scenario\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.allocait.app/api-reference/rules/set-one-asset-classs-rule-in-a-scenario#apireference\",\"headline\":\"Set one asset class's rule in a scenario\",\"name\":\"Set one asset class's rule in a scenario\",\"description\":\"Changes one class's band, target, size range or short size range and keeps every other rule in the scenario. The same function backs the MCP server's save_class_rule and runs the checks the app's one-rule dialog runs. A field you leave out keeps its value. - A new rule needs a band or a size range. band_min_pct must be below band_max_pct, or both 0 for none of the class. - target_pct needs a band and must sit inside it (TARGET_OUT_OF_BAND). - The size fields are set together, or cleared together with null. The short size fields (short_size_min_pct and short_size_max_pct) work the same way. - Both band fields null, with none of the four size fields sent, removes the class's rule. With a size field they clear the band and keep the rule: the class total is no longer judged. - An unknown class name is NOT_FOUND, with the valid names in valid_values, unless create_class is true. Saves a restore point first, so POST /rules/restore-points/{id}/restore undoes it like an import. Requires the API key to have the write permission.\",\"url\":\"https://docs.allocait.app/api-reference/rules/set-one-asset-classs-rule-in-a-scenario\",\"mainEntityOfPage\":{\"@id\":\"https://docs.allocait.app/api-reference/rules/set-one-asset-classs-rule-in-a-scenario#webpage\"},\"dateModified\":\"2026-11-09T05:23:21.780Z\",\"publisher\":{\"@id\":\"https://docs.allocait.app/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.allocait.app#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Allocait\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Allocait\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/api-reference/rules/set-one-asset-classs-rule-in-a-scenario.md","siteName":"Allocait","nav":{"global":null,"tabs":[{"tab":"Get started","pages":[{"title":"Get started","href":""}]},{"tab":"Concepts","pages":[{"title":"Concepts","href":"/concepts/allocation-bands"}]},{"tab":"Claude \u0026 MCP","pages":[{"title":"Claude \u0026 MCP","href":"/claude/overview"}]},{"tab":"ChatGPT \u0026 Codex","pages":[{"title":"ChatGPT \u0026 Codex","href":"/chatgpt/connect"}]},{"tab":"Guides","pages":[{"title":"Guides","href":"/guides/write-your-rules"}]},{"tab":"API reference","groups":[{"group":"Start","pages":[{"title":"API overview","sidebarTitle":"Overview","href":"/api/introduction"},{"title":"Endpoints by task","sidebarTitle":"By task","href":"/api/endpoints-by-task"},{"title":"API quickstart","sidebarTitle":"Quickstart","href":"/api/quickstart"},{"title":"Authentication","sidebarTitle":"Authentication","href":"/api/authentication"}]},{"group":"Conventions","pages":[{"title":"Conventions","sidebarTitle":"Conventions","href":"/api/conventions"},{"title":"Rate limits","sidebarTitle":"Rate limits","href":"/api/rate-limits"},{"title":"Idempotency","sidebarTitle":"Idempotency","href":"/api/idempotency"}]},{"group":"Errors","pages":[{"title":"API errors","sidebarTitle":"Errors","href":"/api/errors"},{"title":"Error codes","sidebarTitle":"Error codes","href":"/api/error-codes"}]},{"group":"Webhooks","pages":[{"title":"Webhook events","sidebarTitle":"Webhook events","href":"/api/webhook-events"},{"title":"Verify deliveries","sidebarTitle":"Verify deliveries","href":"/api/webhook-verification"}]},{"group":"Endpoints","pages":[{"group":"Checks","pages":[{"title":"Check compliance with your prices","deprecated":null,"version":null,"openapi":"/openapi.yaml post /compliance/check","href":"/api-reference/checks/check-compliance-with-your-prices"},{"title":"Pre-flight check of a proposed allocation plan","deprecated":null,"version":null,"openapi":"/openapi.yaml post /validate","href":"/api-reference/checks/pre-flight-check-of-a-proposed-allocation-plan"},{"title":"Check a proposed change against the rules","deprecated":null,"version":null,"openapi":"/openapi.yaml post /trades/check","href":"/api-reference/checks/check-a-proposed-change-against-the-rules"},{"title":"Preview rebalance amounts with your prices","deprecated":null,"version":null,"openapi":"/openapi.yaml post /rebalance/preview","href":"/api-reference/checks/preview-rebalance-amounts-with-your-prices"}]},{"group":"Portfolios","pages":[{"title":"Get portfolio summary","deprecated":null,"version":null,"openapi":"/openapi.yaml get /portfolio/summary","href":"/api-reference/portfolios/get-portfolio-summary"},{"title":"List portfolios","deprecated":null,"version":null,"openapi":"/openapi.yaml get /portfolios","href":"/api-reference/portfolios/list-portfolios"},{"title":"Create a portfolio with an initial cash position","deprecated":null,"version":null,"openapi":"/openapi.yaml post /portfolios","href":"/api-reference/portfolios/create-a-portfolio-with-an-initial-cash-position"},{"title":"Delete a portfolio","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /portfolios/{id}","href":"/api-reference/portfolios/delete-a-portfolio"},{"title":"Change a portfolio's name, description, active scenario or Allow shorts","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /portfolios/{id}","href":"/api-reference/portfolios/change-a-portfolios-name-description-active-scenario-or-allow-shorts"},{"title":"Get a portfolio snapshot (unpriced)","deprecated":null,"version":null,"openapi":"/openapi.yaml get /portfolio/snapshot","href":"/api-reference/portfolios/get-a-portfolio-snapshot-unpriced"},{"title":"Get a portfolio snapshot with your prices","deprecated":null,"version":null,"openapi":"/openapi.yaml post /portfolio/snapshot","href":"/api-reference/portfolios/get-a-portfolio-snapshot-with-your-prices"}]},{"group":"Holdings and cash","pages":[{"title":"List positions","deprecated":null,"version":null,"openapi":"/openapi.yaml get /positions","href":"/api-reference/holdings-and-cash/list-positions"},{"title":"Record one holding's new total shares","deprecated":null,"version":null,"openapi":"/openapi.yaml post /positions/{symbol}","href":"/api-reference/holdings-and-cash/record-one-holdings-new-total-shares"},{"title":"Calculate a target share count for a position","deprecated":null,"version":null,"openapi":"/openapi.yaml post /positions/size","href":"/api-reference/holdings-and-cash/calculate-a-target-share-count-for-a-position"},{"title":"Reconcile a portfolio's holdings to an absolute desired state","deprecated":null,"version":null,"openapi":"/openapi.yaml post /portfolios/{id}/positions/apply","href":"/api-reference/holdings-and-cash/reconcile-a-portfolios-holdings-to-an-absolute-desired-state"},{"title":"Deposit or withdraw cash from a portfolio","deprecated":null,"version":null,"openapi":"/openapi.yaml post /portfolios/{id}/cash-movements","href":"/api-reference/holdings-and-cash/deposit-or-withdraw-cash-from-a-portfolio"}]},{"group":"Watchlists","pages":[{"title":"List watchlists","deprecated":null,"version":null,"openapi":"/openapi.yaml get /watchlists","href":"/api-reference/watchlists/list-watchlists"},{"title":"Create a watchlist","deprecated":null,"version":null,"openapi":"/openapi.yaml post /watchlists","href":"/api-reference/watchlists/create-a-watchlist"},{"title":"Change a watchlist's name and symbols in one call","deprecated":null,"version":null,"openapi":"/openapi.yaml put /watchlists/{id}","href":"/api-reference/watchlists/change-a-watchlists-name-and-symbols-in-one-call"},{"title":"Delete a watchlist","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /watchlists/{id}","href":"/api-reference/watchlists/delete-a-watchlist"},{"title":"Rename a watchlist","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /watchlists/{id}","href":"/api-reference/watchlists/rename-a-watchlist"},{"title":"List items in a watchlist","deprecated":null,"version":null,"openapi":"/openapi.yaml get /watchlists/{id}/items","href":"/api-reference/watchlists/list-items-in-a-watchlist"},{"title":"Add a symbol to a watchlist","deprecated":null,"version":null,"openapi":"/openapi.yaml post /watchlists/{id}/items","href":"/api-reference/watchlists/add-a-symbol-to-a-watchlist"},{"title":"Reorder a watchlist's items","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /watchlists/{id}/items","href":"/api-reference/watchlists/reorder-a-watchlists-items"},{"title":"Remove a symbol from a watchlist","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /watchlists/{id}/items/{item_id}","href":"/api-reference/watchlists/remove-a-symbol-from-a-watchlist"}]},{"group":"Inputs","pages":[{"title":"List input (tracked-value) definitions","deprecated":null,"version":null,"openapi":"/openapi.yaml get /inputs","href":"/api-reference/inputs/list-input-tracked-value-definitions"},{"title":"Create an Input (tracked-value) definition","deprecated":null,"version":null,"openapi":"/openapi.yaml post /inputs","href":"/api-reference/inputs/create-an-input-tracked-value-definition"},{"title":"Change an Input definition and its options in one call","deprecated":null,"version":null,"openapi":"/openapi.yaml put /inputs/{id}","href":"/api-reference/inputs/change-an-input-definition-and-its-options-in-one-call"},{"title":"Delete an Input definition","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /inputs/{id}","href":"/api-reference/inputs/delete-an-input-definition"},{"title":"Update an Input definition","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /inputs/{id}","href":"/api-reference/inputs/update-an-input-definition"},{"title":"List recorded values for one input","deprecated":null,"version":null,"openapi":"/openapi.yaml get /inputs/{id}/entries","href":"/api-reference/inputs/list-recorded-values-for-one-input"},{"title":"List dropdown options for one CHOICE input","deprecated":null,"version":null,"openapi":"/openapi.yaml get /inputs/{id}/options","href":"/api-reference/inputs/list-dropdown-options-for-one-choice-input"},{"title":"Add a dropdown option","deprecated":null,"version":null,"openapi":"/openapi.yaml post /inputs/{id}/options","href":"/api-reference/inputs/add-a-dropdown-option"},{"title":"Remove a dropdown option","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /inputs/{id}/options/{option_id}","href":"/api-reference/inputs/remove-a-dropdown-option"},{"title":"Rename or reorder a dropdown option","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /inputs/{id}/options/{option_id}","href":"/api-reference/inputs/rename-or-reorder-a-dropdown-option"},{"title":"Record (upsert) one or more custom input values","deprecated":null,"version":null,"openapi":"/openapi.yaml post /inputs/entries","href":"/api-reference/inputs/record-upsert-one-or-more-custom-input-values"},{"title":"Delete one or more recorded input values","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /inputs/entries","href":"/api-reference/inputs/delete-one-or-more-recorded-input-values"}]},{"group":"Playbooks","pages":[{"title":"List playbooks","deprecated":null,"version":null,"openapi":"/openapi.yaml get /playbooks","href":"/api-reference/playbooks/list-playbooks"},{"title":"Create a playbook","deprecated":null,"version":null,"openapi":"/openapi.yaml post /playbooks","href":"/api-reference/playbooks/create-a-playbook"},{"title":"Resolve a playbook's symbols and its input values for a date","deprecated":null,"version":null,"openapi":"/openapi.yaml get /playbooks/{id}","href":"/api-reference/playbooks/resolve-a-playbooks-symbols-and-its-input-values-for-a-date"},{"title":"Delete a playbook","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /playbooks/{id}","href":"/api-reference/playbooks/delete-a-playbook"},{"title":"Update a playbook","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /playbooks/{id}","href":"/api-reference/playbooks/update-a-playbook"}]},{"group":"Monitors","pages":[{"title":"List condition monitors and their recorded levels","deprecated":null,"version":null,"openapi":"/openapi.yaml get /monitors","href":"/api-reference/monitors/list-condition-monitors-and-their-recorded-levels"},{"title":"Create a condition monitor","deprecated":null,"version":null,"openapi":"/openapi.yaml post /monitors","href":"/api-reference/monitors/create-a-condition-monitor"},{"title":"Delete a condition monitor","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /monitors/{id}","href":"/api-reference/monitors/delete-a-condition-monitor"},{"title":"Update a condition monitor","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /monitors/{id}","href":"/api-reference/monitors/update-a-condition-monitor"}]},{"group":"Rules","pages":[{"title":"List scenarios","deprecated":null,"version":null,"openapi":"/openapi.yaml get /scenarios","href":"/api-reference/rules/list-scenarios"},{"title":"Create a scenario","deprecated":null,"version":null,"openapi":"/openapi.yaml post /scenarios","href":"/api-reference/rules/create-a-scenario"},{"title":"Delete a scenario","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /scenarios/{id}","href":"/api-reference/rules/delete-a-scenario"},{"title":"Rename a scenario and/or replace its description","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /scenarios/{id}","href":"/api-reference/rules/rename-a-scenario-andor-replace-its-description"},{"title":"List asset classes","deprecated":null,"version":null,"openapi":"/openapi.yaml get /asset-classes","href":"/api-reference/rules/list-asset-classes"},{"title":"Create a custom asset class","deprecated":null,"version":null,"openapi":"/openapi.yaml post /asset-classes","href":"/api-reference/rules/create-a-custom-asset-class"},{"title":"Delete a custom asset class","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /asset-classes/{id}","href":"/api-reference/rules/delete-a-custom-asset-class"},{"title":"Rename an asset class and/or replace its description","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /asset-classes/{id}","href":"/api-reference/rules/rename-an-asset-class-andor-replace-its-description"},{"title":"List position rules (allocation band and position size per asset class)","description":"One row per asset class per scenario. Each row carries the\nallocation band on the asset class total (`min_position_pct` /\n`max_position_pct`, optional `target_allocation_pct`) that\n`/compliance/check` and `/rebalance/preview` evaluate against, and\nan optional position size range (`size_min_pct` / `size_max_pct`)\nfor one holding in that class, which `/compliance/check` and\n`/validate` check (`size_violations`) and `/positions/size` uses, and\nan optional short size range (`short_size_min_pct` /\n`short_size_max_pct`) for one short in that class, which the same\nchecks use for a short. Useful for an\nagent that wants to explain *why* a position was flagged, not just\nthat it was.\n","deprecated":null,"version":null,"openapi":"/openapi.yaml get /position-rules","href":"/api-reference/rules/list-position-rules-allocation-band-and-position-size-per-asset-class"},{"title":"Set one asset class's rule in a scenario","deprecated":null,"version":null,"openapi":"/openapi.yaml post /scenarios/{id}/position-rules","href":"/api-reference/rules/set-one-asset-classs-rule-in-a-scenario"},{"title":"Reconcile a scenario's position rules to an absolute desired state","description":"The same \"make Allocait match what I declared\" shape `/portfolios/\n{id}/positions/apply` uses, applied to the rules themselves rather\nthan the holdings (ADR-019-style agent write). Pass the FULL\ndesired set of rules for the scenario; any asset class not listed\nhas its existing rule removed.\n\nEach rule carries the allocation band on the asset class total\n(`min_position_pct` / `max_position_pct`, optional\n`target_allocation_pct`; both band fields may be left out when the\nrule carries a size range or a short size range, and then the class\ntotal is not judged) and may carry a position size range for\none holding (`size_min_pct` / `size_max_pct`, both or neither) and a\nshort size range for one short (`short_size_min_pct` /\n`short_size_max_pct`, both or neither).\n`target_allocation_pct`, when set, must satisfy `min_position_pct`\n`\u003c=` `target_allocation_pct` `\u003c=` `max_position_pct` for every rule\nin the batch or the whole call fails with `TARGET_OUT_OF_BAND` and\nnothing is written (ADR-042).\nAbsolute state applies to both size ranges too: a rule sent without\nthe size keys has its existing size range cleared, and a rule sent\nwithout the short size keys has its short size range cleared, and a\nrule sent without the band has its band cleared, so an\nagent that rebuilds its payload from the band fields alone will drop\nevery size range on re-apply. Read the rule back from `GET /position-rules`\nand send all of its fields.\n\nThis states the user's OWN threshold back to Allocait. It never\nranks, suggests, or opines on any security, and nothing here is a\nmarket call; see the note on this at the top of this document.\n\nIdempotent: calling this again with the same desired state changes\nnothing (asset classes already matching are reported under\n`unchanged`). Atomic: the whole batch is one transaction.\n\n**Requires the API key to have the `write` permission.**\n","deprecated":null,"version":null,"openapi":"/openapi.yaml post /scenarios/{id}/position-rules/apply","href":"/api-reference/rules/reconcile-a-scenarios-position-rules-to-an-absolute-desired-state"},{"title":"Get a scenario's rules as rules text","deprecated":null,"version":null,"openapi":"/openapi.yaml get /scenarios/{id}/rules","href":"/api-reference/rules/get-a-scenarios-rules-as-rules-text"},{"title":"Import rules text into a scenario's rules, or preview it with dry_run","deprecated":null,"version":null,"openapi":"/openapi.yaml post /scenarios/{id}/rules","href":"/api-reference/rules/import-rules-text-into-a-scenarios-rules-or-preview-it-with-dry_run"},{"title":"List rules restore points, newest first","deprecated":null,"version":null,"openapi":"/openapi.yaml get /rules/restore-points","href":"/api-reference/rules/list-rules-restore-points-newest-first"},{"title":"Undo an import or an earlier restore","deprecated":null,"version":null,"openapi":"/openapi.yaml post /rules/restore-points/{id}/restore","href":"/api-reference/rules/undo-an-import-or-an-earlier-restore"},{"title":"Get the rules text format spec, ready-to-import examples, and copy/paste AI prompts","deprecated":null,"version":null,"openapi":"/openapi.yaml get /rules/spec","href":"/api-reference/rules/get-the-rules-text-format-spec-ready-to-import-examples-and-copypaste-ai-prompts"}]},{"group":"Actions","pages":[{"title":"List a portfolio's actions","deprecated":null,"version":null,"openapi":"/openapi.yaml get /actions","href":"/api-reference/actions/list-a-portfolios-actions"},{"title":"Delete one or more actions","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /actions","href":"/api-reference/actions/delete-one-or-more-actions"},{"title":"Edit an action's comment","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /actions/{id}","href":"/api-reference/actions/edit-an-actions-comment"}]},{"group":"Support and feedback","pages":[{"title":"List your support requests, newest first","deprecated":null,"version":null,"openapi":"/openapi.yaml get /support-requests","href":"/api-reference/support-and-feedback/list-your-support-requests-newest-first"},{"title":"File a support request","deprecated":null,"version":null,"openapi":"/openapi.yaml post /support-requests","href":"/api-reference/support-and-feedback/file-a-support-request"},{"title":"List your agent feedback, newest first","deprecated":null,"version":null,"openapi":"/openapi.yaml get /agent-feedback","href":"/api-reference/support-and-feedback/list-your-agent-feedback-newest-first"},{"title":"Report feedback about the agent surface itself","deprecated":null,"version":null,"openapi":"/openapi.yaml post /agent-feedback","href":"/api-reference/support-and-feedback/report-feedback-about-the-agent-surface-itself"}]},{"group":"Charts","pages":[{"title":"List saved charts for a portfolio","deprecated":null,"version":null,"openapi":"/openapi.yaml get /charts","href":"/api-reference/charts/list-saved-charts-for-a-portfolio"},{"title":"Create a saved chart","deprecated":null,"version":null,"openapi":"/openapi.yaml post /charts","href":"/api-reference/charts/create-a-saved-chart"},{"title":"Delete a saved chart","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /charts/{id}","href":"/api-reference/charts/delete-a-saved-chart"},{"title":"Update a saved chart","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /charts/{id}","href":"/api-reference/charts/update-a-saved-chart"}]},{"group":"Preferences","pages":[{"title":"Get what the app opens to, and the theme","deprecated":null,"version":null,"openapi":"/openapi.yaml get /preferences","href":"/api-reference/preferences/get-what-the-app-opens-to-and-the-theme"},{"title":"Set which portfolio/watchlist/chart/playbook/monitor the app shows, or the theme","deprecated":null,"version":null,"openapi":"/openapi.yaml post /preferences","href":"/api-reference/preferences/set-which-portfoliowatchlistchartplaybookmonitor-the-app-shows-or-the-theme"}]},{"group":"Webhooks","pages":[{"title":"List webhook endpoints","deprecated":null,"version":null,"openapi":"/openapi.yaml get /webhooks","href":"/api-reference/webhooks/list-webhook-endpoints"},{"title":"Register a webhook endpoint","deprecated":null,"version":null,"openapi":"/openapi.yaml post /webhooks","href":"/api-reference/webhooks/register-a-webhook-endpoint"},{"title":"Delete a webhook endpoint","deprecated":null,"version":null,"openapi":"/openapi.yaml delete /webhooks/{id}","href":"/api-reference/webhooks/delete-a-webhook-endpoint"},{"title":"Update a webhook endpoint","deprecated":null,"version":null,"openapi":"/openapi.yaml patch /webhooks/{id}","href":"/api-reference/webhooks/update-a-webhook-endpoint"}]},{"group":"Setup file","pages":[{"title":"Export your watchlists, Inputs, playbooks, monitors and saved charts as one JSON document","deprecated":null,"version":null,"openapi":"/openapi.yaml get /setup/export","href":"/api-reference/setup-file/export-your-watchlists-inputs-playbooks-monitors-and-saved-charts-as-one-json-document"},{"title":"Preview an ALLOCAIT.md setup file","deprecated":null,"version":null,"openapi":"/openapi.yaml post /setup/preview","href":"/api-reference/setup-file/preview-an-allocaitmd-setup-file"},{"title":"Apply a previewed ALLOCAIT.md setup file","deprecated":null,"version":null,"openapi":"/openapi.yaml post /setup/apply","href":"/api-reference/setup-file/apply-a-previewed-allocaitmd-setup-file"},{"title":"List the account's setup file receipts","deprecated":null,"version":null,"openapi":"/openapi.yaml get /setup/receipts","href":"/api-reference/setup-file/list-the-accounts-setup-file-receipts"},{"title":"Undo an applied setup file, or preview the undo","deprecated":null,"version":null,"openapi":"/openapi.yaml post /setup/receipts/{id}/undo","href":"/api-reference/setup-file/undo-an-applied-setup-file-or-preview-the-undo"}]}]}]},{"tab":"Support \u0026 trust","pages":[{"title":"Support \u0026 trust","href":"/support"}]}]},"basePath":"","title":"Set one asset class's rule in a scenario - Allocait","buildId":"dpl_596ePT575z4qnAFksq1biRW97aLY","deploymentId":"dpl_596ePT575z4qnAFksq1biRW97aLY","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-C9Wu0MeN.js","utils-jWgu-6Qf.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-DBD8f9qn.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-BGuX1ui5.js","snippetPresets-Evy63nQB.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","conditional-requirements-CFM0id0Q.js","ApiExamples-BQHO1lnV.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-B6C8m-t_.js","shallow-BG4cT0fH.js","getApiPlaygroundDisplay-CgEPrE-D.js","CodeSnippet-CU8JyZ9N.js","CodeSnippets-BnxHU32T.js","Page-D6S0Yh6q.js","getPastedJson-CwiYOonh.js","icon-DYDpWmDf.js","MethodPill-C-J-l7_c.js","DuplicateIcon-B6ARwg9w.js","createIcon-Dsv4MtDq.js","DynamicMarkdown-CtasenyM.js","SectionHeading-YNcgYwjB.js","axios-vUo_bRtp.js","Markdown-CwLx6PAg.js","clsx-C3kuh_dz.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-CmKHfscc.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-U3mI6Ljh.js"]}