Save the shared visual layout
Developer, admin or owner required, including in protected environments because this changes visual state only. Replaces all saved positions and viewport for the selected scope. A stale revision returns 409 canvas_revision_conflict; GET the latest canvas before retrying. Unknown or no-longer-visible node IDs return 400 canvas_invalid_node. Unknown scope parameters, duplicate/empty scope values and unsupported fields are rejected. Maximum request body is 256 KiB. Uses optimistic revision control, not Idempotency-Key replay.
Kept in memory for this page. Requests go through this documentation site to the live Openstead API and can change your workspace. Use a read-only key to explore read operations.
Developer, admin or owner required, including in protected environments because this changes visual state only. Replaces all saved positions and viewport for the selected scope. A stale revision returns 409 canvas_revision_conflict; GET the latest canvas before retrying. Unknown or no-longer-visible node IDs return 400 canvas_invalid_node. Unknown scope parameters, duplicate/empty scope values and unsupported fields are rejected. Maximum request body is 256 KiB. Uses optimistic revision control, not Idempotency-Key replay.
Workspace-scoped rnv_ API key. Read scope allows GET; write scope is additionally constrained by current membership, role, email verification, expiry and workspace MFA policy.
In: header
Path Parameters
Workspace UUID; it must match the bearer key scope.
uuidQuery Parameters
Optional project in this workspace; omit for all workspace services.
uuidOptional environment; requires projectId and must belong to that project.
uuidHeader Parameters
Optional correlation identifier; invalid values are replaced. The accepted/generated value is returned in X-Request-ID and error body requestId. This is not an idempotency key.
^[A-Za-z0-9][A-Za-z0-9._-]*$length <= 64Required on browser-session writes: obtain csrfToken from /api/bootstrap and retain its cookies. Not required for a validated bearer key.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Replace the visual layout for this scope using its current revision. Empty positions and null viewport reset the layout. Node IDs must be present in the current canvas. No connection, service or infrastructure configuration is changed.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PATCH "https://api.openstead.tech/api/v1/workspaces/497f6eca-6276-4993-bfeb-53cbbbba6f08/canvas" \ -H "Authorization: Bearer <OPENSTEAD_API_KEY>" \ -H "Content-Type: application/json" \ -d '{ "positions": {}, "revision": 0, "viewport": null }'{ "edges": [ { "id": "string", "keys": [ "string" ], "kind": "reference", "source": "string", "target": "string" } ], "groups": [ { "environmentId": "19f5cc2e-7657-437a-9268-83cd3d563563", "id": "string", "name": "string", "serviceIds": [ "a486dd3f-c8ab-4226-b78c-e435f821cb91" ] } ], "layout": { "positions": { "property1": { "x": -10000000, "y": -10000000 }, "property2": { "x": -10000000, "y": -10000000 } }, "revision": 0, "viewport": { "x": -10000000, "y": -10000000, "zoom": 0.1 } }, "nodes": [ { "archived": true, "configuration": { "autoDeploy": "off", "backupEnabled": true, "backupRetentionDays": 7, "branch": "main", "buildCommand": "", "buildMethod": "railpack", "cacheProfile": "none", "databaseName": "", "databaseUser": "", "databaseVersion": "16", "description": "", "dockerContext": ".", "dockerfilePath": "Dockerfile", "evictionPolicy": "allkeys-lru", "healthCheckPath": "", "ignorePaths": [], "image": "", "includePaths": [], "ipAllowList": [], "maintenance": false, "maintenancePage": "", "maxConcurrency": 1, "maxReplicas": 3, "maxRetries": 3, "minReplicas": 1, "notifications": "workspace", "plan": "free", "platformDomainEnabled": true, "port": 8000, "preDeployCommand": "", "previewExpiryHours": 72, "previewMode": "off", "privateNetworking": true, "publishDirectory": "dist", "region": "auto", "registryId": "", "replicas": 1, "repository": "", "rootDirectory": "", "runtime": "auto", "scaling": "manual", "schedule": "0 * * * *", "sourceType": "repository", "startCommand": "", "targetCpu": 70, "targetMemory": 80, "timeoutSeconds": 3600, "timezone": "UTC" }, "createdAt": "2019-08-24T14:15:22Z", "deletedAt": "2019-08-24T14:15:22Z", "deletionRequestedAt": "2019-08-24T14:15:22Z", "deploymentId": "a73c85a1-d857-491e-a6b2-51dce05de7a2", "deploymentUpdatedAt": "2019-08-24T14:15:22Z", "displayStatus": "string", "environmentGroupIds": [ "92fbde13-991c-42dc-b79d-8aae32b12bd2" ], "environmentId": "19f5cc2e-7657-437a-9268-83cd3d563563", "estimatedMonthly": { "ngn": 0, "priced": true, "usd": 0 }, "healthCheckedAt": "2019-08-24T14:15:22Z", "healthStatus": "ready", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "internalHost": "string", "kind": "static", "lifecycleStatus": "string", "liveDeploymentId": "4f10cf15-3de3-4eba-b208-7afcb8afd71d", "name": "string", "projectId": "5a8591dd-4039-49df-9202-96385ba3eff8", "runtimeDetail": "string", "status": "string", "updatedAt": "2019-08-24T14:15:22Z", "url": "string" } ], "scope": { "environmentId": "19f5cc2e-7657-437a-9268-83cd3d563563", "projectId": "5a8591dd-4039-49df-9202-96385ba3eff8" }}Get scoped service topology and shared layout GET
Readers can view the workspace, one project across its environments, or one project environment. Only active service records and valid scoped reference/group connections are shown; archived and deleting/deleted services are excluded. Manual secret values are never inspected. Layouts are independent per scope. Unsaved layouts have revision 0. No pagination or silent truncation: scopes beyond 2000 total nodes or 10000 reference records/edges return 413 canvas_too_large.
List projects GET
Legacy requests without limit/cursor return the complete list. Opt in to bounded pages with limit or cursor.