# Workflows API

Multi-tenant workflow management and execution. Supports workflow CRUD, async execution with persistence, run status tracking, scheduling, and natural language parsing. All authenticated endpoints require a JWT token and are rate-limited to 100 requests per minute per user. Tenant isolation is enforced via `customer_id` from the JWT.

---

## Health Check

Public endpoint for monitoring service availability. No authentication required.

### GET /api/v2/workflows/health

Returns service health status. This endpoint is public and does not require authentication.

**Example Request**

```bash
curl -X GET https://api.lvng.ai/api/v2/workflows/health
```

**Response -- 200**

```json
{
  "status": "ok",
  "service": "workflows-api-v2",
  "version": "2.0.0",
  "timestamp": "2026-03-19T18:00:00.000Z"
}
```

---

## Natural Language Parsing

Convert a natural language instruction into a structured workflow definition using the unified workflow parser.

### POST /api/v2/workflows/parse

Parse a natural language instruction into a structured workflow definition. The instruction must be at least 5 characters.

**Body Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `instruction` | string | Yes | Natural language description of the workflow. Minimum 5 characters. |
| `context` | object | No | Additional context for parsing. Can include availableTools (array) and organizationId (string). |

**Example Request**

```bash
curl -X POST https://api.lvng.ai/api/v2/workflows/parse \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "instruction": "Every Monday at 9am, pull the latest sales data, generate a summary report, and email it to the sales team.",
    "context": {
      "availableTools": ["salesforce.query", "email.send"]
    }
  }'
```

**Response -- 200**

```json
{
  "success": true,
  "workflow": {
    "type": "generated",
    "name": "Weekly Sales Report",
    "description": "Pull sales data, generate summary, and email to team",
    "steps": [
      { "id": "step_1", "type": "integration", "action": "salesforce.query", "config": { "query": "SELECT Id, Amount, StageName, CloseDate FROM Opportunity WHERE CloseDate = LAST_WEEK" } },
      { "id": "step_2", "type": "agent", "action": "generate_report", "input_from": "step_1" },
      { "id": "step_3", "type": "integration", "action": "email.send", "input_from": "step_2" }
    ],
    "confidence": 0.87,
    "source": "ai-generated",
    "valid": true
  },
  "parseTimeMs": 1243
}
```

---

## Workflow CRUD

Create, retrieve, update, and delete workflow definitions. Workflows are scoped to a tenant via `customer_id` and ownership is verified on all mutating operations.

### GET /api/v2/workflows

List all workflows for the authenticated user's tenant. Results are ordered by creation date descending.

**Query Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `status` | string | No | Filter by status: active or archived. |
| `limit` | integer | No | Maximum number of workflows to return. Default: `50` |
| `offset` | integer | No | Pagination offset. Default: `0` |

**Example Request**

```bash
curl -X GET "https://api.lvng.ai/api/v2/workflows?status=active&limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response -- 200**

```json
{
  "success": true,
  "workflows": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "customer_id": "8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      "name": "Weekly Sales Report",
      "description": "Automated weekly sales report generation and distribution",
      "version": "1.0.0",
      "status": "active",
      "created_by": "8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      "created_at": "2026-02-15T10:00:00.000Z",
      "updated_at": "2026-03-10T14:30:00.000Z"
    }
  ],
  "count": 2
}
```

---

### POST /api/v2/workflows

Create a new workflow. The definition must be an object with a nodes array. Returns 409 if a workflow with the same name already exists for this tenant.

**Body Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `name` | string | Yes | Display name for the workflow. |
| `description` | string | No | Description of what the workflow does. |
| `definition` | object | Yes | Workflow definition object. Must contain a nodes array defining the workflow steps. |
| `version` | string | No | Semantic version string. Default: `1.0.0` |

**Example Request**

```bash
curl -X POST https://api.lvng.ai/api/v2/workflows \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Deploy Notification",
    "description": "Notify the team when a deployment completes",
    "definition": {
      "nodes": [
        { "id": "step_1", "type": "condition", "action": "check_status", "config": { "field": "$.deployment.status", "operator": "equals", "value": "success" } },
        { "id": "step_2", "type": "integration", "action": "slack.post_message", "input_from": "step_1", "config": { "channel": "#deployments", "message": "Deployment completed successfully!" } }
      ],
      "inputs": {},
      "outputs": {}
    }
  }'
```

**Response -- 201**

```json
{
  "success": true,
  "workflow": {
    "id": "c3d4e5f6-a7b8-9012-cdef-345678901234",
    "customer_id": "8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "name": "Deploy Notification",
    "description": "Notify the team when a deployment completes",
    "definition": { "nodes": ["..."], "inputs": {}, "outputs": {} },
    "version": "1.0.0",
    "status": "active",
    "created_by": "8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "created_at": "2026-03-19T17:30:00.000Z",
    "updated_at": "2026-03-19T17:30:00.000Z"
  }
}
```

---

### GET /api/v2/workflows/:id

Get the full workflow definition. The definition JSON is parsed and returned as an object. Returns 404 if not found or not owned by the tenant.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |

**Example Request**

```bash
curl -X GET https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response -- 200**

