> ## Documentation Index
> Fetch the complete documentation index at: https://docs.retab.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Validate Workflow Spec

> Validate declarative YAML without changing the workflow.

Any error-level diagnostic responds with 400 and the structured issues.
Warnings do not make a spec invalid: a warning-only spec responds with
200, `is_valid=True`, and the warnings in `diagnostics`.

Validate a declarative workflow YAML spec without changing workflow state.

A declarative spec uses `apiVersion: workflows.retab.com/v1alpha2`. Edges must be explicit and handle-based:

```yaml theme={null}
spec:
  edges:
    - from:
        block: start_document-node
        handle: output-file-0
      to:
        block: extract-node
        handle: input-file-source_doc
```

Handles are raw runtime handles and are validated against the block type and block configuration.

<RequestExample>
  ```python Python theme={null}
  from retab import Retab

  client = Retab()

  validation = client.workflows.spec.validate(yaml_definition)

  print(validation.is_valid)
  print(validation.diagnostics)
  ```

  ```typescript TypeScript theme={null}
  import { Retab } from "@retab/node";

  const client = new Retab({ apiKey: process.env.RETAB_API_KEY });

  const validation = await client.workflows.spec.validate(yamlDefinition);

  console.log(validation.isValid);
  console.log(validation.diagnostics);
  ```

  ```go Go theme={null}
  package main

  import (
  	"context"
  	"fmt"
  	"log"

  	retab "github.com/retab-dev/retab/clients/go"
  )

  func ptr[T any](v T) *T { return &v }

  func main() {
  	ctx := context.Background()

  	client, err := retab.NewClient("")
  	if err != nil {
  		log.Fatal(err)
  	}

  	yamlDefinition := `apiVersion: workflows.retab.com/v1alpha2
  kind: Workflow
  metadata:
    id: wf_invoice_demo
    name: Invoice Workflow
  spec:
    blocks:
      start:
        type: start_json
        label: Input JSON
        config:
          json_schema:
            type: object
            required:
              - value
            properties:
              value:
                type: string
    edges: []
  `
  	validation, err := client.Workflows.Spec.Validate(ctx, &retab.WorkflowSpecValidateParams{
  		YamlDefinition: yamlDefinition,
  	})
  	if err != nil {
  		log.Fatal(err)
  	}

  	fmt.Println(validation.IsValid)
  	fmt.Println(validation.Diagnostics)
  }
  ```

  ```ruby Ruby theme={null}
  require 'retab'

  client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])

  validation = client.workflows.spec.validate(yaml_definition: yaml_definition)

  puts validation.is_valid
  puts validation.diagnostics
  ```

  ```rust Rust theme={null}
  use retab::models::DeclarativeWorkflowRequest;
  use retab::resources::workflow_spec::ValidateParams;
  use retab::Retab;

  #[tokio::main]
  async fn main() -> Result<(), Box<dyn std::error::Error>> {
      let client = Retab::new(std::env::var("RETAB_API_KEY")?);

      let yaml_definition = r#"apiVersion: workflows.retab.com/v1alpha2
  kind: Workflow
  metadata:
    id: wf_invoice_demo
    name: Invoice Workflow
  spec:
    blocks:
      start:
        type: start_json
        label: Input JSON
        config:
          json_schema:
            type: object
            required:
              - value
            properties:
              value:
                type: string
    edges: []
  "#;
      let validation = client
          .workflows().spec()
          .validate(ValidateParams::new(DeclarativeWorkflowRequest::new(
              yaml_definition,
          )))
          .await?;

      println!("{}", validation.is_valid);
      println!("{:?}", validation.diagnostics);
      Ok(())
  }
  ```

  ```php PHP theme={null}
  <?php
  require 'vendor/autoload.php';

  use Retab\Client;

  $client = new Client(apiKey: getenv('RETAB_API_KEY'));

  $yamlDefinition = <<<'YAML'
  apiVersion: workflows.retab.com/v1alpha2
  kind: Workflow
  metadata:
    id: wf_invoice_demo
    name: Invoice Workflow
  spec:
    blocks:
      start:
        type: start_json
        label: Input JSON
        config:
          json_schema:
            type: object
            required:
              - value
            properties:
              value:
                type: string
    edges: []
  YAML;

  $result = $client->workflows()->spec()->validate(
      yamlDefinition: $yamlDefinition,
  );
  print_r($result);
  ```

  ```csharp C# theme={null}
  using Retab;
  using RetabClient = Retab.Retab;

  var apiKey = Environment.GetEnvironmentVariable("RETAB_API_KEY")!;
  var client = new RetabClient(apiKey);

  var yamlDefinition = """
  apiVersion: workflows.retab.com/v1alpha2
  kind: Workflow
  metadata:
    id: wf_invoice_demo
    name: Invoice Workflow
  spec:
    blocks:
      start:
        type: start_json
        label: Input JSON
        config:
          json_schema:
            type: object
            required:
              - value
            properties:
              value:
                type: string
    edges: []
  """;

  var result = await client.Workflows.Spec.ValidateAsync(
      new WorkflowSpecValidateOptions { YamlDefinition = yamlDefinition }
  );
  Console.WriteLine(result);
  ```

  ```java Java theme={null}
  import com.retab.RetabClient;

  public final class Example {
    public static void main(String[] args) throws Exception {
      RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));

      var result = client.workflows().spec().validate("metadata:\n  id: invoice-workflow\n", null);
      System.out.println(result);
    }
  }
  ```

  ```curl cURL theme={null}
  curl -X 'POST' \
    'https://api.retab.com/v1/workflows/spec/validate' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer <your-api-key>' \
    -d '{
      "yaml_definition": "apiVersion: workflows.retab.com/v1alpha2\nkind: Workflow\nmetadata:\n  id: wf_abc123\n  name: Invoice Workflow\nspec:\n  blocks:\n    start_document-node:\n      type: start_document\n      label: Input Document\n    extract-node:\n      type: extract\n      label: Extract Fields\n      config:\n        inputs:\n          - name: source_doc\n            type: file\n            is_primary: true\n        json_schema:\n          type: object\n          properties: {}\n  edges:\n    - from:\n        block: start_document-node\n        handle: output-file-0\n      to:\n        block: extract-node\n        handle: input-file-source_doc\n"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "workflow_id": "wf_abc123",
    "block_count": 2,
    "edge_count": 1,
    "is_valid": true,
    "diagnostics": {
      "issues": []
    }
  }
  ```
