# Versions and edits An app’s version history, comparing two versions as permission facts, rolling back, and changing an app by a sentence. 6 routes, from the API’s own OpenAPI document. URL: https://docs.qaldy.com/reference/api/versions/ 6 routes. Every path starts at `https://cloud-api.qaldy.com`. Sign-in, tokens, errors and limits are on the [overview](https://docs.qaldy.com/reference/api/). ## Routes | Method | Path | What it does | |---|---|---| | [[POST]] | [`/​v1/​apps/​{id}/​changes`](#post-v1-apps-id-changes) | Plan a change to an app from a sentence: the permission diff, nothing built yet | | [[GET]] | [`/​v1/​apps/​{id}/​versions`](#get-v1-apps-id-versions) | An app’s versions, newest first, and its rollbacks | | [[POST]] | [`/​v1/​apps/​{id}/​versions/​{versionId}/​rollback`](#post-v1-apps-id-versions-versionid-rollback) | Go back to an older version: one pointer move, no rebuild | | [[GET]] | [`/​v1/​apps/​{id}/​versions/​compare`](#get-v1-apps-id-versions-compare) | What one version may do that another could not, in permission sentences | | [[GET]] | [`/​v1/​changes/​{changeId}`](#get-v1-changes-changeid) | Where a change is: planned, building, live or failed | | [[POST]] | [`/​v1/​changes/​{changeId}/​approve`](#post-v1-changes-changeid-approve) | Approve a planned change: the new version is written and the app moves to it | ## Reference ### [[POST]] `/v1/apps/{id}/changes` Plan a change to an app from a sentence: the permission diff, nothing built yet. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `write` scope. - **Who:** `can_edit` | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) | Field | Type | Required | Notes | |---|---|---|---| | `instruction` | string | yes | 4 to 2000 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `changeId` | string | yes | at least 1 characters | | `appId` | string | yes | at least 1 characters | | `appName` | string | yes | at least 1 characters | | `baseVersionId` | string | yes | at least 1 characters | | `instruction` | string | yes | | | `summary` | string | yes | 1 to 300 characters | | `manifest` | object | yes | | | `manifest.name` | string | yes | 2 to 60 characters | | `manifest.description` | string | yes | 4 to 280 characters | | `manifest.archetype` | "kiosk" · "tower" · "warehouse" · "workshop" · "bank" · "townhall" · "clocktower" · "printhouse" · … | yes | | | `manifest.category` | "interface" · "data" · "messaging" · "money" · "ai" · "time" · "people" · "growth" | yes | | | `manifest.permissions` | object | yes | | | `manifest.triggers` | object[] | yes | | | `manifest.sharing` | object | yes | | | `manifest.roi` | object | yes | | | `diff` | object | yes | | | `diff.gains` | object[] | yes | | | `diff.losses` | object[] | yes | | | `diff.triggersAdded` | object[] | yes | | | `diff.triggersRemoved` | object[] | yes | | | `diff.details` | object[] | yes | | | `steps` | string[] | yes | | | `rebuildsCode` | boolean | yes | | | `builder` | "claude" · "offline" | yes | | | `model` | string or null | yes | | | `templateId` | string or null | yes | | | `notes` | string[] | yes | up to 8 items | | `adminApproval` | object | yes | | | `adminApproval.required` | boolean | yes | | | `adminApproval.connectors` | string[] | yes | | …and 2 more fields. The full schema is in [openapi.json](https://docs.qaldy.com/openapi.json). Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/apps/{id}/versions` An app’s versions, newest first, and its rollbacks. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** `can_view` | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `appId` | string | yes | at least 1 characters | | `currentVersionId` | string or null | yes | | | `versions` | object[] | yes | | | `versions[].id` | string | yes | at least 1 characters | | `versions[].appId` | string | yes | at least 1 characters | | `versions[].number` | integer | yes | at least 1 | | `versions[].createdAt` | string (date-time) | yes | | | `versions[].createdBy` | string | yes | at least 1 characters | | `versions[].createdByName` | string or null | yes | | | `versions[].bundleHash` | string | yes | at least 1 characters | | `versions[].trustScore` | integer | yes | 0 to 100 | | `versions[].trustBand` | "pass" · "review" · "fail" | yes | | | `versions[].kind` | "build" · "edit" · "seed" | yes | | | `versions[].summary` | string | yes | 1 to 300 characters | | `versions[].instruction` | string or null | yes | | | `versions[].baseVersionId` | string or null | yes | | | `versions[].isCurrent` | boolean | yes | | | `versions[].runnable` | boolean | yes | | | `versions[].builder` | "claude" · "offline" · null or null | yes | | | `rollbacks` | object[] | yes | | | `rollbacks[].at` | string (date-time) | yes | | | `rollbacks[].byName` | string or null | yes | | | `rollbacks[].fromVersionId` | string | yes | at least 1 characters | | `rollbacks[].toVersionId` | string | yes | at least 1 characters | | `canEdit` | boolean | yes | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[POST]] `/v1/apps/{id}/versions/{versionId}/rollback` Go back to an older version: one pointer move, no rebuild. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `write` scope. - **Who:** `can_edit` | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | | `versionId` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) | Field | Type | Required | Notes | |---|---|---|---| | `expectCurrentVersionId` | string | yes | at least 1 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `appId` | string | yes | at least 1 characters | | `fromVersionId` | string | yes | at least 1 characters | | `toVersionId` | string | yes | at least 1 characters | | `trustScore` | integer | yes | 0 to 100 | | `diff` | object | yes | | | `diff.gains` | object[] | yes | | | `diff.losses` | object[] | yes | | | `diff.triggersAdded` | object[] | yes | | | `diff.triggersRemoved` | object[] | yes | | | `diff.details` | object[] | yes | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/apps/{id}/versions/compare` What one version may do that another could not, in permission sentences. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** `can_view` | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `id` | path | string | yes | 1 to 128 characters | | `to` | query | string | yes | 1 to 128 characters | | `from` | query | string | | 1 to 128 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `from` | object | yes | | | `from.id` | string | yes | at least 1 characters | | `from.appId` | string | yes | at least 1 characters | | `from.number` | integer | yes | at least 1 | | `from.createdAt` | string (date-time) | yes | | | `from.createdBy` | string | yes | at least 1 characters | | `from.createdByName` | string or null | yes | | | `from.bundleHash` | string | yes | at least 1 characters | | `from.trustScore` | integer | yes | 0 to 100 | | `from.trustBand` | "pass" · "review" · "fail" | yes | | | `from.kind` | "build" · "edit" · "seed" | yes | | | `from.summary` | string | yes | 1 to 300 characters | | `from.instruction` | string or null | yes | | | `from.baseVersionId` | string or null | yes | | | `from.isCurrent` | boolean | yes | | | `from.runnable` | boolean | yes | | | `from.builder` | "claude" · "offline" · null or null | yes | | | `to` | object | yes | | | `to.id` | string | yes | at least 1 characters | | `to.appId` | string | yes | at least 1 characters | | `to.number` | integer | yes | at least 1 | | `to.createdAt` | string (date-time) | yes | | | `to.createdBy` | string | yes | at least 1 characters | | `to.createdByName` | string or null | yes | | | `to.bundleHash` | string | yes | at least 1 characters | | `to.trustScore` | integer | yes | 0 to 100 | | `to.trustBand` | "pass" · "review" · "fail" | yes | | | `to.kind` | "build" · "edit" · "seed" | yes | | | `to.summary` | string | yes | 1 to 300 characters | | `to.instruction` | string or null | yes | | …and 8 more fields. The full schema is in [openapi.json](https://docs.qaldy.com/openapi.json). Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[GET]] `/v1/changes/{changeId}` Where a change is: planned, building, live or failed. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `read` scope. - **Who:** plan's owner | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `changeId` | path | string | yes | 1 to 128 characters | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `changeId` | string | yes | at least 1 characters | | `appId` | string | yes | at least 1 characters | | `state` | "planned" · "building" · "live" · "failed" · "expired" | yes | | | `message` | string or null | yes | | | `versionId` | string or null | yes | | | `trustScore` | integer or null | yes | 0 to 100 | | `stage` | string or null | yes | | | `plan` | object or null | | | | `plan.changeId` | string | yes | at least 1 characters | | `plan.appId` | string | yes | at least 1 characters | | `plan.appName` | string | yes | at least 1 characters | | `plan.baseVersionId` | string | yes | at least 1 characters | | `plan.instruction` | string | yes | | | `plan.summary` | string | yes | 1 to 300 characters | | `plan.manifest` | object | yes | | | `plan.diff` | object | yes | | | `plan.steps` | string[] | yes | | | `plan.rebuildsCode` | boolean | yes | | | `plan.builder` | "claude" · "offline" | yes | | | `plan.model` | string or null | yes | | | `plan.templateId` | string or null | yes | | | `plan.notes` | string[] | yes | up to 8 items | | `plan.adminApproval` | object | yes | | | `plan.needsConsole` | string[] | yes | | | `plan.expiresAt` | string (date-time) | yes | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)). ### [[POST]] `/v1/changes/{changeId}/approve` Approve a planned change: the new version is written and the app moves to it. - **Authentication:** the console’s session cookie. - **Token:** a personal access token or an MCP sign-in with the `write` scope. - **Who:** plan's owner with `can_edit`; over a token only inside the safe band | Parameter | In | Type | Required | Notes | |---|---|---|---|---| | `changeId` | path | string | yes | 1 to 128 characters | **Request body** (`application/json`) | Field | Type | Required | Notes | |---|---|---|---| | `manifest` | object | yes | | | `manifest.name` | string | yes | 2 to 60 characters | | `manifest.description` | string | yes | 4 to 280 characters | | `manifest.archetype` | "kiosk" · "tower" · "warehouse" · "workshop" · "bank" · "townhall" · "clocktower" · "printhouse" · … | yes | | | `manifest.category` | "interface" · "data" · "messaging" · "money" · "ai" · "time" · "people" · "growth" | yes | | | `manifest.permissions` | object | yes | | | `manifest.permissions.data` | object[] | yes | | | `manifest.permissions.connectors` | object[] | yes | | | `manifest.permissions.egress` | object[] | yes | | | `manifest.permissions.ai` | object or null | yes | | | `manifest.triggers` | object[] | yes | | | `manifest.sharing` | object | yes | | | `manifest.sharing.default` | "private" · "team" · "workspace" | yes | | | `manifest.roi` | object | yes | | | `manifest.roi.manualMinutesPerRun` | number | yes | 0 to 1440 | **Response 200** | Field | Type | Required | Notes | |---|---|---|---| | `changeId` | string | yes | at least 1 characters | | `appId` | string | yes | at least 1 characters | | `state` | "planned" · "building" · "live" · "failed" · "expired" | yes | | | `message` | string or null | yes | | | `versionId` | string or null | yes | | | `trustScore` | integer or null | yes | 0 to 100 | | `stage` | string or null | yes | | | `plan` | object or null | | | | `plan.changeId` | string | yes | at least 1 characters | | `plan.appId` | string | yes | at least 1 characters | | `plan.appName` | string | yes | at least 1 characters | | `plan.baseVersionId` | string | yes | at least 1 characters | | `plan.instruction` | string | yes | | | `plan.summary` | string | yes | 1 to 300 characters | | `plan.manifest` | object | yes | | | `plan.diff` | object | yes | | | `plan.steps` | string[] | yes | | | `plan.rebuildsCode` | boolean | yes | | | `plan.builder` | "claude" · "offline" | yes | | | `plan.model` | string or null | yes | | | `plan.templateId` | string or null | yes | | | `plan.notes` | string[] | yes | up to 8 items | | `plan.adminApproval` | object | yes | | | `plan.needsConsole` | string[] | yes | | | `plan.expiresAt` | string (date-time) | yes | | Errors: `400`, `401`, `403`, `404`, `409`, `429` (the error format is on the [overview](https://docs.qaldy.com/reference/api/#errors)).