Manifest
Validate, plan, apply and export guv.yaml.
| Operation | Method and path |
|---|---|
| Export live state as guv.yaml (pull / eject) | GET /v1/projects/{project}/manifest |
| Manifest management and drift status | GET /v1/projects/{project}/manifest/status |
| Validate guv.yaml (schema, references, policy) | POST /v1/projects/{project}/manifest/validate |
| Plan guv.yaml against live state | POST /v1/projects/{project}/manifest/plan |
| Apply a plan | POST /v1/projects/{project}/manifest/apply |
Export live state as guv.yaml (pull / eject)
Section titled “Export live state as guv.yaml (pull / eject)”GET /v1/projects/{project}/manifestAccept: application/yaml returns the file itself.
- Operation:
exportManifest - Scopes:
projects:read - CLI:
guv pull
Parameters
| Name | In | Type | Description |
|---|---|---|---|
project * |
path | string | Project id (prj_…) or slug (resolved in the Guv-Workspace workspace, or the caller’s default). |
environment |
query | string |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. | ManifestExport |
Errors: 400, 401, 403, 404, 429, 500, as problem+json with a stable code.
Example
curl https://api.guv.dev/v1/projects/shopfront/manifest \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "manifest": "string", "generated_at": "2026-10-22T13:05:00Z"}Manifest management and drift status
Section titled “Manifest management and drift status”GET /v1/projects/{project}/manifest/status- Operation:
getManifestStatus - Scopes:
projects:read
Parameters
| Name | In | Type | Description |
|---|---|---|---|
project * |
path | string | Project id (prj_…) or slug (resolved in the Guv-Workspace workspace, or the caller’s default). |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. | ManifestStatus |
Errors: 400, 401, 403, 404, 429, 500, as problem+json with a stable code.
Example
curl https://api.guv.dev/v1/projects/shopfront/manifest/status \ -H "Authorization: Bearer $GUV_TOKEN"Example response
{ "managed_by_manifest": false, "source": { "repo": "string", "path": "string", "commit": "string" }, "last_applied": { "plan_hash": "string", "at": "2026-10-22T13:05:00Z", "by": { "type": "agent", "id": "tok_01jbx2m9k7q4r8t5v6w3y0z1tk", "display": "Stewart Webb via agent claude-code-on-stewart-laptop", "via_agent": { "id": "tok_01jbx2m9k7q4r8t5v6w3y0z1tk", "name": "claude-code-on-stewart-laptop" }, "on_behalf_of": { "id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us", "display": "Stewart Webb" } }, "operation_id": "string" }, "drift": { "detected": false, "checked_at": "2026-10-22T13:05:00Z", "changes": [ { "action": "create", "resource": { "type": "service", "id": "svc_01jbx2m9k7q4r8t5v6w3y0z1sv", "name": "web", "url": "/v1/projects/primecarers/services/web" }, "environment": "production", "summary": "Create Postgres 18 database main (HA, 50 GB, 30 days point-in-time recovery)", "diff": [ {} ], "destructive": false, "requires_approval": false, "reason": "string" } ] }}Validate guv.yaml (schema, references, policy)
Section titled “Validate guv.yaml (schema, references, policy)”POST /v1/projects/{project}/manifest/validate- Operation:
validateManifest - Scopes:
projects:read - CLI:
guv validate - Idempotency-Key: optional
Parameters
| Name | In | Type | Description |
|---|---|---|---|
project * |
path | string | Project id (prj_…) or slug (resolved in the Guv-Workspace workspace, or the caller’s default). |
Request body (application/json, required): ManifestInput
| Field | Type | Description |
|---|---|---|
manifest * |
string | The guv.yaml text (YAML or JSON). |
files |
map of string to string | Extra files referenced by include (path to content). |
environment |
string | Limit the plan to one environment. |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. | ManifestValidation |
Errors: 400, 401, 403, 404, 409, 422, 429, 500, as problem+json with a stable code.
Example
curl -X POST https://api.guv.dev/v1/projects/shopfront/manifest/validate \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "manifest": "string", "files": { "key": "string" }, "environment": "string"}'Example response
{ "valid": false, "errors": [ { "path": "/services/web/port", "line": 1, "column": 1, "code": "secret_missing", "message": "string", "fix": "string", "severity": "error" } ], "warnings": [ { "path": "/services/web/port", "line": 1, "column": 1, "code": "secret_missing", "message": "string", "fix": "string", "severity": "error" } ], "schema_version": "1"}Plan guv.yaml against live state
Section titled “Plan guv.yaml against live state”POST /v1/projects/{project}/manifest/planNever changes anything. Returns the diff, cost delta, policy decision and the plan_hash to apply.
- Operation:
planManifest - Scopes:
projects:read - CLI:
guv plan - Idempotency-Key: optional
Parameters
| Name | In | Type | Description |
|---|---|---|---|
project * |
path | string | Project id (prj_…) or slug (resolved in the Guv-Workspace workspace, or the caller’s default). |
Request body (application/json, required): ManifestInput
| Field | Type | Description |
|---|---|---|
manifest * |
string | The guv.yaml text (YAML or JSON). |
files |
map of string to string | Extra files referenced by include (path to content). |
environment |
string | Limit the plan to one environment. |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
OK. | Plan |
Errors: 400, 401, 403, 404, 409, 422, 429, 500, as problem+json with a stable code.
Example
curl -X POST https://api.guv.dev/v1/projects/shopfront/manifest/plan \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "manifest": "string", "files": { "key": "string" }, "environment": "string"}'Example response
{ "plan_hash": "sha256:9f2c1e0b7a4d3c2b1a09f8e7d6c5b4a39281706f5e4d3c2b1a0f9e8d7c6b5a49", "dry_run": true, "summary": "1 to update. +£5.00/month at current usage.", "changes": [ { "action": "update", "resource": { "type": "service", "id": "svc_01jbx2m9k7q4r8t5v6w3y0z1sv", "name": "web" }, "environment": "production", "summary": "Raise web memory limit from 1 GB to 2 GB", "diff": [ { "path": "/resources/memory_mb", "before": 1024, "after": 2048 } ], "destructive": false, "requires_approval": true, "reason": "production requires approval for changes made by agents" } ], "cost": { "current_monthly": { "amount": "18.20", "currency": "GBP", "display": "£18.20" }, "projected_monthly": { "amount": "23.20", "currency": "GBP", "display": "£23.20" }, "delta_monthly": { "amount": "5.00", "currency": "GBP", "display": "£5.00" }, "confidence": "medium" }, "policy": { "decision": "approval_required", "reasons": [ { "code": "environment_protected", "message": "production requires approval for changes made by agents", "policy": "guv.environment.protection" } ], "approver_roles": [ "owner", "admin" ] }, "requires_approval": true, "expires_at": "2026-10-23T15:00:00Z"}Apply a plan
Section titled “Apply a plan”POST /v1/projects/{project}/manifest/applyThe plan_hash must match a fresh plan of the same manifest; otherwise 409 plan_hash_mismatch. The plan hash doubles as the idempotency key of the apply operation.
- Operation:
applyManifest - Scopes:
manifest:apply - CLI:
guv apply - Approval: In environments with protection turned on (usually production), changes by agents and by roles outside
approver_rolesreturnapproval_required. - Idempotency-Key: required; supports
?dry_run=true
Parameters
| Name | In | Type | Description |
|---|---|---|---|
project * |
path | string | Project id (prj_…) or slug (resolved in the Guv-Workspace workspace, or the caller’s default). |
Request body (application/json, required): ManifestApplyRequest
| Field | Type | Description |
|---|---|---|
manifest * |
string | The guv.yaml text (YAML or JSON). |
files |
map of string to string | Extra files referenced by include (path to content). |
environment |
string | Limit the plan to one environment. |
plan_hash * |
string | Must match a plan made from the same manifest and the current live state, or the call fails with plan_hash_mismatch. |
Responses
| Status | Meaning | Body |
|---|---|---|
200 OK |
Dry run. Nothing was changed; this is what would happen. | Plan |
202 Accepted |
Accepted. The work continues in the background; follow the operation. | Operation |
Errors: 400, 401, 402, 403, 404, 409, 422, 429, 500, as problem+json with a stable code.
Example
curl -X POST https://api.guv.dev/v1/projects/shopfront/manifest/apply \ -H "Authorization: Bearer $GUV_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "manifest": "string", "files": { "key": "string" }, "environment": "string", "plan_hash": "string"}'Example response
{ "id": "op_01jbx2m9k7q4r8t5v6w3y0z1op", "kind": "deployment.create", "status": "running", "summary": "Deploying web to production", "workspace_id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws", "project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr", "environment_id": "env_01jbx2m9k7q4r8t5v6w3y0z1en", "resource": { "type": "deployment", "id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp", "url": "/v1/deployments/dep_01jbx2m9k7q4r8t5v6w3y0z1dp" }, "progress": { "current_step": "build", "completed_steps": 1, "total_steps": 6, "percent": 20 }, "steps": [ { "name": "resolve", "title": "Reading your settings", "status": "succeeded", "attempt": 1, "started_at": "2026-10-23T14:02:00Z", "finished_at": "2026-10-23T14:02:01Z" }, { "name": "build", "title": "Building your app", "status": "running", "attempt": 1, "started_at": "2026-10-23T14:02:01Z", "finished_at": null } ], "created_by": { "type": "user", "id": "usr_01jbx2m9k7q4r8t5v6w3y0z1us", "display": "Stewart Webb" }, "created_at": "2026-10-23T14:02:00Z", "links": { "self": "/v1/operations/op_01jbx2m9k7q4r8t5v6w3y0z1op", "events": "/v1/operations/op_01jbx2m9k7q4r8t5v6w3y0z1op/events", "resource": "/v1/deployments/dep_01jbx2m9k7q4r8t5v6w3y0z1dp" }}