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

# Executing a Workflow

> Run a workflow with POST /v1/workflows/execute — inputs, handling 200 vs 202 responses, pause points, and partial re-runs.

## Overview

`POST /v1/workflows/execute` runs a workflow and returns the result. By default it uses the latest deployed version of the workflow. The call is synchronous — it holds the connection until the workflow reaches a terminal state or pauses.

**Typical execution times:**

| Workflow type                     | P50   | P95   |
| --------------------------------- | ----- | ----- |
| KYC (document + liveness)         | 2.5s  | 6s    |
| KYB (business lookup + sanctions) | 1.8s  | 4s    |
| Sanctions screening only          | 400ms | 900ms |
| Credential issuance only          | 120ms | 300ms |

These are end-to-end wall-clock times under normal load. Design your UX accordingly — KYC flows warrant a loading state; credential-only calls are fast enough to be invisible.

## Prerequisites

* A Beltic API key (`X-Api-Key` header — see [Authentication](/guides/authentication))
* A deployed workflow — configure and deploy workflows from the [Beltic Console](https://console.beltic.com)

## Basic Execution

```bash theme={null}
curl -X POST https://api.beltic.com/v1/workflows/execute \
  -H "X-Api-Key: $BELTIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflowId": "wf_kyc_standard",
    "options": {
      "input": {
        "subject_id": "user_jane_doe_001"
      }
    }
  }'
```

### Request Fields

| Field                          | Type    | Required | Description                                      |
| ------------------------------ | ------- | -------- | ------------------------------------------------ |
| `workflowId`                   | string  | Yes      | ID of the deployed workflow to run               |
| `options.input`                | object  | No       | Input data passed to the first block             |
| `options.environmentVariables` | object  | No       | Override environment variables for this run      |
| `options.workflowVariables`    | object  | No       | Override workflow-level variables                |
| `options.maxParallelNodes`     | number  | No       | Cap parallel block execution (default: 2)        |
| `useDraftState`                | boolean | No       | Run the draft workflow state instead of deployed |

## Handling the Response

### 200 — Terminal (Completed or Failed)

The workflow ran to a terminal state. Check `success` and `status` to determine outcome:

```json theme={null}
{
  "success": true,
  "status": "completed",
  "executionId": "exec_01HQ7P...",
  "output": {
    "document_verification": {
      "status": "passed",
      "document_type": "passport",
      "name": { "first": "Jane", "last": "Doe" },
      "birth_date": "1990-05-15",
      "nationality": "US"
    },
    "sanctions_screening": {
      "status": "clear"
    },
    "credential_issue": {
      "credential_id": "cred_01HQ...",
      "credential_type": "user",
      "signed_payload": "eyJhbGciOiJFUzI1NiIs...",
      "status": "active",
      "issued_at": "2026-05-21T10:30:00Z",
      "expires_at": "2026-08-19T10:30:00Z"
    }
  }
}
```

If a block failed, `success` will be `false` and `error` will describe what went wrong:

```json theme={null}
{
  "success": false,
  "status": "failed",
  "executionId": "exec_01HQ7Q...",
  "error": "document_verification: document expired",
  "output": {
    "document_verification": {
      "status": "failed",
      "reason": "optical_expiry"
    }
  }
}
```

### 202 — Paused

The workflow reached a block that requires external input before it can continue — a manual compliance review, sponsor bank approval, or a human-in-the-loop decision:

```json theme={null}
{
  "success": false,
  "status": "paused",
  "executionId": "exec_01HQ7R...",
  "pausePoints": [
    {
      "blockId": "sponsor_bank_review",
      "reason": "policy_mismatch",
      "description": "Subject's jurisdiction requires sponsor bank sign-off",
      "requiredInput": ["approval_reference", "reviewer_id"]
    }
  ]
}
```

Store the `executionId`. When the external review is complete, resume by running `POST /v1/workflows/execute` again with `runFromBlock` pointing to the block after the pause point.

## Resuming a Paused Execution

```bash theme={null}
curl -X POST https://api.beltic.com/v1/workflows/execute \
  -H "X-Api-Key: $BELTIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflowId": "wf_kyc_standard",
    "runFromBlock": {
      "executionId": "exec_01HQ7R...",
      "startBlockId": "credential_issue"
    },
    "options": {
      "input": {
        "approval_reference": "BANK-2026-00412",
        "reviewer_id": "rev_jones"
      }
    }
  }'
```

The resumed execution picks up state from `exec_01HQ7R...` and runs from `credential_issue` forward, skipping the already-completed blocks.

## Listing Past Executions

Check the history of any workflow:

```bash theme={null}
curl "https://api.beltic.com/v1/workflows/wf_kyc_standard/executions" \
  -H "X-Api-Key: $BELTIC_API_KEY"
```

```json theme={null}
[
  {
    "executionId": "exec_01HQ7P...",
    "status": "completed",
    "updatedAt": "2026-05-21T10:30:10Z"
  },
  {
    "executionId": "exec_01HQ7R...",
    "status": "paused",
    "updatedAt": "2026-05-21T09:15:02Z"
  }
]
```

## Testing with Draft State

Before deploying a workflow change, run it against draft state to validate the changes:

```bash theme={null}
curl -X POST https://api.beltic.com/v1/workflows/execute \
  -H "X-Api-Key: $BELTIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workflowId": "wf_kyc_standard",
    "useDraftState": true,
    "options": { "input": { "subject_id": "test_user_001" } }
  }'
```

<Warning>
  Never run draft state in production. Use a staging API key (`sk_staging_*`) when testing draft workflows.
</Warning>

## Error Codes

| HTTP  | Meaning                                                                                        |
| ----- | ---------------------------------------------------------------------------------------------- |
| `400` | Request body failed validation                                                                 |
| `401` | API key missing or invalid                                                                     |
| `403` | API key lacks execution permissions                                                            |
| `404` | Workflow ID not found or not deployed                                                          |
| `409` | Execution ID conflict (duplicate idempotency key)                                              |
| `422` | Workflow is valid but semantically unexecutable (e.g. `runFromBlock` references unknown block) |

## Next Steps

<CardGroup cols={2}>
  <Card title="Credentials API" icon="certificate" href="/guides/credentials/overview">
    Deep-dive into the credential that workflows emit
  </Card>

  <Card title="Verifying a Credential" icon="shield-check" href="/guides/credentials/verifying-a-credential">
    How to verify the signed credential at transaction time
  </Card>

  <Card title="Fintech Company Using Beltic" icon="credit-card" href="/use-cases/fintech-onboarding">
    Full end-to-end example — workflow execution, sponsor bank queue, and transaction authorization
  </Card>
</CardGroup>
