# Restore a previous version of a workflow

`POST /v1/workflows/{id}/versions/{version}/restore`

- Authentication: required (Bearer token)
- Required scope: `api.workflows.manage`

Reinstates a previous definition. A restore is an ordinary edit whose
content happens to be old: it snapshots the state it replaces in the
same transaction, so nothing is lost, the restore is itself in the
history, and restoring the version it created undoes it. That is why
this operation is NOT classified destructive, and why a
test-environment credential may call it.

It bypasses the optimistic-concurrency check by design — "whatever is
there now, make it this" is not a statement about what the caller last
read — and it deletes no history.

A restore does NOT change the workflow's status and does not cancel,
re-enrol or re-version its in-flight runs: each run keeps the version
it enrolled under. Restoring a source under an active workflow is a
live edit, exactly as an ordinary update of the same workflow is.

## Path parameters

- `id` (string, required) — The workflow's UUID or its org-unique key.
- `version` (integer, required) — The version number, as returned by the versions collection. Version numbers are the handle on every kind here, including the kinds whose dashboard routes address a version by row id.

## Example request

```bash
curl -X POST 'https://api.sendops.dev/v1/workflows/string/versions/0/restore' \
  -H "Authorization: Bearer $SENDOPS_API_KEY"
```

## Responses

### 200 — The definition after the restore, and the version the restore created

Content type: `application/json`

```json
{
  "kind": "string",
  "restored": 0,
  "current": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "string",
    "key": "string",
    "description": "string",
    "status": "string",
    "invalid_reason": "string",
    "require_send_approval": true,
    "send_mode": "live",
    "shadow_started_at": "2026-05-17T20:00:00Z",
    "shadow_cohort_list_id": "00000000-0000-0000-0000-000000000000",
    "shadow_cohort": {
      "id": "00000000-0000-0000-0000-000000000000",
      "key": "string",
      "name": "string",
      "member_count": 0
    },
    "current_version": 0,
    "run_counts": {},
    "created_at": "2026-05-17T20:00:00Z",
    "updated_at": "2026-05-17T20:00:00Z",
    "source": "string",
    "content_hash": "string",
    "warnings": [
      "string"
    ],
    "diagnostics": [
      {
        "line": 0,
        "column": 0,
        "severity": "string",
        "message": "string"
      }
    ],
    "requires": [
      {
        "kind": "template",
        "key": "string",
        "status": "ok",
        "detail": "string",
        "fix": "string"
      }
    ]
  },
  "version": {
    "version_number": 0,
    "created_at": "2026-05-17T20:00:00Z",
    "actor": {
      "kind": "user",
      "id": "string",
      "label": "string",
      "session": "string"
    },
    "content_hash": "string",
    "summary": "string"
  }
}
```

### 401 — Missing, malformed, or unknown API key

Content type: `application/problem+json`

```json
{
  "type": "https://example.com",
  "title": "string",
  "status": 0,
  "detail": "string",
  "code": "invalid_key",
  "request_id": "string",
  "retry_after": 0,
  "retention_days": 0,
  "scope": "string",
  "resource": "string",
  "errors": [
    {
      "field": "string",
      "reason": "string"
    }
  ],
  "attribute_id": "00000000-0000-0000-0000-000000000000",
  "content_hash": "string",
  "differs": [
    "string"
  ]
}
```

### 403 — Key lacks the required scope or plan limit violated

Content type: `application/problem+json`

```json
{
  "type": "https://example.com",
  "title": "string",
  "status": 0,
  "detail": "string",
  "code": "invalid_key",
  "request_id": "string",
  "retry_after": 0,
  "retention_days": 0,
  "scope": "string",
  "resource": "string",
  "errors": [
    {
      "field": "string",
      "reason": "string"
    }
  ],
  "attribute_id": "00000000-0000-0000-0000-000000000000",
  "content_hash": "string",
  "differs": [
    "string"
  ]
}
```

### 404 — Resource not found

Content type: `application/problem+json`

```json
{
  "type": "https://example.com",
  "title": "string",
  "status": 0,
  "detail": "string",
  "code": "invalid_key",
  "request_id": "string",
  "retry_after": 0,
  "retention_days": 0,
  "scope": "string",
  "resource": "string",
  "errors": [
    {
      "field": "string",
      "reason": "string"
    }
  ],
  "attribute_id": "00000000-0000-0000-0000-000000000000",
  "content_hash": "string",
  "differs": [
    "string"
  ]
}
```

### 429 — Per-org rate limit exceeded

Content type: `application/problem+json`

```json
{
  "type": "https://example.com",
  "title": "string",
  "status": 0,
  "detail": "string",
  "code": "invalid_key",
  "request_id": "string",
  "retry_after": 0,
  "retention_days": 0,
  "scope": "string",
  "resource": "string",
  "errors": [
    {
      "field": "string",
      "reason": "string"
    }
  ],
  "attribute_id": "00000000-0000-0000-0000-000000000000",
  "content_hash": "string",
  "differs": [
    "string"
  ]
}
```

### 500 — Unexpected server-side failure. The `code` is `internal_error`. The
`request_id` field can be quoted to SendOps support to investigate.

Content type: `application/problem+json`

```json
{
  "type": "https://example.com",
  "title": "string",
  "status": 0,
  "detail": "string",
  "code": "invalid_key",
  "request_id": "string",
  "retry_after": 0,
  "retention_days": 0,
  "scope": "string",
  "resource": "string",
  "errors": [
    {
      "field": "string",
      "reason": "string"
    }
  ],
  "attribute_id": "00000000-0000-0000-0000-000000000000",
  "content_hash": "string",
  "differs": [
    "string"
  ]
}
```
