---
title: "Workflows"
description: "List, view, and refresh workflows"
---

# Workflows

## List All Workflows

Get a paginated list of all available workflows with filtering support.

```bash
curl http://localhost:8002/osm/api/workflows \
  -H "Authorization: Bearer $TOKEN"
```

**Query Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `source` | string | `db` | Data source: `db` (database) or `filesystem` (direct file scan) |
| `tags` | string | - | Comma-separated list of tags to filter by |
| `kind` | string | - | Filter by workflow kind: `flow`, `module` |
| `search` | string | - | Search in workflow name and description |
| `offset` | int | 0 | Pagination offset |
| `limit` | int | 50 | Maximum records to return |

**Examples:**

```bash
# Filter by tags
curl "http://localhost:8002/osm/api/workflows?tags=recon,subdomain" \
  -H "Authorization: Bearer $TOKEN"

# Filter by kind (module)
curl "http://localhost:8002/osm/api/workflows?kind=module" \
  -H "Authorization: Bearer $TOKEN"


# Search workflows
curl "http://localhost:8002/osm/api/workflows?search=enum" \
  -H "Authorization: Bearer $TOKEN"

# Load directly from filesystem (bypasses database)
curl "http://localhost:8002/osm/api/workflows?source=filesystem" \
  -H "Authorization: Bearer $TOKEN"

# Pagination
curl "http://localhost:8002/osm/api/workflows?offset=10&limit=20" \
  -H "Authorization: Bearer $TOKEN"
```

**Response:**
```json
{
  "data": [
    {
      "name": "subdomain-enum",
      "kind": "flow",
      "description": "Comprehensive subdomain enumeration and probing workflow",
      "tags": ["recon", "subdomain", "httpx"],
      "file_path": "/home/user/osmedeus-base/workflows/flows/subdomain-enum.yaml",
      "params": [
        {"name": "target", "required": true, "default": "", "generator": ""},
        {"name": "threads", "required": false, "default": "50", "generator": ""},
        {"name": "timeout", "required": false, "default": "30", "generator": ""},
        {"name": "wordlist", "required": false, "default": "", "generator": "default_wordlist"}
      ],
      "required_params": ["target"],
      "step_count": 8,
      "module_count": 3,
      "checksum": "sha256:abc123...",
      "indexed_at": "2025-01-15T08:00:00Z"
    },
    {
      "name": "port-scan",
      "kind": "module",
      "description": "Port scanning module using nmap and masscan",
      "tags": ["recon", "portscan", "nmap"],
      "file_path": "/home/user/osmedeus-base/workflows/modules/port-scan.yaml",
      "params": [
        {"name": "target", "required": true, "default": "", "generator": ""},
        {"name": "ports", "required": false, "default": "top-1000", "generator": ""},
        {"name": "rate", "required": false, "default": "1000", "generator": ""}
      ],
      "required_params": ["target"],
      "step_count": 4,
      "module_count": 0,
      "checksum": "sha256:def456...",
      "indexed_at": "2025-01-15T08:00:00Z"
    }
  ],
  "pagination": {
    "total": 25,
    "offset": 0,
    "limit": 50
  }
}
```

---

## Get Workflow Tags

Get all unique tags from indexed workflows.

```bash
curl http://localhost:8002/osm/api/workflows/tags \
  -H "Authorization: Bearer $TOKEN"
```

**Response:**
```json
{
  "tags": ["recon", "subdomain", "portscan", "vulnerability", "nuclei"],
  "count": 5
}
```

---

## Refresh Workflow Index

Re-index all workflows from filesystem to database. Use this after adding or modifying workflow files.

```bash
curl -X POST http://localhost:8002/osm/api/workflows/refresh \
  -H "Authorization: Bearer $TOKEN"
```

**Query Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `force` | bool | false | Force re-index all workflows regardless of checksum |

**Force re-index all:**
```bash
curl -X POST "http://localhost:8002/osm/api/workflows/refresh?force=true" \
  -H "Authorization: Bearer $TOKEN"
```

**Response:**
```json
{
  "message": "Workflows indexed successfully",
  "added": 5,
  "updated": 2,
  "removed": 1,
  "errors": []
}
```

---

## Get Workflow Details

Get workflow content. Returns raw YAML by default, or JSON with full parsed details.