</ResponseExample>


## OpenAPI

````yaml POST /v1/workflows/spec/validate
openapi: 3.1.0
info:
  title: FastAPI
  version: 0.1.0
servers:
  - url: https://api.retab.com
security: []
paths:
  /v1/workflows/spec/validate:
    post:
      tags:
        - Workflows
      summary: Validate Workflow Spec
      description: |-
        Validate declarative YAML without changing the workflow.

        Any error-level diagnostic responds with 400 and the structured issues.
        Warnings do not make a spec invalid: a warning-only spec responds with
        200, `is_valid=True`, and the warnings in `diagnostics`.
      operationId: validate_workflow_spec
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeclarativeWorkflowRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeclarativeValidationResponse'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - HTTPBearer: []
components:
  schemas:
    DeclarativeWorkflowRequest:
      properties:
        yaml_definition:
          type: string
          title: Yaml Definition
          description: Workflow YAML definition
        project_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Project Id
          description: >-
            Project that should own a workflow created from this spec. Required
            when applying a spec that creates a new workflow.
      additionalProperties: false
      type: object
      required:
        - yaml_definition
      title: DeclarativeWorkflowRequest
      description: >-
        Body carrying a workflow's full YAML definition for validate, plan,
        apply, or export.
    DeclarativeValidationResponse:
      properties:
        workflow_id:
          type: string
          title: Workflow Id
        block_count:
          type: integer
          title: Block Count
        edge_count:
          type: integer
          title: Edge Count
        is_valid:
          type: boolean
          title: Is Valid
        diagnostics:
          additionalProperties: true
          type: object
          title: Diagnostics
      type: object
      required:
        - block_count
        - diagnostics
        - edge_count
        - is_valid
        - workflow_id
      title: DeclarativeValidationResponse
      description: >-
        Result of validating a workflow YAML definition: whether it `is_valid`,
        block/edge counts, and `diagnostics`.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
          default: []
      type: object
      title: HTTPValidationError
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
          default: null
        ctx:
          type: object
          title: Context
          default: {}
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
  securitySchemes:
    HTTPBearer:
      type: http
      scheme: bearer

````