Register an environment: a named target sessions can be opened against.
Supports the standard Idempotency-Key header, which is the mechanism to
reach for in CI: a retry with the same key and body replays the original
environment (200 instead of 201), and the same key with a different body is a
409 idempotency_conflict.
get_or_create is the older, coarser flag and remains supported. Note what
it does NOT do: on a name match it returns the EXISTING row untouched and
IGNORES every other field on this request, so a request whose config has
drifted from the stored one succeeds while changing nothing. Use
Idempotency-Key for retry safety and PATCH to reconcile config.
POST
/
api
/
v1
/
workspaces
/
{workspace_id}
/
environments
Create Environment
curl --request POST \ --url https://api.ishlabs.io/api/v1/workspaces/{workspace_id}/environments \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "config": { "url": "https://staging.example.com/checkout" }, "example_actions": [ { "description": "Move from the cart to the payment step.", "name": "continue_to_payment" }, { "description": "Return to the cart without paying.", "name": "back_to_cart" } ], "kind": "web", "name": "Checkout (staging)", "operating_notes": "Test card 4242 4242 4242 4242. Coupon codes are disabled here."}'
import requests
url = "https://api.ishlabs.io/api/v1/workspaces/{workspace_id}/environments"
payload = {
"config": { "url": "https://staging.example.com/checkout" },
"example_actions": [
{
"description": "Move from the cart to the payment step.",
"name": "continue_to_payment"
},
{
"description": "Return to the cart without paying.",
"name": "back_to_cart"
}
],
"kind": "web",
"name": "Checkout (staging)",
"operating_notes": "Test card 4242 4242 4242 4242. Coupon codes are disabled here."
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)
const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
config: {url: 'https://staging.example.com/checkout'},
example_actions: [
{
description: 'Move from the cart to the payment step.',
name: 'continue_to_payment'
},
{description: 'Return to the cart without paying.', name: 'back_to_cart'}
],
kind: 'web',
name: 'Checkout (staging)',
operating_notes: 'Test card 4242 4242 4242 4242. Coupon codes are disabled here.'
})
};
fetch('https://api.ishlabs.io/api/v1/workspaces/{workspace_id}/environments', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
Workspace API key as a bearer token: Authorization: Bearer ish_sk_live_.... Keys are workspace-scoped machine principals minted in Settings > Developers (shown once at mint). Scopes: sessions:run (create a session, submit turns, close), sessions:read (read the session and its decision trace), environments:read and environments:write (manage the workspace's registered environments), tasks:read and tasks:write (manage the workspace's registered tasks), people:read and people:write (the people the workspace can run a session for), and usage:read (the workspace's own consumption, spend limits and rate-limit budgets). A key is minted with sessions:run, sessions:read, and tasks:read by default; every other scope must be requested, people:read and usage:read included. An ish user access token also works on the same header for personal scripts.
What kind of surface this is. Closed on write, open on read: Open union: new values may be added over time; clients must tolerate unknown values rather than failing on them.
Every field is optional at the type level and required by KIND at validation time: a web environment needs url, and so on. Unknown keys are REJECTED on write, so a typo surfaces as a 422 instead of a target that was silently never set.
Example action vocabulary for this environment (same shape as a turn's valid_actions). NON-AUTHORITATIVE: documentation and SDK scaffolding only, never read at turn time. Every turn declares its own valid_actions, which is the only authoritative source.
Idempotent register for CI: when a LIVE environment with this name (case-insensitive) and the SAME kind already exists, return it with 200 instead of 409. The existing row is returned AS IS: config, notes and example_actions on this request are ignored, never silently applied, and the address-dedupe check is not evaluated on this path (nothing is written). A name held by a different kind still conflicts (409).
How long sessions on this environment keep their observation frames: none (discard after each turn), 30d, 90d, or indefinite. Omit for the default (30d). A session may override this at open; the resolved value is fixed for that session's life.
Operating manual for the RESOLVER only, never shown to the person. Becomes the default resolver_guidance for sessions opened against this environment; a session may pass its own, which wins.
The existing environment, RETURNED AS IS: nothing on this request was applied to it. Two paths reach here: an Idempotency-Key replay (same key, same body), or get_or_create with a live environment already holding this name and kind.
Normalized target identity derived from config (scheme, host and path only). A duplicate-registration guard, NOT the environment's identity, since sessions always reference the id.
Set when the environment is archived (DELETE). An archived environment stays readable by id so existing sessions keep resolving, is hidden from the default list, and frees its name for reuse.
The configuration of an environment as stored, tolerant of unknown keys.
Same fields as the write shape, but a key this client does not know is IGNORED rather than rejected: reads must keep working across server versions, and because a list response parses the whole page, one unfamiliar key would otherwise fail an entire workspace listing rather than its own row. Closed on write, open on read.
Who computes the next observation for this environment. Derived from kind and config, never client-set. Open union: new values may be added over time; clients must tolerate unknown values rather than failing on them.
How long sessions on this environment keep their observation frames: none, 30d, 90d, or indefinite. Open union: new values may be added over time; clients must tolerate unknown values rather than failing on them.
Increments on every write to this environment's identity or configuration. Usage is aggregated by (id, revision), so a run reports against the configuration it actually ran on. Archiving does not change it.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"ish","description":"Documentation for the ish CLI and MCP server. Simulate a visit and read the reactions before you ship.","colors":{"primary":"#C8623F","light":"#D87A55","dark":"#262220"},"logo":{"light":"https://mintcdn.com/ish/4MaJn6-B7_NnPAml/logo/light.svg?fit=max\u0026auto=format\u0026n=4MaJn6-B7_NnPAml\u0026q=85\u0026s=f0edab6b74c19bec95794ee94d7270c2","dark":"https://mintcdn.com/ish/4MaJn6-B7_NnPAml/logo/dark.svg?fit=max\u0026auto=format\u0026n=4MaJn6-B7_NnPAml\u0026q=85\u0026s=da9e886222890dc4edeaf5b77b455102"},"favicon":{"light":"https://mintcdn.com/ish/4MaJn6-B7_NnPAml/favicon.svg?fit=max\u0026auto=format\u0026n=4MaJn6-B7_NnPAml\u0026q=85\u0026s=871b7f0a040fb0e8c3293911bcbfd37d","dark":"https://mintcdn.com/ish/4MaJn6-B7_NnPAml/favicon-dark.svg?fit=max\u0026auto=format\u0026n=4MaJn6-B7_NnPAml\u0026q=85\u0026s=8915499d3e98ef136443c3c38b96e4b9"},"appearance":{"default":"system"},"background":{"color":{"light":"#FDFCFB","dark":"#1A1816"}},"navbar":{"links":[{"href":"https://app.ishlabs.io","label":"Sign in"}],"primary":{"type":"button","label":"Get ish free","href":"https://app.ishlabs.io"}},"footer":{"socials":{"github":"https://github.com/ishlabs"},"links":[{"header":"Product","items":[{"label":"ishlabs.io","href":"https://ishlabs.io"},{"label":"Pricing","href":"https://ishlabs.io/pricing"},{"label":"Sign in","href":"https://app.ishlabs.io"}]}]},"fonts":{"heading":{"family":"Inter"},"body":{"family":"Inter"}},"contextual":{"options":["copy","view","chatgpt","claude","mcp","cursor","vscode"],"display":"header"},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/ishlabs"},{"anchor":"ishlabs.io","icon":"globe","href":"https://ishlabs.io"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"ish","hasAudioNarration":false,"actualSubdomain":"ish","customDomains":["docs.ishlabs.io"],"gitSource":{"type":"github","owner":"ishlabs","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":false,"mountPath":"","label":""},"feedback":{"thumbs":false},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6af0209f0311aab340dbb5c0","clientVersion":"0.0.4094","searchFilterCounts":[{"language":"default","tag":"Guides","count":45},{"language":"default","tag":"API","count":42},{"language":"default","tag":"API reference","count":28},{"language":"default","tag":"CLI Reference","count":28},{"language":"default","tag":"Core concepts","count":26},{"language":"default","tag":"MCP Reference","count":21},{"language":"default","tag":"Commands","count":20},{"language":"default","tag":"Overview","count":15},{"language":"default","tag":"Tools","count":13},{"language":"default","tag":"How-to guides","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":"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},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"[data-component-part=\"card-icon\"] svg{background-color:#262220!important}html.dark [data-component-part=\"card-icon\"] svg{background-color:#e8e3de!important}html.dark img[src*=\"/logos/\"]{filter:invert(0.91) brightness(1.03)}#content-area a[href]>div:hover,.ish-card:hover{border-color:#d87a55;transition:border-color 0.15s ease, box-shadow 0.15s ease}"}],"page":{"pagePath":"api/reference/environments/create-environment","slug":"/api/reference/environments/create-environment","pageMetadata":{"title":"Create Environment","description":"Register an environment: a named target sessions can be opened against.\n\nSupports the standard `Idempotency-Key` header, which is the mechanism to\nreach for in CI: a retry with the same key and body replays the original\nenvironment (200 instead of 201), and the same key with a different body is a\n409 `idempotency_conflict`.\n\n`get_or_create` is the older, coarser flag and remains supported. Note what\nit does NOT do: on a name match it returns the EXISTING row untouched and\nIGNORES every other field on this request, so a request whose config has\ndrifted from the stored one succeeds while changing nothing. Use\n`Idempotency-Key` for retry safety and PATCH to reconcile config.","deprecated":null,"version":null,"openapi":"/api/openapi.public.json post /api/v1/workspaces/{workspace_id}/environments","href":"/api/reference/environments/create-environment","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 ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsx(_components.p, {\n children: \"Register an environment: a named target sessions can be opened against.\"\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Supports the standard \", _jsx(_components.code, {\n children: \"Idempotency-Key\"\n }), \" header, which is the mechanism to\\nreach for in CI: a retry with the same key and body replays the original\\nenvironment (200 instead of 201), and the same key with a different body is a\\n409 \", _jsx(_components.code, {\n children: \"idempotency_conflict\"\n }), \".\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [_jsx(_components.code, {\n children: \"get_or_create\"\n }), \" is the older, coarser flag and remains supported. Note what\\nit does NOT do: on a name match it returns the EXISTING row untouched and\\nIGNORES every other field on this request, so a request whose config has\\ndrifted from the stored one succeeds while changing nothing. Use\\n\", _jsx(_components.code, {\n children: \"Idempotency-Key\"\n }), \" for retry safety and PATCH to reconcile config.\"]\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":"Create Environment","description":"Register an environment: a named target sessions can be opened against.\n\nSupports the standard `Idempotency-Key` header, which is the mechanism to\nreach for in CI: a retry with the same key and body replays the original\nenvironment (200 instead of 201), and the same key with a different body is a\n409 `idempotency_conflict`.\n\n`get_or_create` is the older, coarser flag and remains supported. Note what\nit does NOT do: on a name match it returns the EXISTING row untouched and\nIGNORES every other field on this request, so a request whose config has\ndrifted from the stored one succeeds while changing nothing. Use\n`Idempotency-Key` for retry safety and PATCH to reconcile config.","deprecated":null,"version":null,"openapi":"/api/openapi.public.json post /api/v1/workspaces/{workspace_id}/environments","href":"/api/reference/environments/create-environment","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"description":"Register an environment: a named target sessions can be opened against.\n\nSupports the standard `Idempotency-Key` header, which is the mechanism to\nreach for in CI: a retry with the same key and body replays the original\nenvironment (200 instead of 201), and the same key with a different body is a\n409 `idempotency_conflict`.\n\n`get_or_create` is the older, coarser flag and remains supported. Note what\nit does NOT do: on a name match it returns the EXISTING row untouched and\nIGNORES every other field on this request, so a request whose config has\ndrifted from the stored one succeeds while changing nothing. Use\n`Idempotency-Key` for retry safety and PATCH to reconcile config.","operationId":"createEnvironment","parameters":["c0e91b79-ac22-43f4-8976-807e28f07f96","0b80a69f-b6e9-4b3f-be18-144a986e9a59"],"requestBody":"08ad2f6f-6a53-4870-bd14-37dce1a40ce4","responses":{"200":"47f45228-bda4-42d3-a291-2fd0f5bf57db","201":"0a04fa85-76db-45e6-a10b-a2c590fdadf1","401":"2fe8b246-c8e4-45f8-bbfa-39a482d7972a","403":"db8b5cc3-b026-4306-91f3-0b5515437a6d","404":"e38f3dd4-ede9-4d32-9c95-2f3bc7b88a75","409":"24e26f75-72e1-4acf-abe9-3032261f6970","422":"161fd9eb-0c98-4d89-b32f-87e1a2233edd","429":"99ecf198-4699-4b49-a6a8-ac4ce1aa4d13"},"security":["63c05557-f0ce-4f81-ac7a-12db37c76322"],"summary":"Create Environment","tags":["environments"],"method":"post","type":"path","servers":["22c3a961-b6d9-4922-b5aa-d0aac292aa39"],"path":"/api/v1/workspaces/{workspace_id}/environments","baseUrlOptions":["https://api.ishlabs.io"],"title":"Create Environment","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"c0e91b79-ac22-43f4-8976-807e28f07f96":{"in":"path","name":"workspace_id","required":true,"schema":{"format":"uuid","title":"Workspace Id","type":"string","isRequired":true,"uniqueKey":"","typeLabel":"string\u003cuuid>"}},"0b80a69f-b6e9-4b3f-be18-144a986e9a59":{"in":"header","name":"Idempotency-Key","required":false,"schema":{"oneOf":[{"type":"string","title":"Idempotency-Key","uniqueKey":"oneOf.0","typeLabel":"string"},{"type":"null","title":"Idempotency-Key","uniqueKey":"oneOf.1","typeLabel":"null"}],"isRequired":false,"uniqueKey":"","typeLabel":"string | null"}}},"requestBody":{"content":{"application/json":{"examples":{"default":{"title":"default","value":{"config":{"url":"https://staging.example.com/checkout"},"example_actions":[{"description":"Move from the cart to the payment step.","name":"continue_to_payment"},{"description":"Return to the cart without paying.","name":"back_to_cart"}],"kind":"web","name":"Checkout (staging)","operating_notes":"Test card 4242 4242 4242 4242. Coupon codes are disabled here."}}},"schema":{"additionalProperties":false,"properties":{"kind":{"description":"What kind of surface this is. Closed on write, open on read: Open union: new values may be added over time; clients must tolerate unknown values rather than failing on them.","enum":["web","device","world"],"title":"EnvironmentKind","type":"string","isRequired":true,"uniqueKey":"kind","typeLabel":"enum\u003cstring>"},"name":{"maxLength":120,"minLength":1,"title":"Name","type":"string","isRequired":true,"uniqueKey":"name","typeLabel":"string"},"config":{"additionalProperties":false,"description":"The per-kind configuration of an environment.\n\nEvery field is optional at the type level and required by KIND at validation time: a `web` environment needs `url`, and so on. Unknown keys are REJECTED on write, so a typo surfaces as a 422 instead of a target that was silently never set.","properties":{"app_artifact":{"oneOf":[{"type":"string","title":"App Artifact","maxLength":2000,"minLength":1,"uniqueKey":"config.app_artifact.oneOf.0","typeLabel":"string"},{"type":"null","title":"App Artifact","uniqueKey":"config.app_artifact.oneOf.1","typeLabel":"null"}],"uniqueKey":"config.app_artifact","typeLabel":"string | null"},"origins":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"config.origins.oneOf.0.items.[INDEX]","typeLabel":"string"},"title":"Origins","maxItems":50,"uniqueKey":"config.origins.oneOf.0","typeLabel":"string[]"},{"type":"null","title":"Origins","uniqueKey":"config.origins.oneOf.1","typeLabel":"null"}],"uniqueKey":"config.origins","typeLabel":"string[] | null"},"url":{"oneOf":[{"type":"string","title":"Url","maxLength":2000,"uniqueKey":"config.url.oneOf.0","typeLabel":"string"},{"type":"null","title":"Url","uniqueKey":"config.url.oneOf.1","typeLabel":"null"}],"uniqueKey":"config.url","typeLabel":"string | null"}},"title":"EnvironmentConfig","type":"object","uniqueKey":"config","typeLabel":"EnvironmentConfig · object"},"example_actions":{"description":"Example action vocabulary for this environment (same shape as a turn's `valid_actions`). NON-AUTHORITATIVE: documentation and SDK scaffolding only, never read at turn time. Every turn declares its own `valid_actions`, which is the only authoritative source.","items":{"additionalProperties":true,"type":"object","uniqueKey":"example_actions.items.[INDEX]","typeLabel":"object"},"title":"Example Actions","type":"array","uniqueKey":"example_actions","typeLabel":"Example Actions · object[]"},"get_or_create":{"default":false,"description":"Idempotent register for CI: when a LIVE environment with this name (case-insensitive) and the SAME kind already exists, return it with 200 instead of 409. The existing row is returned AS IS: config, notes and example_actions on this request are ignored, never silently applied, and the address-dedupe check is not evaluated on this path (nothing is written). A name held by a different kind still conflicts (409).","title":"Get Or Create","type":"boolean","uniqueKey":"get_or_create","typeLabel":"boolean"},"observation_retention":{"oneOf":[{"type":"string","title":"ObservationRetention","description":"How long sessions on this environment keep their observation frames: `none` (discard after each turn), `30d`, `90d`, or `indefinite`. Omit for the default (`30d`). A session may override this at open; the resolved value is fixed for that session's life.","enum":["none","30d","90d","indefinite"],"uniqueKey":"observation_retention.oneOf.0","typeLabel":"enum\u003cstring>"},{"type":"null","description":"How long sessions on this environment keep their observation frames: `none` (discard after each turn), `30d`, `90d`, or `indefinite`. Omit for the default (`30d`). A session may override this at open; the resolved value is fixed for that session's life.","uniqueKey":"observation_retention.oneOf.1","typeLabel":"null"}],"uniqueKey":"observation_retention","typeLabel":"enum\u003cstring> | null"},"operating_notes":{"oneOf":[{"type":"string","title":"Operating Notes","description":"Operating manual for the RESOLVER only, never shown to the person. Becomes the default `resolver_guidance` for sessions opened against this environment; a session may pass its own, which wins.","maxLength":8000,"uniqueKey":"operating_notes.oneOf.0","typeLabel":"string"},{"type":"null","title":"Operating Notes","description":"Operating manual for the RESOLVER only, never shown to the person. Becomes the default `resolver_guidance` for sessions opened against this environment; a session may pass its own, which wins.","uniqueKey":"operating_notes.oneOf.1","typeLabel":"null"}],"uniqueKey":"operating_notes","typeLabel":"string | null"},"slug":{"oneOf":[{"type":"string","title":"Slug","maxLength":120,"uniqueKey":"slug.oneOf.0","typeLabel":"string"},{"type":"null","title":"Slug","uniqueKey":"slug.oneOf.1","typeLabel":"null"}],"uniqueKey":"slug","typeLabel":"string | null"}},"required":["name","kind"],"title":"CreateEnvironmentRequest","type":"object","uniqueKey":"","typeLabel":"CreateEnvironmentRequest · object"},"exampleType":"examples"}},"required":true,"exampleType":"examples"},"responses":{"47f45228-bda4-42d3-a291-2fd0f5bf57db":{"content":{"application/json":{"schema":{"description":"A registered environment as the caller sees it.","properties":{"address":{"oneOf":[{"type":"string","title":"Address","description":"Normalized target identity derived from `config` (scheme, host and path only). A duplicate-registration guard, NOT the environment's identity, since sessions always reference the id.","isRequired":true,"uniqueKey":"address.oneOf.0","typeLabel":"string"},{"type":"null","title":"Address","description":"Normalized target identity derived from `config` (scheme, host and path only). A duplicate-registration guard, NOT the environment's identity, since sessions always reference the id.","isRequired":true,"uniqueKey":"address.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"address","typeLabel":"string | null"},"archived_at":{"oneOf":[{"type":"string","title":"Archived At","description":"Set when the environment is archived (DELETE). An archived environment stays readable by id so existing sessions keep resolving, is hidden from the default list, and frees its name for reuse.","format":"date-time","isRequired":true,"uniqueKey":"archived_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","title":"Archived At","description":"Set when the environment is archived (DELETE). An archived environment stays readable by id so existing sessions keep resolving, is hidden from the default list, and frees its name for reuse.","isRequired":true,"uniqueKey":"archived_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"archived_at","typeLabel":"string\u003cdate-time> | null"},"config":{"description":"The configuration of an environment as stored, tolerant of unknown keys.\n\nSame fields as the write shape, but a key this client does not know is IGNORED rather than rejected: reads must keep working across server versions, and because a list response parses the whole page, one unfamiliar key would otherwise fail an entire workspace listing rather than its own row. Closed on write, open on read.","properties":{"app_artifact":{"oneOf":[{"type":"string","title":"App Artifact","maxLength":2000,"minLength":1,"uniqueKey":"config.app_artifact.oneOf.0","typeLabel":"string"},{"type":"null","title":"App Artifact","uniqueKey":"config.app_artifact.oneOf.1","typeLabel":"null"}],"uniqueKey":"config.app_artifact","typeLabel":"string | null"},"origins":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"config.origins.oneOf.0.items.[INDEX]","typeLabel":"string"},"title":"Origins","maxItems":50,"uniqueKey":"config.origins.oneOf.0","typeLabel":"string[]"},{"type":"null","title":"Origins","uniqueKey":"config.origins.oneOf.1","typeLabel":"null"}],"uniqueKey":"config.origins","typeLabel":"string[] | null"},"url":{"oneOf":[{"type":"string","title":"Url","maxLength":2000,"uniqueKey":"config.url.oneOf.0","typeLabel":"string"},{"type":"null","title":"Url","uniqueKey":"config.url.oneOf.1","typeLabel":"null"}],"uniqueKey":"config.url","typeLabel":"string | null"}},"title":"StoredEnvironmentConfig","type":"object","isRequired":true,"uniqueKey":"config","typeLabel":"StoredEnvironmentConfig · object"},"created_at":{"format":"date-time","title":"Created At","type":"string","isRequired":true,"uniqueKey":"created_at","typeLabel":"string\u003cdate-time>"},"example_actions":{"items":{"additionalProperties":true,"type":"object","uniqueKey":"example_actions.items.[INDEX]","typeLabel":"object"},"title":"Example Actions","type":"array","isRequired":true,"uniqueKey":"example_actions","typeLabel":"Example Actions · object[]"},"hosting":{"description":"Who computes the next observation for this environment. Derived from kind and config, never client-set. Open union: new values may be added over time; clients must tolerate unknown values rather than failing on them.","title":"Hosting","type":"string","isRequired":true,"uniqueKey":"hosting","typeLabel":"string"},"id":{"format":"uuid","title":"Id","type":"string","isRequired":true,"uniqueKey":"id","typeLabel":"string\u003cuuid>"},"kind":{"description":"What kind of surface this is. Open union: new values may be added over time; clients must tolerate unknown values rather than failing on them.","title":"Kind","type":"string","isRequired":true,"uniqueKey":"kind","typeLabel":"string"},"name":{"title":"Name","type":"string","isRequired":true,"uniqueKey":"name","typeLabel":"string"},"observation_retention":{"description":"How long sessions on this environment keep their observation frames: `none`, `30d`, `90d`, or `indefinite`. Open union: new values may be added over time; clients must tolerate unknown values rather than failing on them.","title":"Observation Retention","type":"string","isRequired":true,"uniqueKey":"observation_retention","typeLabel":"string"},"operating_notes":{"oneOf":[{"type":"string","title":"Operating Notes","isRequired":true,"uniqueKey":"operating_notes.oneOf.0","typeLabel":"string"},{"type":"null","title":"Operating Notes","isRequired":true,"uniqueKey":"operating_notes.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"operating_notes","typeLabel":"string | null"},"revision":{"description":"Increments on every write to this environment's identity or configuration. Usage is aggregated by (id, revision), so a run reports against the configuration it actually ran on. Archiving does not change it.","title":"Revision","type":"integer","isRequired":true,"uniqueKey":"revision","typeLabel":"integer"},"slug":{"oneOf":[{"type":"string","title":"Slug","isRequired":true,"uniqueKey":"slug.oneOf.0","typeLabel":"string"},{"type":"null","title":"Slug","isRequired":true,"uniqueKey":"slug.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"slug","typeLabel":"string | null"},"updated_at":{"format":"date-time","title":"Updated At","type":"string","isRequired":true,"uniqueKey":"updated_at","typeLabel":"string\u003cdate-time>"},"workspace_id":{"format":"uuid","title":"Workspace Id","type":"string","isRequired":true,"uniqueKey":"workspace_id","typeLabel":"string\u003cuuid>"}},"required":["id","workspace_id","name","kind","slug","config","operating_notes","observation_retention","example_actions","hosting","address","revision","archived_at","created_at","updated_at"],"title":"EnvironmentResponse","type":"object","uniqueKey":"","typeLabel":"EnvironmentResponse · object"},"examples":{"Example":{"title":"Example","value":{"address":"\u003cstring>","archived_at":"2023-11-07T05:31:56Z","config":{"app_artifact":"\u003cstring>","origins":["\u003cstring>"],"url":"\u003cstring>"},"created_at":"2023-11-07T05:31:56Z","example_actions":[{}],"hosting":"\u003cstring>","id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","kind":"\u003cstring>","name":"\u003cstring>","observation_retention":"\u003cstring>","operating_notes":"\u003cstring>","revision":123,"slug":"\u003cstring>","updated_at":"2023-11-07T05:31:56Z","workspace_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a"}}},"exampleType":"generated"}},"description":"The existing environment, RETURNED AS IS: nothing on this request was applied to it. Two paths reach here: an `Idempotency-Key` replay (same key, same body), or `get_or_create` with a live environment already holding this name and kind.","headers":{"X-Request-Id":{"description":"Per-response correlation id, present on EVERY response (success and error). Error bodies echo it as `request_id`.","schema":{"type":"string"}},"x-ratelimit-limit":{"description":"Ceiling for the rate-limit window this request charged. Present on responses made with an API key against a rate-limited operation, including the `429` itself; absent for user access tokens (which carry no per-key budget) and when the rate-limit backend could not be read.","schema":{"type":"integer"}},"x-ratelimit-remaining":{"description":"Requests left in that window AFTER this one was counted. Pace off this rather than waiting for a `429`.","schema":{"type":"integer"}},"x-ratelimit-reset":{"description":"**Seconds from now** until that window resets (a delta, NOT a Unix timestamp). Measured when the response is written. Omitted on the rare occasion the reset instant could not be read, while `limit` and `remaining` are still published.","schema":{"type":"integer"}}},"exampleType":"generated"},"0a04fa85-76db-45e6-a10b-a2c590fdadf1":{"content":{"application/json":{"schema":{"description":"A registered environment as the caller sees it.","properties":{"address":{"oneOf":[{"type":"string","title":"Address","description":"Normalized target identity derived from `config` (scheme, host and path only). A duplicate-registration guard, NOT the environment's identity, since sessions always reference the id.","isRequired":true,"uniqueKey":"address.oneOf.0","typeLabel":"string"},{"type":"null","title":"Address","description":"Normalized target identity derived from `config` (scheme, host and path only). A duplicate-registration guard, NOT the environment's identity, since sessions always reference the id.","isRequired":true,"uniqueKey":"address.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"address","typeLabel":"string | null"},"archived_at":{"oneOf":[{"type":"string","title":"Archived At","description":"Set when the environment is archived (DELETE). An archived environment stays readable by id so existing sessions keep resolving, is hidden from the default list, and frees its name for reuse.","format":"date-time","isRequired":true,"uniqueKey":"archived_at.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","title":"Archived At","description":"Set when the environment is archived (DELETE). An archived environment stays readable by id so existing sessions keep resolving, is hidden from the default list, and frees its name for reuse.","isRequired":true,"uniqueKey":"archived_at.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"archived_at","typeLabel":"string\u003cdate-time> | null"},"config":{"description":"The configuration of an environment as stored, tolerant of unknown keys.\n\nSame fields as the write shape, but a key this client does not know is IGNORED rather than rejected: reads must keep working across server versions, and because a list response parses the whole page, one unfamiliar key would otherwise fail an entire workspace listing rather than its own row. Closed on write, open on read.","properties":{"app_artifact":{"oneOf":[{"type":"string","title":"App Artifact","maxLength":2000,"minLength":1,"uniqueKey":"config.app_artifact.oneOf.0","typeLabel":"string"},{"type":"null","title":"App Artifact","uniqueKey":"config.app_artifact.oneOf.1","typeLabel":"null"}],"uniqueKey":"config.app_artifact","typeLabel":"string | null"},"origins":{"oneOf":[{"type":"array","items":{"type":"string","uniqueKey":"config.origins.oneOf.0.items.[INDEX]","typeLabel":"string"},"title":"Origins","maxItems":50,"uniqueKey":"config.origins.oneOf.0","typeLabel":"string[]"},{"type":"null","title":"Origins","uniqueKey":"config.origins.oneOf.1","typeLabel":"null"}],"uniqueKey":"config.origins","typeLabel":"string[] | null"},"url":{"oneOf":[{"type":"string","title":"Url","maxLength":2000,"uniqueKey":"config.url.oneOf.0","typeLabel":"string"},{"type":"null","title":"Url","uniqueKey":"config.url.oneOf.1","typeLabel":"null"}],"uniqueKey":"config.url","typeLabel":"string | null"}},"title":"StoredEnvironmentConfig","type":"object","isRequired":true,"uniqueKey":"config","typeLabel":"StoredEnvironmentConfig · object"},"created_at":{"format":"date-time","title":"Created At","type":"string","isRequired":true,"uniqueKey":"created_at","typeLabel":"string\u003cdate-time>"},"example_actions":{"items":{"additionalProperties":true,"type":"object","uniqueKey":"example_actions.items.[INDEX]","typeLabel":"object"},"title":"Example Actions","type":"array","isRequired":true,"uniqueKey":"example_actions","typeLabel":"Example Actions · object[]"},"hosting":{"description":"Who computes the next observation for this environment. Derived from kind and config, never client-set. Open union: new values may be added over time; clients must tolerate unknown values rather than failing on them.","title":"Hosting","type":"string","isRequired":true,"uniqueKey":"hosting","typeLabel":"string"},"id":{"format":"uuid","title":"Id","type":"string","isRequired":true,"uniqueKey":"id","typeLabel":"string\u003cuuid>"},"kind":{"description":"What kind of surface this is. Open union: new values may be added over time; clients must tolerate unknown values rather than failing on them.","title":"Kind","type":"string","isRequired":true,"uniqueKey":"kind","typeLabel":"string"},"name":{"title":"Name","type":"string","isRequired":true,"uniqueKey":"name","typeLabel":"string"},"observation_retention":{"description":"How long sessions on this environment keep their observation frames: `none`, `30d`, `90d`, or `indefinite`. Open union: new values may be added over time; clients must tolerate unknown values rather than failing on them.","title":"Observation Retention","type":"string","isRequired":true,"uniqueKey":"observation_retention","typeLabel":"string"},"operating_notes":{"oneOf":[{"type":"string","title":"Operating Notes","isRequired":true,"uniqueKey":"operating_notes.oneOf.0","typeLabel":"string"},{"type":"null","title":"Operating Notes","isRequired":true,"uniqueKey":"operating_notes.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"operating_notes","typeLabel":"string | null"},"revision":{"description":"Increments on every write to this environment's identity or configuration. Usage is aggregated by (id, revision), so a run reports against the configuration it actually ran on. Archiving does not change it.","title":"Revision","type":"integer","isRequired":true,"uniqueKey":"revision","typeLabel":"integer"},"slug":{"oneOf":[{"type":"string","title":"Slug","isRequired":true,"uniqueKey":"slug.oneOf.0","typeLabel":"string"},{"type":"null","title":"Slug","isRequired":true,"uniqueKey":"slug.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"slug","typeLabel":"string | null"},"updated_at":{"format":"date-time","title":"Updated At","type":"string","isRequired":true,"uniqueKey":"updated_at","typeLabel":"string\u003cdate-time>"},"workspace_id":{"format":"uuid","title":"Workspace Id","type":"string","isRequired":true,"uniqueKey":"workspace_id","typeLabel":"string\u003cuuid>"}},"required":["id","workspace_id","name","kind","slug","config","operating_notes","observation_retention","example_actions","hosting","address","revision","archived_at","created_at","updated_at"],"title":"EnvironmentResponse","type":"object","uniqueKey":"","typeLabel":"EnvironmentResponse · object"},"examples":{"Example":{"title":"Example","value":{"address":"\u003cstring>","archived_at":"2023-11-07T05:31:56Z","config":{"app_artifact":"\u003cstring>","origins":["\u003cstring>"],"url":"\u003cstring>"},"created_at":"2023-11-07T05:31:56Z","example_actions":[{}],"hosting":"\u003cstring>","id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","kind":"\u003cstring>","name":"\u003cstring>","observation_retention":"\u003cstring>","operating_notes":"\u003cstring>","revision":123,"slug":"\u003cstring>","updated_at":"2023-11-07T05:31:56Z","workspace_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a"}}},"exampleType":"generated"}},"description":"Successful Response","headers":{"X-Request-Id":{"description":"Per-response correlation id, present on EVERY response (success and error). Error bodies echo it as `request_id`.","schema":{"type":"string"}},"x-ratelimit-limit":{"description":"Ceiling for the rate-limit window this request charged. Present on responses made with an API key against a rate-limited operation, including the `429` itself; absent for user access tokens (which carry no per-key budget) and when the rate-limit backend could not be read.","schema":{"type":"integer"}},"x-ratelimit-remaining":{"description":"Requests left in that window AFTER this one was counted. Pace off this rather than waiting for a `429`.","schema":{"type":"integer"}},"x-ratelimit-reset":{"description":"**Seconds from now** until that window resets (a delta, NOT a Unix timestamp). Measured when the response is written. Omitted on the rare occasion the reset instant could not be read, while `limit` and `remaining` are still published.","schema":{"type":"integer"}}},"exampleType":"generated"},"2fe8b246-c8e4-45f8-bbfa-39a482d7972a":{"content":{"application/json":{"schema":{"description":"Generic error envelope for 4xx/5xx responses other than request-shape validation.","properties":{"detail":{"oneOf":[{"type":"string","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","isRequired":true,"uniqueKey":"detail.oneOf.0","typeLabel":"string"},{"type":"object","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","additionalProperties":true,"isRequired":true,"uniqueKey":"detail.oneOf.1","typeLabel":"Detail · object"}],"isRequired":true,"uniqueKey":"detail","typeLabel":"string | Detail · object"},"request_id":{"description":"Correlation id; identical to the `X-Request-Id` response header. Quote it in support requests.","title":"Request Id","type":"string","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"docs_url":{"description":"Link to this error's entry in the error catalog. Present whenever `detail` carries a registered `error_kind`; absent on unclassified errors.","title":"Docs Url","type":"string","uniqueKey":"docs_url","typeLabel":"string"}},"required":["detail","request_id"],"title":"Error","type":"object","uniqueKey":"","typeLabel":"Error · object"},"examples":{"Example":{"title":"Example","value":{"detail":"\u003cstring>","request_id":"\u003cstring>","docs_url":"\u003cstring>"}}},"exampleType":"generated"}},"description":"The bearer token is missing, malformed, unknown, or revoked (`detail.error_kind = 'invalid_api_key'`). One kind covers all four deliberately: distinguishing them would confirm which guesses are real keys.","headers":{"X-Request-Id":{"description":"Per-response correlation id, present on EVERY response (success and error). Error bodies echo it as `request_id`.","schema":{"type":"string"}},"x-ratelimit-limit":{"description":"Ceiling for the rate-limit window this request charged. Present on responses made with an API key against a rate-limited operation, including the `429` itself; absent for user access tokens (which carry no per-key budget) and when the rate-limit backend could not be read.","schema":{"type":"integer"}},"x-ratelimit-remaining":{"description":"Requests left in that window AFTER this one was counted. Pace off this rather than waiting for a `429`.","schema":{"type":"integer"}},"x-ratelimit-reset":{"description":"**Seconds from now** until that window resets (a delta, NOT a Unix timestamp). Measured when the response is written. Omitted on the rare occasion the reset instant could not be read, while `limit` and `remaining` are still published.","schema":{"type":"integer"}}},"exampleType":"generated"},"db8b5cc3-b026-4306-91f3-0b5515437a6d":{"content":{"application/json":{"schema":{"description":"Generic error envelope for 4xx/5xx responses other than request-shape validation.","properties":{"detail":{"oneOf":[{"type":"string","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","isRequired":true,"uniqueKey":"detail.oneOf.0","typeLabel":"string"},{"type":"object","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","additionalProperties":true,"isRequired":true,"uniqueKey":"detail.oneOf.1","typeLabel":"Detail · object"}],"isRequired":true,"uniqueKey":"detail","typeLabel":"string | Detail · object"},"request_id":{"description":"Correlation id; identical to the `X-Request-Id` response header. Quote it in support requests.","title":"Request Id","type":"string","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"docs_url":{"description":"Link to this error's entry in the error catalog. Present whenever `detail` carries a registered `error_kind`; absent on unclassified errors.","title":"Docs Url","type":"string","uniqueKey":"docs_url","typeLabel":"string"}},"required":["detail","request_id"],"title":"Error","type":"object","uniqueKey":"","typeLabel":"Error · object"},"examples":{"Example":{"title":"Example","value":{"detail":"\u003cstring>","request_id":"\u003cstring>","docs_url":"\u003cstring>"}}},"exampleType":"generated"}},"description":"The API key lacks the `environments:write` scope (`detail.error_kind = 'insufficient_scope'`, with `detail.required_scope = 'environments:write'`). Mint a key that includes it; an ish user access token is unconstrained by scopes.","headers":{"X-Request-Id":{"description":"Per-response correlation id, present on EVERY response (success and error). Error bodies echo it as `request_id`.","schema":{"type":"string"}},"x-ratelimit-limit":{"description":"Ceiling for the rate-limit window this request charged. Present on responses made with an API key against a rate-limited operation, including the `429` itself; absent for user access tokens (which carry no per-key budget) and when the rate-limit backend could not be read.","schema":{"type":"integer"}},"x-ratelimit-remaining":{"description":"Requests left in that window AFTER this one was counted. Pace off this rather than waiting for a `429`.","schema":{"type":"integer"}},"x-ratelimit-reset":{"description":"**Seconds from now** until that window resets (a delta, NOT a Unix timestamp). Measured when the response is written. Omitted on the rare occasion the reset instant could not be read, while `limit` and `remaining` are still published.","schema":{"type":"integer"}}},"exampleType":"generated"},"e38f3dd4-ede9-4d32-9c95-2f3bc7b88a75":{"content":{"application/json":{"schema":{"description":"Generic error envelope for 4xx/5xx responses other than request-shape validation.","properties":{"detail":{"oneOf":[{"type":"string","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","isRequired":true,"uniqueKey":"detail.oneOf.0","typeLabel":"string"},{"type":"object","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","additionalProperties":true,"isRequired":true,"uniqueKey":"detail.oneOf.1","typeLabel":"Detail · object"}],"isRequired":true,"uniqueKey":"detail","typeLabel":"string | Detail · object"},"request_id":{"description":"Correlation id; identical to the `X-Request-Id` response header. Quote it in support requests.","title":"Request Id","type":"string","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"docs_url":{"description":"Link to this error's entry in the error catalog. Present whenever `detail` carries a registered `error_kind`; absent on unclassified errors.","title":"Docs Url","type":"string","uniqueKey":"docs_url","typeLabel":"string"}},"required":["detail","request_id"],"title":"Error","type":"object","uniqueKey":"","typeLabel":"Error · object"},"examples":{"Example":{"title":"Example","value":{"detail":"\u003cstring>","request_id":"\u003cstring>","docs_url":"\u003cstring>"}}},"exampleType":"generated"}},"description":"The workspace (`workspace_id`) was not found, or is not reachable with this credential. `detail.error_kind` is `workspace_not_found`.","headers":{"X-Request-Id":{"description":"Per-response correlation id, present on EVERY response (success and error). Error bodies echo it as `request_id`.","schema":{"type":"string"}},"x-ratelimit-limit":{"description":"Ceiling for the rate-limit window this request charged. Present on responses made with an API key against a rate-limited operation, including the `429` itself; absent for user access tokens (which carry no per-key budget) and when the rate-limit backend could not be read.","schema":{"type":"integer"}},"x-ratelimit-remaining":{"description":"Requests left in that window AFTER this one was counted. Pace off this rather than waiting for a `429`.","schema":{"type":"integer"}},"x-ratelimit-reset":{"description":"**Seconds from now** until that window resets (a delta, NOT a Unix timestamp). Measured when the response is written. Omitted on the rare occasion the reset instant could not be read, while `limit` and `remaining` are still published.","schema":{"type":"integer"}}},"exampleType":"generated"},"24e26f75-72e1-4acf-abe9-3032261f6970":{"content":{"application/json":{"schema":{"description":"Generic error envelope for 4xx/5xx responses other than request-shape validation.","properties":{"detail":{"oneOf":[{"type":"string","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","isRequired":true,"uniqueKey":"detail.oneOf.0","typeLabel":"string"},{"type":"object","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","additionalProperties":true,"isRequired":true,"uniqueKey":"detail.oneOf.1","typeLabel":"Detail · object"}],"isRequired":true,"uniqueKey":"detail","typeLabel":"string | Detail · object"},"request_id":{"description":"Correlation id; identical to the `X-Request-Id` response header. Quote it in support requests.","title":"Request Id","type":"string","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"docs_url":{"description":"Link to this error's entry in the error catalog. Present whenever `detail` carries a registered `error_kind`; absent on unclassified errors.","title":"Docs Url","type":"string","uniqueKey":"docs_url","typeLabel":"string"}},"required":["detail","request_id"],"title":"Error","type":"object","uniqueKey":"","typeLabel":"Error · object"},"examples":{"Example":{"title":"Example","value":{"detail":"\u003cstring>","request_id":"\u003cstring>","docs_url":"\u003cstring>"}}},"exampleType":"generated"}},"description":"`detail.error_kind` says which: `environment_name_taken` (an environment with this name already exists in the workspace; names are unique per workspace, case-insensitive; with `get_or_create`, only a name held by a DIFFERENT kind conflicts), `environment_address_taken`, or `idempotency_conflict` (the `Idempotency-Key` was reused with a different request body).","headers":{"X-Request-Id":{"description":"Per-response correlation id, present on EVERY response (success and error). Error bodies echo it as `request_id`.","schema":{"type":"string"}},"x-ratelimit-limit":{"description":"Ceiling for the rate-limit window this request charged. Present on responses made with an API key against a rate-limited operation, including the `429` itself; absent for user access tokens (which carry no per-key budget) and when the rate-limit backend could not be read.","schema":{"type":"integer"}},"x-ratelimit-remaining":{"description":"Requests left in that window AFTER this one was counted. Pace off this rather than waiting for a `429`.","schema":{"type":"integer"}},"x-ratelimit-reset":{"description":"**Seconds from now** until that window resets (a delta, NOT a Unix timestamp). Measured when the response is written. Omitted on the rare occasion the reset instant could not be read, while `limit` and `remaining` are still published.","schema":{"type":"integer"}}},"exampleType":"generated"},"161fd9eb-0c98-4d89-b32f-87e1a2233edd":{"content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"ValidationError","description":"Request body / parameter validation failure (HTTP 422). A field-level envelope so callers can pinpoint the offending field, value, and allowed values without parsing prose.","required":["error","error_code","status","retryable","detail","errors"],"properties":{"detail":{"title":"Detail","type":"string","isRequired":true,"uniqueKey":"oneOf.0.detail","typeLabel":"string"},"error":{"title":"Error","type":"string","isRequired":true,"uniqueKey":"oneOf.0.error","typeLabel":"string"},"error_code":{"description":"Stable machine code, e.g. `validation_error`.","title":"Error Code","type":"string","isRequired":true,"uniqueKey":"oneOf.0.error_code","typeLabel":"string"},"errors":{"items":{"description":"One field-level entry in a ValidationError envelope.","properties":{"loc":{"description":"Path to the offending field.","items":{"oneOf":[{"type":"string","uniqueKey":"oneOf.0.errors.items.[INDEX].loc.items.[INDEX].oneOf.0","typeLabel":"string"},{"type":"integer","uniqueKey":"oneOf.0.errors.items.[INDEX].loc.items.[INDEX].oneOf.1","typeLabel":"integer"}],"uniqueKey":"oneOf.0.errors.items.[INDEX].loc.items.[INDEX]","typeLabel":"string | integer"},"title":"Location","type":"array","isRequired":true,"uniqueKey":"oneOf.0.errors.items.[INDEX].loc","typeLabel":"(string | integer)[]"},"msg":{"title":"Message","type":"string","isRequired":true,"uniqueKey":"oneOf.0.errors.items.[INDEX].msg","typeLabel":"string"},"type":{"title":"Error Type","type":"string","isRequired":true,"uniqueKey":"oneOf.0.errors.items.[INDEX].type","typeLabel":"string"},"allowed_values":{"description":"For enum/literal failures, the accepted values.","items":{"oneOf":[{}],"uniqueKey":"oneOf.0.errors.items.[INDEX].allowed_values.items.[INDEX]","typeLabel":"any"},"title":"Allowed Values","type":"array","uniqueKey":"oneOf.0.errors.items.[INDEX].allowed_values","typeLabel":"any[]"},"input":{"oneOf":[{"type":"string","title":"Input","description":"Offending value (truncated); omitted for containers.","uniqueKey":"oneOf.0.errors.items.[INDEX].input.oneOf.0","typeLabel":"string"},{"type":"number","title":"Input","description":"Offending value (truncated); omitted for containers.","uniqueKey":"oneOf.0.errors.items.[INDEX].input.oneOf.1","typeLabel":"number"},{"type":"boolean","title":"Input","description":"Offending value (truncated); omitted for containers.","uniqueKey":"oneOf.0.errors.items.[INDEX].input.oneOf.2","typeLabel":"boolean"},{"type":"null","title":"Input","description":"Offending value (truncated); omitted for containers.","uniqueKey":"oneOf.0.errors.items.[INDEX].input.oneOf.3","typeLabel":"null"}],"uniqueKey":"oneOf.0.errors.items.[INDEX].input","typeLabel":"string | number | boolean | null"}},"required":["loc","msg","type"],"title":"FieldError","type":"object","uniqueKey":"oneOf.0.errors.items.[INDEX]","typeLabel":"FieldError · object"},"title":"Errors","type":"array","isRequired":true,"uniqueKey":"oneOf.0.errors","typeLabel":"FieldError · object[]"},"retryable":{"title":"Retryable","type":"boolean","isRequired":true,"uniqueKey":"oneOf.0.retryable","typeLabel":"boolean"},"status":{"title":"Status","type":"integer","isRequired":true,"uniqueKey":"oneOf.0.status","typeLabel":"integer"},"suggestions":{"items":{"type":"string","uniqueKey":"oneOf.0.suggestions.items.[INDEX]","typeLabel":"string"},"title":"Suggestions","type":"array","uniqueKey":"oneOf.0.suggestions","typeLabel":"string[]"}},"uniqueKey":"oneOf.0","typeLabel":"ValidationError · object"},{"type":"object","title":"Error","description":"Generic error envelope for 4xx/5xx responses other than request-shape validation.","required":["detail","request_id"],"properties":{"detail":{"oneOf":[{"type":"string","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","isRequired":true,"uniqueKey":"oneOf.1.detail.oneOf.0","typeLabel":"string"},{"type":"object","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","additionalProperties":true,"isRequired":true,"uniqueKey":"oneOf.1.detail.oneOf.1","typeLabel":"Detail · object"}],"isRequired":true,"uniqueKey":"oneOf.1.detail","typeLabel":"string | Detail · object"},"request_id":{"description":"Correlation id; identical to the `X-Request-Id` response header. Quote it in support requests.","title":"Request Id","type":"string","isRequired":true,"uniqueKey":"oneOf.1.request_id","typeLabel":"string"},"docs_url":{"description":"Link to this error's entry in the error catalog. Present whenever `detail` carries a registered `error_kind`; absent on unclassified errors.","title":"Docs Url","type":"string","uniqueKey":"oneOf.1.docs_url","typeLabel":"string"}},"uniqueKey":"oneOf.1","typeLabel":"Error · object"}],"uniqueKey":"","typeLabel":"ValidationError · object | Error · object"},"examples":{"Example":{"title":"Example","value":{"detail":"\u003cstring>","error":"\u003cstring>","error_code":"\u003cstring>","errors":[{"loc":["\u003cstring>"],"msg":"\u003cstring>","type":"\u003cstring>","allowed_values":["\u003cunknown>"],"input":"\u003cstring>"}],"retryable":true,"status":123,"suggestions":["\u003cstring>"]}}},"exampleType":"generated"}},"description":"Validation error. A request-shape failure uses the `ValidationError` envelope; a handler-raised domain-validation refusal uses the `Error` envelope.","headers":{"X-Request-Id":{"description":"Per-response correlation id, present on EVERY response (success and error). Error bodies echo it as `request_id`.","schema":{"type":"string"}},"x-ratelimit-limit":{"description":"Ceiling for the rate-limit window this request charged. Present on responses made with an API key against a rate-limited operation, including the `429` itself; absent for user access tokens (which carry no per-key budget) and when the rate-limit backend could not be read.","schema":{"type":"integer"}},"x-ratelimit-remaining":{"description":"Requests left in that window AFTER this one was counted. Pace off this rather than waiting for a `429`.","schema":{"type":"integer"}},"x-ratelimit-reset":{"description":"**Seconds from now** until that window resets (a delta, NOT a Unix timestamp). Measured when the response is written. Omitted on the rare occasion the reset instant could not be read, while `limit` and `remaining` are still published.","schema":{"type":"integer"}}},"exampleType":"generated"},"99ecf198-4699-4b49-a6a8-ac4ce1aa4d13":{"content":{"application/json":{"schema":{"description":"Generic error envelope for 4xx/5xx responses other than request-shape validation.","properties":{"detail":{"oneOf":[{"type":"string","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","isRequired":true,"uniqueKey":"detail.oneOf.0","typeLabel":"string"},{"type":"object","title":"Detail","description":"A human-readable message, OR a structured object carrying a machine-readable `error_kind` (e.g. `idempotency_conflict`, `turn_index_mismatch`, `decision_invalid`).","additionalProperties":true,"isRequired":true,"uniqueKey":"detail.oneOf.1","typeLabel":"Detail · object"}],"isRequired":true,"uniqueKey":"detail","typeLabel":"string | Detail · object"},"request_id":{"description":"Correlation id; identical to the `X-Request-Id` response header. Quote it in support requests.","title":"Request Id","type":"string","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"docs_url":{"description":"Link to this error's entry in the error catalog. Present whenever `detail` carries a registered `error_kind`; absent on unclassified errors.","title":"Docs Url","type":"string","uniqueKey":"docs_url","typeLabel":"string"}},"required":["detail","request_id"],"title":"Error","type":"object","uniqueKey":"","typeLabel":"Error · object"},"examples":{"Example":{"title":"Example","value":{"detail":"\u003cstring>","request_id":"\u003cstring>","docs_url":"\u003cstring>"}}},"exampleType":"generated"}},"description":"The API key's request rate limit is exceeded (`detail.error_kind = 'rate_limited'`). Transient: retry after the `Retry-After` interval, also echoed as `detail.retry_after_seconds`. Not applied to user access tokens.","headers":{"X-Request-Id":{"description":"Per-response correlation id, present on EVERY response (success and error). Error bodies echo it as `request_id`.","schema":{"type":"string"}},"x-ratelimit-limit":{"description":"Ceiling for the rate-limit window this request charged. Present on responses made with an API key against a rate-limited operation, including the `429` itself; absent for user access tokens (which carry no per-key budget) and when the rate-limit backend could not be read.","schema":{"type":"integer"}},"x-ratelimit-remaining":{"description":"Requests left in that window AFTER this one was counted. Pace off this rather than waiting for a `429`.","schema":{"type":"integer"}},"x-ratelimit-reset":{"description":"**Seconds from now** until that window resets (a delta, NOT a Unix timestamp). Measured when the response is written. Omitted on the rare occasion the reset instant could not be read, while `limit` and `remaining` are still published.","schema":{"type":"integer"}}},"exampleType":"generated"}},"security":{"63c05557-f0ce-4f81-ac7a-12db37c76322":{"bearerAuth":{"description":"Workspace API key as a bearer token: `Authorization: Bearer ish_sk_live_...`. Keys are workspace-scoped machine principals minted in Settings > Developers (shown once at mint). Scopes: `sessions:run` (create a session, submit turns, close), `sessions:read` (read the session and its decision trace), `environments:read` and `environments:write` (manage the workspace's registered environments), `tasks:read` and `tasks:write` (manage the workspace's registered tasks), `people:read` and `people:write` (the people the workspace can run a session for), and `usage:read` (the workspace's own consumption, spend limits and rate-limit budgets). A key is minted with `sessions:run`, `sessions:read`, and `tasks:read` by default; every other scope must be requested, `people:read` and `usage:read` included. An ish user access token also works on the same header for personal scripts.","scheme":"bearer","type":"http","scopes":[],"schemeName":"bearerAuth"}}},"servers":{"22c3a961-b6d9-4922-b5aa-d0aac292aa39":{"description":"Production","url":"https://api.ishlabs.io"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"description":"Workspace API key as a bearer token: `Authorization: Bearer ish_sk_live_...`. Keys are workspace-scoped machine principals minted in Settings > Developers (shown once at mint). Scopes: `sessions:run` (create a session, submit turns, close), `sessions:read` (read the session and its decision trace), `environments:read` and `environments:write` (manage the workspace's registered environments), `tasks:read` and `tasks:write` (manage the workspace's registered tasks), `people:read` and `people:write` (the people the workspace can run a session for), and `usage:read` (the workspace's own consumption, spend limits and rate-limit budgets). A key is minted with `sessions:run`, `sessions:read`, and `tasks:read` by default; every other scope must be requested, `people:read` and `usage:read` included. An ish user access token also works on the same header for personal scripts.","scheme":"bearer","type":"http","scopes":[],"schemeName":"bearerAuth"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"Workspace API key as a bearer token: `Authorization: Bearer ish_sk_live_...`. Keys are workspace-scoped machine principals minted in Settings > Developers (shown once at mint). Scopes: `sessions:run` (create a session, submit turns, close), `sessions:read` (read the session and its decision trace), `environments:read` and `environments:write` (manage the workspace's registered environments), `tasks:read` and `tasks:write` (manage the workspace's registered tasks), `people:read` and `people:write` (the people the workspace can run a session for), and `usage:read` (the workspace's own consumption, spend limits and rate-limit budgets). A key is minted with `sessions:run`, `sessions:read`, and `tasks:read` by default; every other scope must be requested, `people:read` and `usage:read` included. An ish user access token also works on the same header for personal scripts.","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"bearerAuth","name":"Authorization"}],"title":"bearerAuth"}]},"originalFileLocation":"api/openapi.public.json"},"subdomain":"ish","siteName":"ish","title":"Create Environment - ish","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-08T15:42:21.173Z","originalFileLocation":"api/reference/environments/create-environment.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=\"system\"}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=\"Register an environment: a named target sessions can be opened against. Supports the standard Idempotency-Key header, which is the mechanism to reach for in CI: a retry with the same key and body replays the original environment (200 instead of 201), and the same key with a different body is a 409 idempotency_conflict. get_or_create is the older, coarser flag and remains supported. Note what it does NOT do: on a name match it returns the EXISTING row untouched and IGNORES every other field on this request, so a request whose config has drifted from the stored one succeeds while changing nothing. Use Idempotency-Key for retry safety and PATCH to reconcile config.\">\u003cmeta data-mint-head name=\"application-name\" content=\"ish\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/ish/pQaVEm2sa1ahpXnl/_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/ish/pQaVEm2sa1ahpXnl/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/ish/pQaVEm2sa1ahpXnl/_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/ish/pQaVEm2sa1ahpXnl/_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/ish/pQaVEm2sa1ahpXnl/_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/ish/pQaVEm2sa1ahpXnl/_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/ish/pQaVEm2sa1ahpXnl/_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/ish/pQaVEm2sa1ahpXnl/_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/ish/pQaVEm2sa1ahpXnl/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Create Environment - ish\">\u003cmeta data-mint-head property=\"og:description\" content=\"Register an environment: a named target sessions can be opened against. Supports the standard Idempotency-Key header, which is the mechanism to reach for in CI: a retry with the same key and body replays the original environment (200 instead of 201), and the same key with a different body is a 409 idempotency_conflict. get_or_create is the older, coarser flag and remains supported. Note what it does NOT do: on a name match it returns the EXISTING row untouched and IGNORES every other field on this request, so a request whose config has drifted from the stored one succeeds while changing nothing. Use Idempotency-Key for retry safety and PATCH to reconcile config.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"ish\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.ishlabs.io/api/reference/environments/create-environment\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://ish.mintlify.site/_mintlify/api/og/v2?division=API+reference\u0026amp;title=Create+Environment\u0026amp;description=Register+an+environment%3A+a+named+target+sessions+can+be+opened+against.%0A%0ASupports+the+standard+%60Idempotency-Key%60+header%2C+which+is+the+mechanism+to%0Areach+for+in+\u0026amp;theme=e052e8dabadef59794361480\u0026amp;signature=6ac4fc97558cb1e820828474cae10d2d31392041f4feaec37210608068bca82f\">\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=\"Create Environment - ish\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Register an environment: a named target sessions can be opened against. Supports the standard Idempotency-Key header, which is the mechanism to reach for in CI: a retry with the same key and body replays the original environment (200 instead of 201), and the same key with a different body is a 409 idempotency_conflict. get_or_create is the older, coarser flag and remains supported. Note what it does NOT do: on a name match it returns the EXISTING row untouched and IGNORES every other field on this request, so a request whose config has drifted from the stored one succeeds while changing nothing. Use Idempotency-Key for retry safety and PATCH to reconcile config.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://ish.mintlify.site/_mintlify/api/og/v2?division=API+reference\u0026amp;title=Create+Environment\u0026amp;description=Register+an+environment%3A+a+named+target+sessions+can+be+opened+against.%0A%0ASupports+the+standard+%60Idempotency-Key%60+header%2C+which+is+the+mechanism+to%0Areach+for+in+\u0026amp;theme=e052e8dabadef59794361480\u0026amp;signature=6ac4fc97558cb1e820828474cae10d2d31392041f4feaec37210608068bca82f\">\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/ish/pQaVEm2sa1ahpXnl/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"ish\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#C8623F\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.ishlabs.io/api/reference/environments/create-environment\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api/reference/environments/create-environment.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.ishlabs.io/#organization\",\"name\":\"ish\",\"url\":\"https://docs.ishlabs.io\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/ish/4MaJn6-B7_NnPAml/logo/light.svg?fit=max\u0026auto=format\u0026n=4MaJn6-B7_NnPAml\u0026q=85\u0026s=f0edab6b74c19bec95794ee94d7270c2\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.ishlabs.io#website\",\"name\":\"ish\",\"url\":\"https://docs.ishlabs.io\",\"publisher\":{\"@id\":\"https://docs.ishlabs.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.ishlabs.io/api/reference/environments/create-environment#webpage\",\"url\":\"https://docs.ishlabs.io/api/reference/environments/create-environment\",\"name\":\"Create Environment\",\"description\":\"Register an environment: a named target sessions can be opened against. Supports the standard Idempotency-Key header, which is the mechanism to reach for in CI: a retry with the same key and body replays the original environment (200 instead of 201), and the same key with a different body is a 409 idempotency_conflict. get_or_create is the older, coarser flag and remains supported. Note what it does NOT do: on a name match it returns the EXISTING row untouched and IGNORES every other field on this request, so a request whose config has drifted from the stored one succeeds while changing nothing. Use Idempotency-Key for retry safety and PATCH to reconcile config.\",\"dateModified\":\"2026-10-08T15:42:21.173Z\",\"isPartOf\":{\"@id\":\"https://docs.ishlabs.io#website\"},\"breadcrumb\":{\"@id\":\"https://docs.ishlabs.io/api/reference/environments/create-environment#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.ishlabs.io/api/reference/environments/create-environment#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"API reference\",\"item\":\"https://docs.ishlabs.io/api/reference/introduction\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Create Environment\",\"item\":\"https://docs.ishlabs.io/api/reference/environments/create-environment\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.ishlabs.io/api/reference/environments/create-environment#apireference\",\"headline\":\"Create Environment\",\"name\":\"Create Environment\",\"description\":\"Register an environment: a named target sessions can be opened against. Supports the standard Idempotency-Key header, which is the mechanism to reach for in CI: a retry with the same key and body replays the original environment (200 instead of 201), and the same key with a different body is a 409 idempotency_conflict. get_or_create is the older, coarser flag and remains supported. Note what it does NOT do: on a name match it returns the EXISTING row untouched and IGNORES every other field on this request, so a request whose config has drifted from the stored one succeeds while changing nothing. Use Idempotency-Key for retry safety and PATCH to reconcile config.\",\"url\":\"https://docs.ishlabs.io/api/reference/environments/create-environment\",\"mainEntityOfPage\":{\"@id\":\"https://docs.ishlabs.io/api/reference/environments/create-environment#webpage\"},\"dateModified\":\"2026-10-08T15:42:21.173Z\",\"publisher\":{\"@id\":\"https://docs.ishlabs.io/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.ishlabs.io#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"ish\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"ish","nav":{"global":{"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/ishlabs"},{"anchor":"ishlabs.io","icon":"globe","href":"https://ishlabs.io"}]},"tabs":[{"tab":"Guides","pages":[{"title":"Guides","href":""}]},{"tab":"CLI Reference","pages":[{"title":"CLI Reference","href":"/cli/overview"}]},{"tab":"MCP Reference","pages":[{"title":"MCP Reference","href":"/mcp/overview"}]},{"tab":"API","groups":[{"group":"Get started","pages":[{"title":"The ish API","mode":"explanation","href":"/api/overview"},{"title":"Quickstart","mode":"tutorial","href":"/api/quickstart"},{"title":"Authentication","mode":"how-to","href":"/api/authentication"}]},{"group":"Core concepts","pages":[{"title":"Sessions and turns","mode":"explanation","href":"/api/concepts/sessions-and-turns"},{"title":"Observations","mode":"explanation","href":"/api/concepts/observations"},{"title":"The decide-only loop","mode":"explanation","href":"/api/concepts/decide-only-loop"},{"title":"Intent and resolution","mode":"explanation","href":"/api/concepts/intent-and-resolution"},{"title":"People","mode":"explanation","href":"/api/concepts/people"}]},{"group":"Guides","pages":[{"title":"Run the session loop","mode":"how-to","href":"/api/guides/session-loop"},{"title":"Author your environment","mode":"how-to","href":"/api/guides/environment-authoring"},{"title":"Score outcomes","mode":"how-to","href":"/api/guides/scoring-outcomes"},{"title":"Search people","mode":"how-to","href":"/api/guides/people-search"}]},{"group":"API reference","pages":[{"title":"API reference","mode":"reference","href":"/api/reference/introduction"},{"title":"Errors","mode":"reference","href":"/api/errors"},{"title":"Create Session","deprecated":null,"version":null,"openapi":"/api/openapi.public.json post /api/v1/workspaces/{workspace_id}/sessions","href":"/api/reference/sessions/create-session"},{"title":"List Sessions","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/workspaces/{workspace_id}/sessions","href":"/api/reference/sessions/list-sessions"},{"title":"Submit Turn","deprecated":null,"version":null,"openapi":"/api/openapi.public.json post /api/v1/sessions/{session_id}/turns","href":"/api/reference/sessions/submit-turn"},{"title":"Get Session","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/sessions/{session_id}","href":"/api/reference/sessions/get-session"},{"title":"Close Session","description":"Close an open session and return it (idempotent on an already-closed one).\n\nA POST on a `/close` subresource rather than `DELETE /sessions/{id}`:\nclosing is a state TRANSITION that settles the session's turns and leaves a\nreadable record, not a removal. DELETE promised an erasure this route never\nperformed, and it had no honest way to return the closed session's body.","deprecated":null,"version":null,"openapi":"/api/openapi.public.json post /api/v1/sessions/{session_id}/close","href":"/api/reference/sessions/close-session"},{"title":"Create Environment","deprecated":null,"version":null,"openapi":"/api/openapi.public.json post /api/v1/workspaces/{workspace_id}/environments","href":"/api/reference/environments/create-environment"},{"title":"List Environments","description":"Every LIVE environment registered in this workspace, oldest first.\n\nArchived environments are excluded unless `include_archived=true`; they stay\nindividually readable by id either way.\n\nAPI keys do not see console-owned kinds (`chatbot` environments, which the\nchat federation writes and the console renders as read-only mirrors). They\nare not developer-registerable, so listing them to an integrator would offer\nrows no key can act on.","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/workspaces/{workspace_id}/environments","href":"/api/reference/environments/list-environments"},{"title":"Get Environment","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/environments/{environment_id}","href":"/api/reference/environments/get-environment"},{"title":"Update Environment","deprecated":null,"version":null,"openapi":"/api/openapi.public.json patch /api/v1/environments/{environment_id}","href":"/api/reference/environments/update-environment"},{"title":"Delete Environment","deprecated":null,"version":null,"openapi":"/api/openapi.public.json delete /api/v1/environments/{environment_id}","href":"/api/reference/environments/delete-environment"},{"title":"Create Environment Version","deprecated":null,"version":null,"openapi":"/api/openapi.public.json post /api/v1/environments/{environment_id}/versions","href":"/api/reference/environments/create-environment-version"},{"title":"List Environment Versions","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/environments/{environment_id}/versions","href":"/api/reference/environments/list-environment-versions"},{"title":"Get Environment Version","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/environment-versions/{version_id}","href":"/api/reference/environments/get-environment-version"},{"title":"Update Environment Version","deprecated":null,"version":null,"openapi":"/api/openapi.public.json patch /api/v1/environment-versions/{version_id}","href":"/api/reference/environments/update-environment-version"},{"title":"Delete Environment Version","deprecated":null,"version":null,"openapi":"/api/openapi.public.json delete /api/v1/environment-versions/{version_id}","href":"/api/reference/environments/delete-environment-version"},{"title":"Set Default Environment Version","deprecated":null,"version":null,"openapi":"/api/openapi.public.json post /api/v1/environment-versions/{version_id}/set-default","href":"/api/reference/environments/set-default-environment-version"},{"title":"Create Task","deprecated":null,"version":null,"openapi":"/api/openapi.public.json post /api/v1/workspaces/{workspace_id}/tasks","href":"/api/reference/tasks/create-task"},{"title":"List Tasks","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/workspaces/{workspace_id}/tasks","href":"/api/reference/tasks/list-tasks"},{"title":"Get Task","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/tasks/{task_id}","href":"/api/reference/tasks/get-task"},{"title":"Update Task","deprecated":null,"version":null,"openapi":"/api/openapi.public.json patch /api/v1/tasks/{task_id}","href":"/api/reference/tasks/update-task"},{"title":"Delete Task","deprecated":null,"version":null,"openapi":"/api/openapi.public.json delete /api/v1/tasks/{task_id}","href":"/api/reference/tasks/delete-task"},{"title":"List People","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/workspaces/{workspace_id}/people","href":"/api/reference/people/list-people"},{"title":"Search People","deprecated":null,"version":null,"openapi":"/api/openapi.public.json post /api/v1/workspaces/{workspace_id}/people/search","href":"/api/reference/people/search-people"},{"title":"Get Person","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/workspaces/{workspace_id}/people/{person_id}","href":"/api/reference/people/get-person"},{"title":"Get People Counts","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/workspaces/{workspace_id}/people/counts","href":"/api/reference/people/get-people-counts"},{"title":"Get People Schema","deprecated":null,"version":null,"openapi":"/api/openapi.public.json get /api/v1/workspaces/{workspace_id}/people/schema","href":"/api/reference/people/get-people-schema"}]},{"group":"Versioning and changes","pages":[{"title":"Versioning and deprecation","mode":"reference","href":"/api/versioning"},{"title":"Changelog","mode":"reference","href":"/api/changelog"}]}]},{"tab":"Help","pages":[{"title":"Help","href":"/help/troubleshooting"}]}]},"basePath":"","title":"Create Environment - ish","buildId":"dpl_42LwxxU1kGN114H4XzwGYXa9ZDah","deploymentId":"dpl_42LwxxU1kGN114H4XzwGYXa9ZDah","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-C-hEh3I2.js","utils-CnF4QiUD.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-C7PVNbel.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-8ytevL2A.js","snippetPresets-BT1alx3v.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","conditional-requirements-CFM0id0Q.js","ApiExamples-BLXC0i_W.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-CyLIGI9_.js","shallow-DC0lGVIW.js","getApiPlaygroundDisplay-CgDQ85tN.js","CodeSnippet-6-I-Gpv9.js","CodeSnippets-BAk1kDdu.js","Page-C945cI-W.js","getPastedJson-B276RuWN.js","icon-BqP8etTm.js","MethodPill-DM6sbxG1.js","DuplicateIcon-PyJglOaE.js","createIcon-CMeOMAc_.js","DynamicMarkdown-BoyYAA8K.js","SectionHeading-DAYv3gvZ.js","axios-vUo_bRtp.js","Markdown-BhTTmazV.js","clsx-CR-RHrVC.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-CBUH0-zX.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-BmARFYNC.js"]}