---
title: "Dry-run (validate) a workflow"
method: POST
path: "/api/v3/workflows/{workflowId}/test"
tags: ["V3 Workflows"]
---

# Dry-run (validate) a workflow

`POST /api/v3/workflows/{workflowId}/test`

Validates a workflow without running it or causing any side effect. It checks that the workflow's current definition is executable, that the trigger's referenced survey and ending cards still exist in the workspace, and that every `send_email` action addressing a *literal* email address targets someone who can access this workspace. **No** workflow run is created and **no** email or webhook is sent.

The response is always `200` with `{ data: { workflowId, ok, problems } }`. `data.ok` is `true` when the workflow would execute; otherwise `data.problems` lists every issue found — each with a machine-readable `code` and the offending `field` — so they can be fixed in a single pass.

Drafts are testable — validating the setup before going live is the point of a dry run. Only an `archived` workflow is rejected, with **422** and code `invalid_workflow_state`.

## Path parameters

- `workflowId` string, cuid2, required

## Response `200`

Validation result. The request succeeded; inspect `data.ok` to see whether the workflow is ready, and `data.problems` for any issues.

- object
  - `data` WorkflowTestResult, required — Result of dry-running (testing) a workflow: whether it would execute and, if not, why not. No run is created and no side effects occur.
    - `workflowId` string, cuid2, required
    - `ok` boolean, required — True when the definition is executable, every trigger reference resolves, and every literal `send_email` recipient can access this workspace.
    - `problems` object[], required — Every problem found, so all issues can be fixed at once. Empty when `ok` is true.
      - `code` 'definition_not_executable' | 'survey_not_found' | 'ending_card_not_found' | 'recipient_not_allowed', required — Machine-readable problem category.
      - `field` string, required — Dotted path to the offending field, e.g. `definition.trigger.config.surveyId`.
      - `message` string, required — Human-readable explanation of the problem.

## Other responses

- `401` — Not authenticated (no valid session or API key).
- `403` — Forbidden — no workspace access, or resource does not exist (404 not used; avoids existence leak).
- `422` — Unprocessable Content — semantic validation failed or the requested lifecycle transition is invalid.
- `429` — Rate limit exceeded.
- `500` — Internal Server Error.

---

[API](https://skmtc.dev/formbricks/apis/formbricks-api-v3.md) · [All operations](https://skmtc.dev/formbricks/apis/formbricks-api-v3/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/formbricks/formbricks-api-v3/revisions/3c2c022e49d2/schema)
