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

# Create Workflow

> Create a new workflow for an app.

Create a new workflow. Provider keys referenced in `VERIFICATION` nodes must exist in `app.providers`. Maximum 100 workflows per app.

## Request

<ParamField header="Authorization" type="string" required>
  `Bearer <API_KEY>` from Console > Developers > Workspace API Keys.
</ParamField>

<ParamField header="Content-Type" type="string">
  `application/json`
</ParamField>

<ParamField header="Idempotency-Key" type="string">
  Optional client-generated string (max 255 chars) to safely retry without creating duplicates. Scoped per workspace. A key is valid for 24 hours. If the same key is replayed with an identical body, the original response is returned with an `Idempotency-Replayed: true` header. Reusing the same key with a different body returns `409 IDEMPOTENCY_KEY_CONFLICT`.
</ParamField>

### Path parameters

<ParamField path="client_id" type="string" required>
  Client identifier of the app.
</ParamField>

### Request body

<ParamField body="name" type="string" required>
  Display name for the workflow.
</ParamField>

<ParamField body="entryNodeId" type="string" required>
  ID of the entry node (must exist in `nodes`).
</ParamField>

<ParamField body="nodes" type="object[]" required>
  Array of flow nodes. Each node has:

  <Expandable title="Node properties">
    <ParamField body="id" type="string" required>
      Unique node identifier.
    </ParamField>

    <ParamField body="type" type="string" required>
      Node type: `request`, `verification`, `check-min-loa`, `check-claim`, `evaluate`, `if`, `response`.
    </ParamField>

    <ParamField body="next" type="string | object[]">
      Next node ID (string) or conditional routes (array) for `IF` nodes.
    </ParamField>

    <ParamField body="config" type="object">
      Type-specific configuration.
    </ParamField>
  </Expandable>
</ParamField>

## Response

<ResponseField name="workflowId" type="string">
  Auto-generated workflow identifier.
</ResponseField>

<ResponseField name="name" type="string">
  Workflow name.
</ResponseField>

<ResponseField name="entryNodeId" type="string">
  Entry node ID.
</ResponseField>

<ResponseField name="nodes" type="object[]">
  Array of flow nodes.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO 8601 timestamp.
</ResponseField>

<ResponseField name="updatedAt" type="string">
  ISO 8601 timestamp.
</ResponseField>

<Note>
  The response includes a `Location` header pointing at the newly-created resource (e.g., `/connect/v1/apps/{clientId}/workflows/wf_abc123`).
</Note>

<RequestExample>
  ```bash theme={null}
  curl -X POST \
    -H "Authorization: Bearer sk_workspace_test_..." \
    -H "Content-Type: application/json" \
    -d '{
      "name": "KYC Premium",
      "entryNodeId": "nd_req",
      "nodes": [
        { "id": "nd_req", "type": "request", "next": "nd_verify" },
        { "id": "nd_verify", "type": "verification", "next": "nd_resp", "config": { "channel": "oidc", "claims": ["name", "birthdate"] } },
        { "id": "nd_resp", "type": "response" }
      ]
    }' \
    "https://sandbox.api.hopae.com/connect/v1/apps/abc123/workflows"
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "workflowId": "wf_abc123",
    "name": "KYC Premium",
    "entryNodeId": "nd_req",
    "nodes": [
      { "id": "nd_req", "type": "request", "next": "nd_verify" },
      { "id": "nd_verify", "type": "verification", "next": "nd_resp", "config": { "channel": "oidc", "claims": ["name", "birthdate"] } },
      { "id": "nd_resp", "type": "response" }
    ],
    "createdAt": "2025-01-15T10:00:00.000Z",
    "updatedAt": "2025-01-15T10:00:00.000Z"
  }
  ```
</ResponseExample>