```json
{
  "success": true,
  "workflow": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "customer_id": "8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "name": "Weekly Sales Report",
    "description": "Automated weekly sales report generation and distribution",
    "definition": {
      "nodes": [
        { "id": "step_1", "type": "integration", "action": "salesforce.query" },
        { "id": "step_2", "type": "agent", "action": "generate_report", "input_from": "step_1" },
        { "id": "step_3", "type": "integration", "action": "email.send", "input_from": "step_2" }
      ],
      "inputs": {},
      "outputs": {}
    },
    "version": "1.0.0",
    "status": "active",
    "created_by": "8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "created_at": "2026-02-15T10:00:00.000Z",
    "updated_at": "2026-03-10T14:30:00.000Z"
  }
}
```

---

### PATCH /api/v2/workflows/:id

Partially update a workflow. Verifies tenant ownership before applying changes.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |

**Body Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `name` | string | No | Updated workflow name. |
| `description` | string | No | Updated description. |
| `definition` | object | No | Updated workflow definition (must contain nodes array). |
| `version` | string | No | Updated version string. |
| `status` | string | No | Set workflow status: active or archived. |

**Example Request**

```bash
curl -X PATCH https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Weekly Sales & Marketing Report",
    "status": "active"
  }'
```

**Response -- 200**

```json
{
  "success": true,
  "workflow": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Weekly Sales & Marketing Report",
    "status": "active",
    "updated_at": "2026-03-19T17:45:00.000Z"
  }
}
```

---

### DELETE /api/v2/workflows/:id

Delete a workflow and all its execution history (CASCADE). Verifies tenant ownership.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |

**Example Request**

```bash
curl -X DELETE https://api.lvng.ai/api/v2/workflows/c3d4e5f6-a7b8-9012-cdef-345678901234 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response -- 200**

```json
{
  "success": true,
  "message": "Workflow deleted successfully"
}
```

---

### GET /api/v2/workflows/:id/schema

Get the input/output schema extracted from the workflow definition.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |

**Example Request**

```bash
curl -X GET https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schema \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response -- 200**

```json
{
  "success": true,
  "schema": {
    "inputs": {
      "type": "object",
      "properties": {
        "date_range": { "type": "string", "description": "Override the default date range", "default": "LAST_WEEK" },
        "recipients": { "type": "array", "items": { "type": "string" }, "description": "Override default email recipients" }
      }
    },
    "outputs": {
      "type": "object",
      "properties": {
        "report": { "type": "string" },
        "email_sent": { "type": "boolean" }
      }
    }
  }
}
```

---

## Workflow Execution

Execute workflows and track their progress. Each execution creates a `workflow_runs` record. The workflow engine runs asynchronously and emits WebSocket events for real-time progress tracking.

### POST /api/v2/workflows/:id/execute

Trigger a workflow execution. Creates a run record and begins async execution.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |

**Body Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `inputs` | object | No | Input parameters for the workflow execution. Defaults to empty object. |

**Example Request**

```bash
curl -X POST https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890/execute \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": {
      "date_range": "LAST_MONTH",
      "recipients": ["ceo@company.com", "sales-lead@company.com"]
    }
  }'
```

**Response -- 201**

```json
{
  "success": true,
  "run": {
    "id": "e5f6a7b8-c9d0-1234-ef56-789012345678",
    "workflow_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "running",
    "inputs": { "date_range": "LAST_MONTH", "recipients": ["ceo@company.com", "sales-lead@company.com"] },
    "outputs": null,
    "error": null,
    "started_at": "2026-03-19T18:00:00.000Z",
    "finished_at": null
  }
}
```

---

### GET /api/v2/workflows/:id/runs

Get the execution history for a workflow. Results are ordered by started_at descending.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |

**Query Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `status` | string | No | Filter by run status: running, completed, failed, or terminated. |
| `limit` | integer | No | Maximum number of runs to return. Default: `50` |
| `offset` | integer | No | Pagination offset. Default: `0` |

**Example Request**

```bash
curl -X GET "https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890/runs?status=completed&limit=5" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response -- 200**

```json
{
  "success": true,
  "runs": [
    {
      "id": "e5f6a7b8-c9d0-1234-ef56-789012345678",
      "workflow_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "status": "completed",
      "inputs": { "date_range": "LAST_MONTH" },
      "outputs": { "report": "Q1 2026 Sales Summary...", "email_sent": true },
      "error": null,
      "started_at": "2026-03-19T18:00:00.000Z",
      "finished_at": "2026-03-19T18:00:47.000Z"
    }
  ],
  "count": 2
}
```

---

### GET /api/v2/workflows/:id/runs/:runId

Get detailed status of a specific workflow run.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |
| `runId` | uuid | Yes | The run ID. |

**Example Request**

```bash
curl -X GET https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890/runs/e5f6a7b8-c9d0-1234-ef56-789012345678 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response -- 200**

