Re-applies the rules a restore point saved, by asset_class_id:
the same absolute-state reconciliation POST /scenarios/{id}/rules
and POST /scenarios/{id}/position-rules/apply use. A saved rule
whose class no longer exists, or is no longer this key’s to use, is
skipped and named in skipped rather than failing the whole
restore. Deletes any custom class the original import created that
nothing references any more (named in removed_classes), never a
system class, and never one that any position, watchlist item, or
another scenario’s rule still uses.
Takes a fresh restore point of the scenario’s rules right before
this restore, first, so the restore can itself be undone the same
way: restore_point_id on the response is that new point, never
the one you passed in.
Requires the API key to have the write permission.
POST
/
rules
/
restore-points
/
{id}
/
restore
Undo an import or an earlier restore
curl --request POST \ --url https://allocait.app/api/v1/rules/restore-points/{id}/restore \ --header 'x-api-key: <api-key>'
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.
The result of an import (POST /scenarios/{id}/rules) or an undo
(POST /rules/restore-points/{id}/restore); both reconcile a
scenario's rules to an absolute desired state, the same shape
POST /scenarios/{id}/position-rules/apply uses, and both save a
restore point of what the scenario's rules were immediately before,
so either one can itself be undone.
Null under dry_run: true. Otherwise the restore point saved
immediately before this write. Pass it to POST /rules/restore-points/{id}/restore to undo it.
Import only. Warnings from reading the file; POST /scenarios/{id}/rules never reaches the RPC, and never returns this field, when the file has an error-level issue.
Restore only. Custom classes the original import created that nothing references any more, deleted as part of the undo.
{"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/undo-an-import-or-an-earlier-restore","slug":"/api-reference/rules/undo-an-import-or-an-earlier-restore","pageMetadata":{"title":"Undo an import or an earlier restore","description":"Re-applies the rules a restore point saved, by `asset_class_id`:\nthe same absolute-state reconciliation `POST /scenarios/{id}/rules`\nand `POST /scenarios/{id}/position-rules/apply` use. A saved rule\nwhose class no longer exists, or is no longer this key's to use, is\nskipped and named in `skipped` rather than failing the whole\nrestore. Deletes any custom class the original import created that\nnothing references any more (named in `removed_classes`), never a\nsystem class, and never one that any position, watchlist item, or\nanother scenario's rule still uses.\n\nTakes a fresh restore point of the scenario's rules right before\nthis restore, first, so the restore can itself be undone the same\nway: `restore_point_id` on the response is that new point, never\nthe one you passed in.\n\n**Requires the API key to have the `write` permission.**\n","deprecated":null,"version":null,"openapi":"/openapi.yaml post /rules/restore-points/{id}/restore","href":"/api-reference/rules/undo-an-import-or-an-earlier-restore","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 p: \"p\",\n strong: \"strong\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsxs(_components.p, {\n children: [\"Re-applies the rules a restore point saved, by \", _jsx(_components.code, {\n children: \"asset_class_id\"\n }), \":\\nthe same absolute-state reconciliation \", _jsx(_components.code, {\n children: \"POST /scenarios/{id}/rules\"\n }), \"\\nand \", _jsx(_components.code, {\n children: \"POST /scenarios/{id}/position-rules/apply\"\n }), \" use. A saved rule\\nwhose class no longer exists, or is no longer this key’s to use, is\\nskipped and named in \", _jsx(_components.code, {\n children: \"skipped\"\n }), \" rather than failing the whole\\nrestore. Deletes any custom class the original import created that\\nnothing references any more (named in \", _jsx(_components.code, {\n children: \"removed_classes\"\n }), \"), never a\\nsystem class, and never one that any position, watchlist item, or\\nanother scenario’s rule still uses.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Takes a fresh restore point of the scenario’s rules right before\\nthis restore, first, so the restore can itself be undone the same\\nway: \", _jsx(_components.code, {\n children: \"restore_point_id\"\n }), \" on the response is that new point, never\\nthe one you passed in.\"]\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":"Undo an import or an earlier restore","description":"Re-applies the rules a restore point saved, by `asset_class_id`:\nthe same absolute-state reconciliation `POST /scenarios/{id}/rules`\nand `POST /scenarios/{id}/position-rules/apply` use. A saved rule\nwhose class no longer exists, or is no longer this key's to use, is\nskipped and named in `skipped` rather than failing the whole\nrestore. Deletes any custom class the original import created that\nnothing references any more (named in `removed_classes`), never a\nsystem class, and never one that any position, watchlist item, or\nanother scenario's rule still uses.\n\nTakes a fresh restore point of the scenario's rules right before\nthis restore, first, so the restore can itself be undone the same\nway: `restore_point_id` on the response is that new point, never\nthe one you passed in.\n\n**Requires the API key to have the `write` permission.**\n","deprecated":null,"version":null,"openapi":"/openapi.yaml post /rules/restore-points/{id}/restore","href":"/api-reference/rules/undo-an-import-or-an-earlier-restore","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"tags":["Rules"],"operationId":"restoreRulesRestorePoint","summary":"Undo an import or an earlier restore","description":"Re-applies the rules a restore point saved, by `asset_class_id`:\nthe same absolute-state reconciliation `POST /scenarios/{id}/rules`\nand `POST /scenarios/{id}/position-rules/apply` use. A saved rule\nwhose class no longer exists, or is no longer this key's to use, is\nskipped and named in `skipped` rather than failing the whole\nrestore. Deletes any custom class the original import created that\nnothing references any more (named in `removed_classes`), never a\nsystem class, and never one that any position, watchlist item, or\nanother scenario's rule still uses.\n\nTakes a fresh restore point of the scenario's rules right before\nthis restore, first, so the restore can itself be undone the same\nway: `restore_point_id` on the response is that new point, never\nthe one you passed in.\n\n**Requires the API key to have the `write` permission.**\n","security":["3aca293b-d6cc-411d-b4ff-5d123d40f3b9"],"parameters":["bf4312b4-9b48-4955-aae3-18d404000ea4"],"responses":{"200":"a9694efe-cd93-44b2-9245-c0f6f1c174e7","400":"c5773cd3-f240-4d8c-a780-5396d2a0169c","401":"1343e95a-c857-448e-b678-7dfd0d57b94a","403":"175c1e0d-a9ea-428d-87f6-3e40d35ebc4b","404":"9853d30f-67a2-4e30-bc22-53db46504e92","429":"b28beb83-cdcf-4cf9-b66e-ccb58ff3973c","500":"f6ea867e-aca2-49c9-a131-71aeca7ac7a7"},"method":"post","type":"path","servers":["13120e45-325e-41e1-99fd-a11d6f409d02"],"path":"/rules/restore-points/{id}/restore","baseUrlOptions":["https://allocait.app/api/v1"],"title":"Undo an import or an earlier restore","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"bf4312b4-9b48-4955-aae3-18d404000ea4":{"name":"id","in":"path","required":true,"description":"restore_point_id","schema":{"type":"string","format":"uuid","isRequired":true,"description":"restore_point_id","uniqueKey":"","typeLabel":"string\u003cuuid>"}}},"responses":{"a9694efe-cd93-44b2-9245-c0f6f1c174e7":{"description":"The restore point was applied","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","description":"The result of an import (`POST /scenarios/{id}/rules`) or an undo\n(`POST /rules/restore-points/{id}/restore`); both reconcile a\nscenario's rules to an absolute desired state, the same shape\n`POST /scenarios/{id}/position-rules/apply` uses, and both save a\nrestore point of what the scenario's rules were immediately before,\nso either one can itself be undone.\n","properties":{"success":{"type":"boolean","uniqueKey":"success","typeLabel":"boolean"},"dry_run":{"type":"boolean","description":"Import only. True when nothing was written. `changes` and `counts` are still the full preview.","uniqueKey":"dry_run","typeLabel":"boolean"},"scenario_id":{"type":"string","format":"uuid","uniqueKey":"scenario_id","typeLabel":"string\u003cuuid>"},"scenario_name":{"type":"string","uniqueKey":"scenario_name","typeLabel":"string"},"restore_point_id":{"oneOf":[{"type":"string","format":"uuid","description":"Null under `dry_run: true`. Otherwise the restore point saved\nimmediately before this write. Pass it to `POST\n/rules/restore-points/{id}/restore` to undo it.\n","uniqueKey":"restore_point_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","format":"uuid","description":"Null under `dry_run: true`. Otherwise the restore point saved\nimmediately before this write. Pass it to `POST\n/rules/restore-points/{id}/restore` to undo it.\n","uniqueKey":"restore_point_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"restore_point_id","typeLabel":"string\u003cuuid> | null"},"classes_to_create":{"type":"array","items":{"type":"string","uniqueKey":"classes_to_create.items.[INDEX]","typeLabel":"string"},"description":"Import only. Class names in the file that matched no existing class and will be (or, under `dry_run`, would be) created.","uniqueKey":"classes_to_create","typeLabel":"string[]"},"changes":{"type":"array","items":{"type":"object","description":"One asset class's before/after in an import or restore diff.","properties":{"name":{"type":"string","uniqueKey":"changes.items.[INDEX].name","typeLabel":"string"},"asset_class_id":{"oneOf":[{"type":"string","format":"uuid","description":"Null for an `added` change while `dry_run` is true, before the class actually exists.","uniqueKey":"changes.items.[INDEX].asset_class_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","format":"uuid","description":"Null for an `added` change while `dry_run` is true, before the class actually exists.","uniqueKey":"changes.items.[INDEX].asset_class_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"changes.items.[INDEX].asset_class_id","typeLabel":"string\u003cuuid> | null"},"change":{"type":"string","enum":["added","changed","removed","unchanged"],"uniqueKey":"changes.items.[INDEX].change","typeLabel":"enum\u003cstring>"},"before":{"oneOf":[{"type":"object","description":"The class's rule immediately before this write:\n`{target_allocation_pct, min_position_pct, max_position_pct,\nsize_min_pct, size_max_pct, short_size_min_pct,\nshort_size_max_pct}`. Null when `change` is `added`.\n","uniqueKey":"changes.items.[INDEX].before.oneOf.0","typeLabel":"object"},{"type":"null","description":"The class's rule immediately before this write:\n`{target_allocation_pct, min_position_pct, max_position_pct,\nsize_min_pct, size_max_pct, short_size_min_pct,\nshort_size_max_pct}`. Null when `change` is `added`.\n","uniqueKey":"changes.items.[INDEX].before.oneOf.1","typeLabel":"null"}],"uniqueKey":"changes.items.[INDEX].before","typeLabel":"object | null"},"after":{"oneOf":[{"type":"object","description":"The class's rule after this write, same shape as `before`. Null when `change` is `removed`.","uniqueKey":"changes.items.[INDEX].after.oneOf.0","typeLabel":"object"},{"type":"null","description":"The class's rule after this write, same shape as `before`. Null when `change` is `removed`.","uniqueKey":"changes.items.[INDEX].after.oneOf.1","typeLabel":"null"}],"uniqueKey":"changes.items.[INDEX].after","typeLabel":"object | null"},"written_as":{"oneOf":[{"type":"string","description":"The class name exactly as written in the imported file, when it\ndiffers (case-insensitively) from the resolved class's own name,\ne.g. `Stocks` resolving to the system class `Equities`. Null\nwhen the written name already matches the resolved class, and\nalways null for a `removed` change and throughout `POST\n/rules/restore-points/{id}/restore` (a restore re-applies by\n`asset_class_id`, not by name, so nothing is re-resolved).\n","uniqueKey":"changes.items.[INDEX].written_as.oneOf.0","typeLabel":"string"},{"type":"null","description":"The class name exactly as written in the imported file, when it\ndiffers (case-insensitively) from the resolved class's own name,\ne.g. `Stocks` resolving to the system class `Equities`. Null\nwhen the written name already matches the resolved class, and\nalways null for a `removed` change and throughout `POST\n/rules/restore-points/{id}/restore` (a restore re-applies by\n`asset_class_id`, not by name, so nothing is re-resolved).\n","uniqueKey":"changes.items.[INDEX].written_as.oneOf.1","typeLabel":"null"}],"uniqueKey":"changes.items.[INDEX].written_as","typeLabel":"string | null"}},"uniqueKey":"changes.items.[INDEX]","typeLabel":"object"},"description":"Ordered by file (or saved-snapshot) order for added/changed/unchanged, then by class display order for removed.","uniqueKey":"changes","typeLabel":"object[]"},"counts":{"type":"object","properties":{"added":{"type":"integer","uniqueKey":"counts.added","typeLabel":"integer"},"changed":{"type":"integer","uniqueKey":"counts.changed","typeLabel":"integer"},"removed":{"type":"integer","uniqueKey":"counts.removed","typeLabel":"integer"},"unchanged":{"type":"integer","uniqueKey":"counts.unchanged","typeLabel":"integer"}},"uniqueKey":"counts","typeLabel":"object"},"issues":{"type":"array","items":{"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].level","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"issues.items.[INDEX].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].class","typeLabel":"string"}},"uniqueKey":"issues.items.[INDEX]","typeLabel":"object"},"description":"Import only. Warnings from reading the file; `POST /scenarios/{id}/rules` never reaches the RPC, and never returns this field, when the file has an error-level issue.","uniqueKey":"issues","typeLabel":"object[]"},"skipped":{"type":"array","items":{"type":"string","uniqueKey":"skipped.items.[INDEX]","typeLabel":"string"},"description":"Restore only. Class names the saved rule pointed at that no longer exist or are no longer this key's to use. Restoring wrote nothing for these.","uniqueKey":"skipped","typeLabel":"string[]"},"removed_classes":{"type":"array","items":{"type":"string","uniqueKey":"removed_classes.items.[INDEX]","typeLabel":"string"},"description":"Restore only. Custom classes the original import created that nothing references any more, deleted as part of the undo.","uniqueKey":"removed_classes","typeLabel":"string[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"success":true,"dry_run":true,"scenario_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","scenario_name":"\u003cstring>","restore_point_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","classes_to_create":["\u003cstring>"],"changes":[{"name":"\u003cstring>","asset_class_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","change":"added","before":{},"after":{},"written_as":"\u003cstring>"}],"counts":{"added":123,"changed":123,"removed":123,"unchanged":123},"issues":[{"level":"error","message":"\u003cstring>","class":"\u003cstring>"}],"skipped":["\u003cstring>"],"removed_classes":["\u003cstring>"]}}},"exampleType":"generated"}},"exampleType":"generated"},"c5773cd3-f240-4d8c-a780-5396d2a0169c":{"description":"The id in the path is not a UUID","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"},"1343e95a-c857-448e-b678-7dfd0d57b94a":{"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"},"175c1e0d-a9ea-428d-87f6-3e40d35ebc4b":{"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"},"9853d30f-67a2-4e30-bc22-53db46504e92":{"description":"Restore point not found, or not yours (`NOT_FOUND`)","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"},"b28beb83-cdcf-4cf9-b66e-ccb58ff3973c":{"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"},"f6ea867e-aca2-49c9-a131-71aeca7ac7a7":{"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":{"3aca293b-d6cc-411d-b4ff-5d123d40f3b9":{"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":"Undo an import or an earlier restore - Allocait","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-09T05:23:22.083Z","originalFileLocation":"api-reference/rules/undo-an-import-or-an-earlier-restore.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=\"Re-applies the rules a restore point saved, by asset_class_id: the same absolute-state reconciliation POST /scenarios/{id}/rules and POST /scenarios/{id}/position-rules/apply use. A saved rule whose class no longer exists, or is no longer this key\u0026#x27;s to use, is skipped and named in skipped rather than failing the whole restore. Deletes any custom class the original import created that nothing references any more (named in removed_classes), never a system class, and never one that any position, watchlist item, or another scenario\u0026#x27;s rule still uses. Takes a fresh restore point of the scenario\u0026#x27;s rules right before this restore, first, so the restore can itself be undone the same way: restore_point_id on the response is that new point, never the one you passed in. 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=\"Undo an import or an earlier restore - Allocait\">\u003cmeta data-mint-head property=\"og:description\" content=\"Re-applies the rules a restore point saved, by asset_class_id: the same absolute-state reconciliation POST /scenarios/{id}/rules and POST /scenarios/{id}/position-rules/apply use. A saved rule whose class no longer exists, or is no longer this key\u0026#x27;s to use, is skipped and named in skipped rather than failing the whole restore. Deletes any custom class the original import created that nothing references any more (named in removed_classes), never a system class, and never one that any position, watchlist item, or another scenario\u0026#x27;s rule still uses. Takes a fresh restore point of the scenario\u0026#x27;s rules right before this restore, first, so the restore can itself be undone the same way: restore_point_id on the response is that new point, never the one you passed in. 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/undo-an-import-or-an-earlier-restore\">\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=Undo+an+import+or+an+earlier+restore\u0026amp;description=Re-applies+the+rules+a+restore+point+saved%2C+by+%60asset_class_id%60%3A%0Athe+same+absolute-state+reconciliation+%60POST+%2Fscenarios%2F%7Bid%7D%2Frules%60%0Aand+%60POST+%2Fscenarios%2F%7Bid%7D%2Fp\u0026amp;theme=f4ffca4ae92cd96f3d29a15e\u0026amp;signature=8ae7b0c1310e399a0deefaf12da845c11299fbdee728e8f22143254e2aa40baa\">\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=\"Undo an import or an earlier restore - Allocait\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Re-applies the rules a restore point saved, by asset_class_id: the same absolute-state reconciliation POST /scenarios/{id}/rules and POST /scenarios/{id}/position-rules/apply use. A saved rule whose class no longer exists, or is no longer this key\u0026#x27;s to use, is skipped and named in skipped rather than failing the whole restore. Deletes any custom class the original import created that nothing references any more (named in removed_classes), never a system class, and never one that any position, watchlist item, or another scenario\u0026#x27;s rule still uses. Takes a fresh restore point of the scenario\u0026#x27;s rules right before this restore, first, so the restore can itself be undone the same way: restore_point_id on the response is that new point, never the one you passed in. 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=Undo+an+import+or+an+earlier+restore\u0026amp;description=Re-applies+the+rules+a+restore+point+saved%2C+by+%60asset_class_id%60%3A%0Athe+same+absolute-state+reconciliation+%60POST+%2Fscenarios%2F%7Bid%7D%2Frules%60%0Aand+%60POST+%2Fscenarios%2F%7Bid%7D%2Fp\u0026amp;theme=f4ffca4ae92cd96f3d29a15e\u0026amp;signature=8ae7b0c1310e399a0deefaf12da845c11299fbdee728e8f22143254e2aa40baa\">\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/undo-an-import-or-an-earlier-restore\">\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/undo-an-import-or-an-earlier-restore.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/undo-an-import-or-an-earlier-restore#webpage\",\"url\":\"https://docs.allocait.app/api-reference/rules/undo-an-import-or-an-earlier-restore\",\"name\":\"Undo an import or an earlier restore\",\"description\":\"Re-applies the rules a restore point saved, by asset_class_id: the same absolute-state reconciliation POST /scenarios/{id}/rules and POST /scenarios/{id}/position-rules/apply use. A saved rule whose class no longer exists, or is no longer this key's to use, is skipped and named in skipped rather than failing the whole restore. Deletes any custom class the original import created that nothing references any more (named in removed_classes), never a system class, and never one that any position, watchlist item, or another scenario's rule still uses. Takes a fresh restore point of the scenario's rules right before this restore, first, so the restore can itself be undone the same way: restore_point_id on the response is that new point, never the one you passed in. Requires the API key to have the write permission.\",\"dateModified\":\"2026-11-09T05:23:22.083Z\",\"isPartOf\":{\"@id\":\"https://docs.allocait.app#website\"},\"breadcrumb\":{\"@id\":\"https://docs.allocait.app/api-reference/rules/undo-an-import-or-an-earlier-restore#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.allocait.app/api-reference/rules/undo-an-import-or-an-earlier-restore#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\":\"Undo an import or an earlier restore\",\"item\":\"https://docs.allocait.app/api-reference/rules/undo-an-import-or-an-earlier-restore\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.allocait.app/api-reference/rules/undo-an-import-or-an-earlier-restore#apireference\",\"headline\":\"Undo an import or an earlier restore\",\"name\":\"Undo an import or an earlier restore\",\"description\":\"Re-applies the rules a restore point saved, by asset_class_id: the same absolute-state reconciliation POST /scenarios/{id}/rules and POST /scenarios/{id}/position-rules/apply use. A saved rule whose class no longer exists, or is no longer this key's to use, is skipped and named in skipped rather than failing the whole restore. Deletes any custom class the original import created that nothing references any more (named in removed_classes), never a system class, and never one that any position, watchlist item, or another scenario's rule still uses. Takes a fresh restore point of the scenario's rules right before this restore, first, so the restore can itself be undone the same way: restore_point_id on the response is that new point, never the one you passed in. Requires the API key to have the write permission.\",\"url\":\"https://docs.allocait.app/api-reference/rules/undo-an-import-or-an-earlier-restore\",\"mainEntityOfPage\":{\"@id\":\"https://docs.allocait.app/api-reference/rules/undo-an-import-or-an-earlier-restore#webpage\"},\"dateModified\":\"2026-11-09T05:23:22.083Z\",\"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/undo-an-import-or-an-earlier-restore.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)","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","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","description":"One row per import or restore (ADR-050), holding the scenario's\nrules from immediately before that write. An undo point, not a\nchange log (past values per class rule are `rule_changes` on `GET\n/scenarios/{id}/rules`). Allocait keeps no reasoning, and this\nlist is already capped to the most recent 20 per caller, trimmed on\nevery write. Not paginated (see the Pagination note above).\n","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","description":"Everything an agent needs to learn the rules text format from the\nAPI itself, with no other document to fetch: the full spec as\nmarkdown (`spec`), four ready-to-import example files spanning a\nbeginner's 3-class file to a converted advisor IPS (`examples`),\nand copy/paste prompts for writing, converting, or checking\nrules text with any AI (`prompts`). All three come from the same\nshared module `GET /scenarios/{id}/rules` and `POST\n/scenarios/{id}/rules` parse and render with, so nothing here can\ndrift from what actually validates.\n","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":"Undo an import or an earlier restore - 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"]}