```bash
# Get raw YAML content (default)
curl http://localhost:8002/osm/api/workflows/subdomain-enum \
  -H "Authorization: Bearer $TOKEN"
```

```bash
# Get workflow details as JSON
curl "http://localhost:8002/osm/api/workflows/subdomain-enum?json=true" \
  -H "Authorization: Bearer $TOKEN"
```

**Query Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `json` | bool | false | Return JSON with parsed details instead of raw YAML |

**Response (YAML - default):**
```yaml
name: subdomain-enum
kind: flow
description: Subdomain enumeration
params:
  - name: target
    required: true
steps:
  - name: run-subfinder
    command: subfinder -d {{target}}
...
```

**Response (JSON with `?json=true`):**
```json
{
  "name": "subdomain-enum",
  "kind": "flow",
  "description": "Comprehensive subdomain enumeration and probing workflow",
  "file_path": "/home/user/osmedeus-base/workflows/flows/subdomain-enum.yaml",
  "params": [
    {"name": "target", "required": true, "default": "", "generator": ""},
    {"name": "threads", "required": false, "default": "50", "generator": ""},
    {"name": "output_dir", "required": false, "default": "{{Workspace}}", "generator": "workspace_path"},
    {"name": "wordlist", "required": false, "default": "", "generator": "default_wordlist"}
  ],
  "steps": [
    {
      "index": 0,
      "name": "run-subfinder",
      "type": "bash",
      "command": "subfinder -d {{target}} -t {{threads}} -o {{output_dir}}/subdomains-subfinder.txt",
      "timeout": "30m",
      "pre_condition": "",
      "exports": {"subfinder_output": "{{output_dir}}/subdomains-subfinder.txt"}
    },
    {
      "index": 1,
      "name": "run-amass",
      "type": "bash",
      "command": "amass enum -passive -d {{target}} -o {{output_dir}}/subdomains-amass.txt",
      "timeout": "60m",
      "pre_condition": "commandExists('amass')",
      "exports": {"amass_output": "{{output_dir}}/subdomains-amass.txt"}
    },
    {
      "index": 2,
      "name": "merge-subdomains",
      "type": "function",
      "command": "mergeFiles('{{output_dir}}/subdomains-*.txt', '{{output_dir}}/all-subdomains.txt')",
      "timeout": "",
      "pre_condition": "",
      "exports": {"all_subdomains": "{{output_dir}}/all-subdomains.txt"}
    },
    {
      "index": 3,
      "name": "run-httpx",
      "type": "bash",
      "command": "httpx -l {{all_subdomains}} -t {{threads}} -o {{output_dir}}/alive.txt -json -o {{output_dir}}/httpx.json",
      "timeout": "60m",
      "pre_condition": "fileLength('{{all_subdomains}}') > 0",
      "exports": {"alive_hosts": "{{output_dir}}/alive.txt", "httpx_json": "{{output_dir}}/httpx.json"}
    }
  ],
  "modules": [
    {"index": 0, "name": "port-scan", "path": "modules/port-scan.yaml", "depends_on": [], "condition": ""},
    {"index": 1, "name": "nuclei-scan", "path": "modules/nuclei-scan.yaml", "depends_on": ["port-scan"], "condition": "fileLength('{{alive_hosts}}') > 0"},
    {"index": 2, "name": "screenshot", "path": "modules/screenshot.yaml", "depends_on": ["port-scan"], "condition": ""}
  ],
  "triggers": [
    {"name": "daily-scan", "on": "cron", "schedule": "0 2 * * *", "enabled": true},
    {"name": "on-new-asset", "on": "event", "topic": "asset.discovered", "enabled": false}
  ],
  "dependencies": {
    "commands": ["subfinder", "amass", "httpx", "nuclei", "nmap"],
    "files": ["{{wordlist}}"]
  }
}
```

**Step Dependencies:**

Steps can have dependencies on other steps using the `depends_on` field:
```json
{
  "steps": [
    {
      "index": 0,
      "name": "step-a",
      "type": "bash",
      "command": "echo A"
    },
    {
      "index": 1,
      "name": "step-b",
      "type": "bash",
      "command": "echo B",
      "depends_on": ["step-a"]
    },
    {
      "index": 2,
      "name": "step-c",
      "type": "bash",
      "command": "echo C",
      "depends_on": ["step-a", "step-b"]
    }
  ]
}
```