```json
{
  "success": true,
  "run": {
    "id": "e5f6a7b8-c9d0-1234-ef56-789012345678",
    "workflow_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "completed",
    "inputs": { "date_range": "LAST_MONTH", "recipients": ["ceo@company.com"] },
    "outputs": { "report": "Q1 2026 Sales Summary...", "email_sent": true },
    "error": null,
    "started_at": "2026-03-19T18:00:00.000Z",
    "finished_at": "2026-03-19T18:00:47.000Z"
  }
}
```

---

### DELETE /api/v2/workflows/:id/runs/:runId

Terminate a running workflow execution. Returns 400 if the run is already in a terminal state.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |
| `runId` | uuid | Yes | The run ID to terminate. |

**Example Request**

```bash
curl -X DELETE https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890/runs/e5f6a7b8-c9d0-1234-ef56-789012345678 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response -- 200**

```json
{
  "success": true,
  "message": "Workflow run terminated successfully"
}
```

---

## Workflow Schedules

Manage cron-based schedules for automated workflow execution.

### POST /api/v2/workflows/:id/schedules

Create a new cron schedule for the workflow.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |

**Body Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `cron_expression` | string | Yes | Standard 5-field cron expression. Example: "0 9 * * 1" for every Monday at 9am. |
| `timezone` | string | No | IANA timezone identifier. Default: `UTC` |
| `inputs` | object | No | Inputs to pass to each scheduled execution. |
| `missed_execution_policy` | string | No | How to handle missed runs: run_immediately, skip, or queue. |

**Example Request**

```bash
curl -X POST https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schedules \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cron_expression": "0 9 * * 1",
    "timezone": "America/New_York",
    "inputs": { "date_range": "LAST_WEEK" },
    "missed_execution_policy": "run_immediately"
  }'
```

**Response -- 201**

```json
{
  "success": true,
  "schedule": {
    "id": "f6a7b8c9-d0e1-2345-f678-901234567890",
    "workflow_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "cron_expression": "0 9 * * 1",
    "timezone": "America/New_York",
    "inputs": { "date_range": "LAST_WEEK" },
    "missed_execution_policy": "run_immediately",
    "enabled": true,
    "next_run_at": "2026-03-24T13:00:00.000Z",
    "created_at": "2026-03-19T18:15:00.000Z"
  }
}
```

---

### GET /api/v2/workflows/:id/schedules

List all schedules for a workflow.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |

**Example Request**

```bash
curl -X GET https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schedules \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response -- 200**

```json
{
  "success": true,
  "schedules": [
    {
      "id": "f6a7b8c9-d0e1-2345-f678-901234567890",
      "workflow_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "cron_expression": "0 9 * * 1",
      "timezone": "America/New_York",
      "enabled": true,
      "next_run_at": "2026-03-24T13:00:00.000Z",
      "last_run_at": "2026-03-17T13:00:00.000Z",
      "created_at": "2026-03-19T18:15:00.000Z"
    }
  ],
  "count": 1
}
```

---

### PATCH /api/v2/workflows/:id/schedules/:scheduleId

Update an existing schedule.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |
| `scheduleId` | uuid | Yes | The schedule ID to update. |

**Body Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `cron_expression` | string | No | Updated cron expression. |
| `timezone` | string | No | Updated IANA timezone. |
| `inputs` | object | No | Updated inputs for scheduled executions. |
| `enabled` | boolean | No | Enable or disable the schedule. |
| `missed_execution_policy` | string | No | Updated missed execution policy. |

**Example Request**

```bash
curl -X PATCH https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schedules/f6a7b8c9-d0e1-2345-f678-901234567890 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cron_expression": "0 9 * * 1,4",
    "enabled": true
  }'
```

**Response -- 200**

```json
{
  "success": true,
  "schedule": {
    "id": "f6a7b8c9-d0e1-2345-f678-901234567890",
    "workflow_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "cron_expression": "0 9 * * 1,4",
    "timezone": "America/New_York",
    "enabled": true,
    "next_run_at": "2026-03-20T13:00:00.000Z",
    "updated_at": "2026-03-19T18:20:00.000Z"
  }
}
```

---

### DELETE /api/v2/workflows/:id/schedules/:scheduleId

Delete a schedule.

**Path Parameters**

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | uuid | Yes | The workflow ID. |
| `scheduleId` | uuid | Yes | The schedule ID to delete. |

**Example Request**

```bash
curl -X DELETE https://api.lvng.ai/api/v2/workflows/a1b2c3d4-e5f6-7890-abcd-ef1234567890/schedules/f6a7b8c9-d0e1-2345-f678-901234567890 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response -- 200**

```json
{
  "success": true,
  "message": "Schedule deleted successfully"
}
```
