--- title: "Generic REST Orchestration" slug: "generic-rest-orchestration" updated: 2026-04-03T01:59:00Z published: 2026-04-03T01:59:00Z canonical: "docs.validatar.com/generic-rest-orchestration" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.validatar.com/llms.txt > Use this file to discover all available pages before exploring further. # Generic REST Orchestration ## Overview Any orchestration tool that can make REST API calls can integrate with Validatar. This guide provides complete, copy-paste-ready scripts in Python, PowerShell, and Bash for the execute-poll-evaluate pattern. Adapt these for your specific orchestrator. ## Prerequisites - Validatar API token with the **Execution** scope enabled — see [User Tokens](https://docs.validatar.com/docs/user-tokens) - Network access from your orchestration environment to the Validatar API endpoint - Your Validatar project ID and job ID (visible in the Validatar UI URL) ## Example: Execute a Job and Evaluate Results (Python) ``` import requests import time import os import sys # --------------------------------------------------------------------------- # Configuration — set these as environment variables or replace inline # --------------------------------------------------------------------------- VALIDATAR_API_URL = os.environ.get("VALIDATAR_API_URL") # e.g., https://mycompany.cloud.validatar.com VALIDATAR_API_TOKEN = os.environ.get("VALIDATAR_API_TOKEN") PROJECT_ID = int(os.environ.get("VALIDATAR_PROJECT_ID", "0")) JOB_ID = int(os.environ.get("VALIDATAR_JOB_ID", "0")) POLL_INTERVAL_SECONDS = 5 TIMEOUT_SECONDS = int(os.environ.get("VALIDATAR_TIMEOUT", "1800")) # 30 minutes default HEADERS = { "x-val-api-token": VALIDATAR_API_TOKEN, "Content-Type": "application/json" } BASE = f"{VALIDATAR_API_URL}/core/api/v1" # --------------------------------------------------------------------------- # Step 1 — Execute the job # --------------------------------------------------------------------------- print(f"Executing job {JOB_ID} in project {PROJECT_ID}...") execute_url = f"{BASE}/projects/{PROJECT_ID}/jobs/{JOB_ID}/execute" response = requests.post(execute_url, headers=HEADERS) response.raise_for_status() execution = response.json() batch_key = execution["executionKey"] print(f"Execution started. Batch key: {batch_key}") # --------------------------------------------------------------------------- # Step 2 — Poll for results # --------------------------------------------------------------------------- results_url = f"{BASE}/projects/{PROJECT_ID}/jobs/{JOB_ID}/results/{batch_key}" elapsed = 0 while elapsed < TIMEOUT_SECONDS: time.sleep(POLL_INTERVAL_SECONDS) elapsed += POLL_INTERVAL_SECONDS poll_response = requests.get(results_url, headers=HEADERS) poll_response.raise_for_status() result = poll_response.json() status = result.get("status", "Unknown") print(f" [{elapsed}s] Status: {status}") if status in ("Completed", "Aborted", "Abandoned"): break else: print(f"ERROR: Timeout after {TIMEOUT_SECONDS} seconds. Job may still be running.") sys.exit(1) # --------------------------------------------------------------------------- # Step 3 — Evaluate results # --------------------------------------------------------------------------- print(f"\nJob finished with status: {status}") print(f" Started: {result.get('dateStarted')}") print(f" Completed: {result.get('dateCompleted')}") if status != "Completed": print(f"FAILED: Job ended with status '{status}'.") sys.exit(1) # Check individual test results within the job tests = result.get("tests", []) failed_tests = [t for t in tests if t.get("status") not in ("Passed", "Completed")] if failed_tests: print(f"\n{len(failed_tests)} test(s) did not pass:") for t in failed_tests: print(f" - {t.get('name')} (ID: {t.get('id')}): {t.get('status')}") sys.exit(1) print(f"All {len(tests)} test(s) passed. Pipeline may continue.") sys.exit(0) ``` ## Example: Execute a Job and Evaluate Results (PowerShell) ``` # --------------------------------------------------------------------------- # Configuration — set these as environment variables or replace inline # --------------------------------------------------------------------------- $ValidatarApiUrl = $env:VALIDATAR_API_URL # e.g., https://mycompany.cloud.validatar.com $ValidatarApiToken = $env:VALIDATAR_API_TOKEN $ProjectId = [int]$env:VALIDATAR_PROJECT_ID $JobId = [int]$env:VALIDATAR_JOB_ID $PollIntervalSeconds = 5 $TimeoutSeconds = if ($env:VALIDATAR_TIMEOUT) { [int]$env:VALIDATAR_TIMEOUT } else { 1800 } $Headers = @{ "x-val-api-token" = $ValidatarApiToken "Content-Type" = "application/json" } $Base = "$ValidatarApiUrl/core/api/v1" # --------------------------------------------------------------------------- # Compatibility — TLS 1.2 for Windows PowerShell 5.1 # --------------------------------------------------------------------------- if ($PSVersionTable.PSVersion.Major -le 5) { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } # --------------------------------------------------------------------------- # Step 1 — Execute the job # --------------------------------------------------------------------------- Write-Host "Executing job $JobId in project $ProjectId..." $ExecuteUrl = "$Base/projects/$ProjectId/jobs/$JobId/execute" try { $ExecuteResponse = Invoke-RestMethod -Uri $ExecuteUrl -Method Post -Headers $Headers -ErrorAction Stop } catch { Write-Error "Failed to execute job: $_" exit 1 } $BatchKey = $ExecuteResponse.executionKey Write-Host "Execution started. Batch key: $BatchKey" # --------------------------------------------------------------------------- # Step 2 — Poll for results # --------------------------------------------------------------------------- $ResultsUrl = "$Base/projects/$ProjectId/jobs/$JobId/results/$BatchKey" $Elapsed = 0 $Status = "Running" while ($Elapsed -lt $TimeoutSeconds) { Start-Sleep -Seconds $PollIntervalSeconds $Elapsed += $PollIntervalSeconds try { $PollResponse = Invoke-RestMethod -Uri $ResultsUrl -Method Get -Headers $Headers -ErrorAction Stop } catch { Write-Warning "Poll request failed at ${Elapsed}s: $_. Retrying..." continue } $Status = $PollResponse.status Write-Host " [${Elapsed}s] Status: $Status" if ($Status -in @("Completed", "Aborted", "Abandoned")) { break } } if ($Elapsed -ge $TimeoutSeconds -and $Status -eq "Running") { Write-Error "Timeout after $TimeoutSeconds seconds. Job may still be running." exit 1 } # --------------------------------------------------------------------------- # Step 3 — Evaluate results # --------------------------------------------------------------------------- Write-Host "`nJob finished with status: $Status" Write-Host " Started: $($PollResponse.dateStarted)" Write-Host " Completed: $($PollResponse.dateCompleted)" if ($Status -ne "Completed") { Write-Error "Job ended with status '$Status'." exit 1 } # Check individual test results within the job $Tests = $PollResponse.tests $FailedTests = $Tests | Where-Object { $_.status -notin @("Passed", "Completed") } if ($FailedTests) { Write-Host "`n$($FailedTests.Count) test(s) did not pass:" foreach ($t in $FailedTests) { Write-Host " - $($t.name) (ID: $($t.id)): $($t.status)" } exit 1 } Write-Host "All $($Tests.Count) test(s) passed. Pipeline may continue." exit 0 ``` ## Example: Execute a Job (Bash/curl) ``` #!/usr/bin/env bash set -euo pipefail # --------------------------------------------------------------------------- # Configuration # --------------------------------------------------------------------------- VALIDATAR_API_URL="${VALIDATAR_API_URL:?Set VALIDATAR_API_URL}" VALIDATAR_API_TOKEN="${VALIDATAR_API_TOKEN:?Set VALIDATAR_API_TOKEN}" PROJECT_ID="${VALIDATAR_PROJECT_ID:?Set VALIDATAR_PROJECT_ID}" JOB_ID="${VALIDATAR_JOB_ID:?Set VALIDATAR_JOB_ID}" POLL_INTERVAL=5 TIMEOUT="${VALIDATAR_TIMEOUT:-1800}" BASE="${VALIDATAR_API_URL}/core/api/v1" # --------------------------------------------------------------------------- # Step 1 — Execute # --------------------------------------------------------------------------- echo "Executing job ${JOB_ID} in project ${PROJECT_ID}..." EXEC_RESPONSE=$(curl -s -f -X POST \ "${BASE}/projects/${PROJECT_ID}/jobs/${JOB_ID}/execute" \ -H "x-val-api-token: ${VALIDATAR_API_TOKEN}" \ -H "Content-Type: application/json") BATCH_KEY=$(echo "${EXEC_RESPONSE}" | python3 -c "import sys,json; print(json.load(sys.stdin)['executionKey'])") echo "Execution started. Batch key: ${BATCH_KEY}" # --------------------------------------------------------------------------- # Step 2 — Poll # --------------------------------------------------------------------------- RESULTS_URL="${BASE}/projects/${PROJECT_ID}/jobs/${JOB_ID}/results/${BATCH_KEY}" ELAPSED=0 STATUS="Running" while [ "${ELAPSED}" -lt "${TIMEOUT}" ]; do sleep "${POLL_INTERVAL}" ELAPSED=$((ELAPSED + POLL_INTERVAL)) POLL_RESPONSE=$(curl -s -f -X GET "${RESULTS_URL}" \ -H "x-val-api-token: ${VALIDATAR_API_TOKEN}") STATUS=$(echo "${POLL_RESPONSE}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('status','Unknown'))") echo " [${ELAPSED}s] Status: ${STATUS}" if [[ "${STATUS}" == "Completed" || "${STATUS}" == "Aborted" || "${STATUS}" == "Abandoned" ]]; then break fi done if [[ "${STATUS}" == "Running" ]]; then echo "ERROR: Timeout after ${TIMEOUT}s" exit 1 fi # --------------------------------------------------------------------------- # Step 3 — Evaluate # --------------------------------------------------------------------------- if [[ "${STATUS}" != "Completed" ]]; then echo "FAILED: Job ended with status '${STATUS}'" exit 1 fi echo "Job completed successfully." exit 0 ``` ## Example: Execute a Standard Test with waitUntilComplete (Python) For individual standard tests, you can skip polling entirely by setting `waitUntilComplete` to `true`. The API call blocks until the test finishes and returns the result directly. ``` import requests import os import sys VALIDATAR_API_URL = os.environ.get("VALIDATAR_API_URL") VALIDATAR_API_TOKEN = os.environ.get("VALIDATAR_API_TOKEN") PROJECT_ID = int(os.environ.get("VALIDATAR_PROJECT_ID", "0")) TEST_ID = int(os.environ.get("VALIDATAR_TEST_ID", "0")) HEADERS = { "x-val-api-token": VALIDATAR_API_TOKEN, "Content-Type": "application/json" } BASE = f"{VALIDATAR_API_URL}/core/api/v1" # Execute synchronously — no polling needed print(f"Executing standard test {TEST_ID} (synchronous)...") execute_url = f"{BASE}/projects/{PROJECT_ID}/tests/{TEST_ID}/execute" payload = { "saveInRepository": True, "waitUntilComplete": True } response = requests.post(execute_url, headers=HEADERS, json=payload) response.raise_for_status() execution = response.json() batch_key = execution["executionKey"] print(f"Execution complete. Batch key: {batch_key}") # Get the summary to check the result summary_url = f"{BASE}/projects/{PROJECT_ID}/tests/{TEST_ID}/results/{batch_key}" summary_response = requests.get(summary_url, headers=HEADERS) summary_response.raise_for_status() summary = summary_response.json() result = summary.get("result", "Unknown") print(f"Test: {summary.get('name')}") print(f"Result: {result}") print(f"Started: {summary.get('dateStarted')}") print(f"Completed: {summary.get('dateCompleted')}") if result == "Passed": print("Test passed. Pipeline may continue.") sys.exit(0) else: print(f"Test did not pass (result: {result}).") sys.exit(1) ``` ## Adapting for Your Orchestrator The scripts above work anywhere you can run Python, PowerShell, or Bash. Here's how to call them from common orchestration platforms: | Orchestrator | How to Run | Notes | | --- | --- | --- | | **Control-M** | Web Services job type or OS job running a script | Use the Python or PowerShell script as the job command | | **Prefect** | `@task` decorator calling `requests` in a flow | Wrap the Python logic in a Prefect task; use Prefect Blocks for credentials | | **Dagster** | `@op` decorator with `requests` in a job | Wrap the Python logic in a Dagster op; use Resources for credentials | | **dbt Cloud** | Webhooks triggering an external script | dbt Cloud can call a webhook on model completion; the webhook runs the Validatar script | | **Luigi** | `Task` subclass with `requests` in `run()` | Wrap the Python logic in a Luigi Task | | **SSIS** | Execute Process task running PowerShell | Point the task at the PowerShell script; pass parameters via SSIS variables | | **Talend** | tSystem component or tRESTClient | Use tSystem to call the script, or tRESTClient for direct API calls | ## Troubleshooting ### 401 or 403 Response - Verify the `x-val-api-token` header name is exact (not `Authorization` or `Bearer`) - Confirm the token has the **Execution** scope - Check that the token user has access to the project ### Timeout Without Completion - Increase `TIMEOUT_SECONDS` if your jobs are expected to run longer than 30 minutes - Check the Validatar UI to see if the execution is still running or has an error - Verify the job has tests assigned to it — an empty job may behave unexpectedly ### Connection Refused or Timeout - Verify `VALIDATAR_API_URL` is correct (e.g., `https://mycompany.cloud.validatar.com`) - Check network connectivity — if Validatar Server is behind a firewall, the orchestrator must be able to reach it - For Cloud instances, verify no corporate proxy is blocking the connection ### Empty Test Results in Job Summary - The `tests` array in the job summary may not be populated until the job status is `Completed` - Ensure you're reading the final poll response, not an intermediate one