Skip to docs navigation

REST API Reference

The WEXTL REST v1 API — versioned, frozen-additive, and machine-readable via a single OpenAPI document.

text
GET /api/v1/openapi.json
  1. WEXTL® REST v1 API — our own source implementation.
  2. Our users' real API integrations and automations.
  3. The machine-readable OpenAPI specification for the REST API.

Common error responses

StatusDescription
401No valid bearer token.
421Wrong regional endpoint — follow error.base_url.
429Rate limited — retry after error.retry_after_s seconds.

Workflows

13endpoints

  • GET /workflows Auth required

    List workflows (bounded, cursor-paginated).

    NameInTypeDescription
    cursorquerystringOpaque continuation token from a previous response.
    limitqueryintegerPage size. Default 50.
    qquerystringFree-text search on name + description.
    statusquerystring—
    folderIdquerystringRestrict to this folder and its descendants.
    sortByquerystring—
    sortDirquerystring—
    tagIdsquerystringComma-separated tag ids.
    tagMatchquerystring—
    • 200A page of workflow summaries.
    • 403Missing workflow:read scope, or the plan lacks API access.
    • Common error responses
    NameInTypeDescription
    data*—array<WorkflowSummary>—
    next_cursor*—string | null—

    data[] item (WorkflowSummary)

    NameInTypeDescription
    id*—string—
    name*—string—
    active*—boolean—
    folderId—string | null—
    nodeCount—integer—
    tagIds—array<string>—
    createdAt—integerEpoch milliseconds.
    updatedAt—integerEpoch milliseconds.

    Example response

    json
    {
      "data": [
        {
          "id": "abc123",
          "name": "My workflow",
          "active": true,
          "folderId": "fld_01HXEXAMPLE",
          "nodeCount": 3,
          "tagIds": [
            "..."
          ],
          "createdAt": 1719792000000,
          "updatedAt": 1719792000000
        }
      ],
      "next_cursor": null
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/workflows \
      -H "Authorization: Bearer wextl_..."
  • POST /workflows Auth required

    Create a new, empty (draft) workflow. Build its graph via POST .../ops afterwards.

    NameInTypeDescription
    name*bodystring—
    folderIdbodystring | nullMust reference an accessible folder.
    teamIdbodystring | nullMust belong to the caller's org. Omit to use the org's default team.
    • 201The created (empty) draft workflow.
    • 400Invalid body — missing/oversized name, or an unresolvable folderId/teamId.
    • 403Missing workflow:write scope, or the plan lacks API access.
    • Common error responses
    NameInTypeDescription
    data—WorkflowCreateResult—

    data shape (WorkflowCreateResult)

    NameInTypeDescription
    id*—string—
    name*—string—
    teamId*—string—
    folderId—string | null—
    active*—boolean—
    createdAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "teamId": "team_01HXEXAMPLE",
        "active": true,
        "createdAt": 1719792000000,
        "folderId": "fld_01HXEXAMPLE"
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/workflows \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "folderId": "fld_01HXEXAMPLE",
      "teamId": "team_01HXEXAMPLE"
    }'
  • GET /workflows/{id} Auth required

    Read a workflow's full DRAFT graph, or its deployed snapshot via ?view=deployed.

    NameInTypeDescription
    id*pathstring—
    viewquerystringOmit for the current draft. `deployed` reads the last Go Live snapshot; 404 workflow_not_deployed if never published.
    • 200The workflow (draft or deployed, per ?view).
    • 403Missing workflow:read scope, or the plan lacks API access.
    • 404Workflow not found (or, with ?view=deployed, never deployed — workflow_not_deployed).
    • Common error responses
    NameInTypeDescription
    data—one of 2 shapes—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "active": true,
        "nodes": [
          {
            "id": 12,
            "appId": "slack",
            "name": "Send a message",
            "moduleSlug": "sendMessage",
            "x": 420,
            "y": 180,
            "params": {
              "channel": "#general",
              "text": "Deployment finished."
            },
            "connectionId": "oauth2",
            "credentialId": "cred_01HXEXAMPLE"
          }
        ],
        "edges": [
          {
            "id": "e_12_18",
            "from": 12,
            "to": 18,
            "type": "normal",
            "order": 0
          }
        ],
        "description": "...",
        "folderId": "fld_01HXEXAMPLE",
        "teamId": "team_01HXEXAMPLE",
        "schedule": {
          "recurrence": {
            "kind": "interval",
            "every": 15,
            "unit": "min",
            "timezone": "Europe/London",
            "skipIfRunning": true
          },
          "executionTimeoutMs": 0
        },
        "createdAt": 1719792000000,
        "updatedAt": 1719792000000,
        "deployed": {
          "deployedAt": 1719792000000,
          "versionNo": 0,
          "contentHash": "..."
        }
      }
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."
  • PATCH /workflows/{id} Auth required

    Curated update: name, active, schedule (recurrence), and/or folderId.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    namebodystring—
    activebodybooleanActivate or deactivate the workflow.
    queuedEventsbodystringOnly with active: true. Webhook events that arrived while the workflow was off: 'all' (default) processes every one, 'latest' keeps only the newest, 'none' drops them so only new events run.
    recurrencebodyScheduleRecurrenceSchedule recurrence object, or null to clear. Setting a schedule does not activate.
    folderIdbodystring | nullMove into folder; null to unassign.
    • 200Fields that were updated.
    • 400Invalid body.
    • 403Missing workflow:write scope.
    • 404Workflow not found.
    • 409Conflict — re-read and retry.
    • 503queuedEvents could not drop the waiting events; the workflow is still off. Retry.
    • Common error responses
    NameInTypeDescription
    data*—object—

    data shape (object)

    NameInTypeDescription
    id—string—
    updated—array<string>—
    name—string—
    active—boolean—
    folderId—string | null—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "updated": [
          "..."
        ],
        "name": "My workflow",
        "active": true,
        "folderId": "fld_01HXEXAMPLE"
      }
    }

    Example request

    bash
    curl -X PATCH https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "active": true,
      "queuedEvents": "...",
      "recurrence": {
        "kind": "interval",
        "every": 15,
        "unit": "min",
        "timezone": "Europe/London",
        "skipIfRunning": true
      },
      "folderId": "fld_01HXEXAMPLE"
    }'
  • DELETE /workflows/{id} Auth required

    Permanently delete a workflow. Refused while active or deployed.

    NameInTypeDescription
    id*pathstring—
    • 200Deleted.
    • 403Missing workflow:write scope.
    • 404Workflow not found.
    • 409Workflow is active or deployed — deactivate/undeploy first.
    • Common error responses
    NameInTypeDescription
    data—object—

    data shape (object)

    NameInTypeDescription
    ok—boolean—

    Example response

    json
    {
      "data": {
        "ok": true
      }
    }

    Example request

    bash
    curl -X DELETE https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."
  • POST /workflows/{id}/ops Auth required

    Apply a batch of graph operations to a workflow.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    ops*bodyarray<object>Batch of GraphOp objects. One of: add_node, update_params, update_config, connect, disconnect, remove_node, rename_node, set_credential, set_edge_filter.
    expectedUpdatedAt*bodyintegerREQUIRED optimistic-concurrency precondition — the workflow `updatedAt` this batch was computed against (take it from a prior GET /workflows/{id}). Mismatch → 409 workflow_modified. Without it two agents editing the same workflow silently overwrite each other, since a batch replaces the whole nodes/edges set; omitting it is rejected with 400 VALIDATION_ERROR.
    • 200The batch result — best-effort; a non-empty errors[] does not mean the whole batch was rejected.
    • 400Invalid body, or the resulting graph fails the topology gate.
    • 403Missing workflow:write scope, or the plan lacks API access.
    • 404Workflow not found.
    • 409workflow_modified — expectedUpdatedAt no longer matches; reload and retry.
    • Common error responses
    NameInTypeDescription
    data—GraphOpsResult—

    data shape (GraphOpsResult)

    NameInTypeDescription
    applied*—objecttempId → real node id, for every add_node that landed.
    errors*—array<string>Best-effort per-op failures — the rest of the batch still applies.
    touched*—array<integer>Node ids added or param/config-updated by this batch, including hub-scaffolded satellite/placeholder ids.
    updatedAt—integerThe workflow's new updatedAt — pass it as expectedUpdatedAt on the next ops call to avoid conflicts.

    Example response

    json
    {
      "data": {
        "applied": {
          "tmp_1": "42",
          "tmp_2": "43"
        },
        "errors": [
          "..."
        ],
        "touched": [
          0
        ],
        "updatedAt": 1719792000000
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE/ops \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "ops": [
        {
          "op": "..."
        }
      ],
      "expectedUpdatedAt": 1719792000000
    }'
  • POST /workflows/{id}/deploy Auth required

    Go Live — publish the current draft as the deployed snapshot (idempotent).

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    expectedUpdatedAtbodyintegerOptimistic-concurrency precondition — the draft updatedAt this deploy was computed against. Mismatch → 409 workflow_modified.
    • 200The new deployed snapshot summary.
    • 403Missing workflow:write or run scope (deploying arms future runs), or the plan lacks API access.
    • 404Workflow not found.
    • 409workflow_modified — expectedUpdatedAt no longer matches; reload and retry.
    • Common error responses
    NameInTypeDescription
    data—DeployResult—

    data shape (DeployResult)

    NameInTypeDescription
    workflowId*—string—
    contentHash*—string—
    versionNo*—integer—
    deployedAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": {
        "workflowId": "wf_01HXEXAMPLE",
        "contentHash": "...",
        "versionNo": 0,
        "deployedAt": 1719792000000
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE/deploy \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "expectedUpdatedAt": 1719792000000
    }'
  • POST /workflows/{id}/validate Auth required

    Validate a workflow's structure (duplicate ids, orphan edges, cycles, trigger placement). Run this before declaring a workflow correct.

    NameInTypeDescription
    id*pathstring—
    • 200The validation result.
    • 403Missing workflow:read scope, or the plan lacks API access.
    • 404Workflow not found.
    • Common error responses
    NameInTypeDescription
    data—ValidateWorkflowResult—

    data shape (ValidateWorkflowResult)

    NameInTypeDescription
    valid*—boolean—
    issues*—array<string>Human-readable validation problems. Empty when valid is true.

    Example response

    json
    {
      "data": {
        "valid": false,
        "issues": [
          "Node 7 has no incoming edges and is not the trigger."
        ]
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE/validate \
      -H "Authorization: Bearer wextl_..."
  • POST /workflows/{id}/resolve-expression Auth required

    Resolve a {{expr}} template against a node's available input data from the latest (or a specific) run — validates references like {{4.user_id}} before wiring them.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    expression*bodystringThe expression template, e.g. '{{3.rows[0].name}}' or bare '3.rows[0].name'.
    fromNodeIdbodystringThe node id that uses this expression — helps locate its upstream nodes from the latest run.
    runIdbodystringOptional run id to use for sample data. Defaults to the most recent run.
    • 200The resolution attempt — resolved is null with error set when it could not be resolved (e.g. no runs yet).
    • 400expression is required.
    • 403Missing workflow:read scope, or the plan lacks API access.
    • 404Workflow not found.
    • Common error responses
    NameInTypeDescription
    data—ResolveExpressionResult—

    data shape (ResolveExpressionResult)

    NameInTypeDescription
    resolved*—anyThe resolved value (any JSON type), or null when resolution failed or no run data exists yet.
    resolvedType—stringtypeof the resolved value, e.g. "string", "number", "object". Absent when resolved is null.
    truncated—booleantrue when a large resolved string value was cut to fit the response budget.
    error*—string | nullPresent when resolution failed, or when no runs exist yet for this workflow.

    Example response

    json
    {
      "data": {
        "resolved": "user_42",
        "resolvedType": "string",
        "error": null
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE/resolve-expression \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "expression": "{{3.rows[0].name}}",
      "fromNodeId": "4"
    }'
  • POST /workflows/{id}/webhook Auth required

    Mint (or return the existing) inbound webhook URL for a workflow trigger node.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    nodeId*bodystringThe webhook trigger node id (numeric id as a string).
    • 200The webhook URL (idempotent — alreadyBound:true when a live one already existed).
    • 400Missing nodeId, or the node is not a webhook trigger node.
    • 403Missing webhook:write scope, or the plan lacks API access.
    • 404Workflow or node not found.
    • 409The node already has a DISABLED webhook record bound to it.
    • Common error responses
    NameInTypeDescription
    data—Webhook—

    data shape (Webhook)

    NameInTypeDescription
    webhookId*—string—
    url*—stringThe inbound URL to POST trigger payloads to.
    alreadyBound—boolean—

    Example response

    json
    {
      "data": {
        "webhookId": "wh_01HXEXAMPLE",
        "url": "https://eu1.wextl.com/hooks/wh_01HXEXAMPLE",
        "alreadyBound": true
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE/webhook \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "nodeId": "abc123"
    }'
  • POST /workflows/{id}/runs Auth required

    Start a run of the workflow's current draft (billing and structure checks apply).

    NameInTypeDescription
    id*pathstring—
    Idempotency-KeyheaderstringOptional but strongly recommended when the client may retry. A caller-chosen unique string; retrying with the same key returns the SAME run rather than starting another. Without it a timeout-and-retry starts a second run, double-charging credits and repeating any external side effects the workflow performs.
    NameInTypeDescription
    nodeIdbodystringOptional node id (numeric id as a string) to run from — a scoped run. Omit for a full-graph run.
    upstreamOutputsbodyobjectOptional nodeId→payload map to seed as upstream inputs. Mutually exclusive with seedFromRun.
    seedFromRunbodyobjectSeed from a past run node output (server-resolved). Mutually exclusive with upstreamOutputs.
    • 201The run was created and enqueued.
    • 400Invalid nodeId/inputs, or the workflow fails the topology gate (e.g. no runnable path).
    • 402Payment required — a payment problem or an inactive subscription is blocking runs.
    • 403Missing run scope, no active plan, or out of credits (PLAN_LIMIT_EXCEEDED).
    • 404Workflow not found.
    • Common error responses
    NameInTypeDescription
    data—StartRunResult—

    data shape (StartRunResult)

    NameInTypeDescription
    runId*—string—

    Example response

    json
    {
      "data": {
        "runId": "run_01HXEXAMPLE"
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE/runs \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "nodeId": "abc123",
      "upstreamOutputs": {
        "12": {
          "message": "Hello world",
          "channel": "#general"
        }
      },
      "seedFromRun": {
        "runId": "run_01HXEXAMPLE",
        "nodeId": 0
      }
    }'
  • PUT /workflows/{id}/tags Auth required

    Replace the full tag set on a workflow.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    tagIds*bodyarray<string>—
    NameInTypeDescription
    data—SetWorkflowTagsResult—

    data shape (SetWorkflowTagsResult)

    NameInTypeDescription
    ok*—boolean—
    tagIds*—array<string>—

    Example response

    json
    {
      "data": {
        "ok": true,
        "tagIds": [
          "tag_01HXEXAMPLE"
        ]
      }
    }

    Example request

    bash
    curl -X PUT https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE/tags \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "tagIds": [
        "..."
      ]
    }'
  • POST /workflows/{id}/test-module Auth required

    Execute a single app node with its current parameters (module test).

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    nodeId*bodyone of 2 shapes—
    NameInTypeDescription
    data—objectThe node's module output on success. Shape depends on the module — the same shape a real run's node output would have.

    Example response

    json
    {
      "data": {
        "ok": true,
        "ts": "1719792000.000100",
        "channel": "#general"
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/workflows/wf_01HXEXAMPLE/test-module \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "nodeId": "abc123"
    }'

Variables

4endpoints

  • GET /variables Auth required

    List variable names and metadata for the organization (up to 500). Secret values are always returned as null.

    • 200Every variable visible to this key.
    • 403Missing variable:read scope, or the plan lacks API access.
    • Common error responses
    NameInTypeDescription
    data*—array<Variable>—

    data[] item (Variable)

    NameInTypeDescription
    id*—string—
    name*—string—
    isSecret*—boolean—
    value*—string | null—
    teamId*—string | null—
    createdAt*—integerEpoch milliseconds.
    updatedAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": [
        {
          "id": "abc123",
          "name": "My workflow",
          "isSecret": false,
          "value": null,
          "teamId": "team_01HXEXAMPLE",
          "createdAt": 1719792000000,
          "updatedAt": 1719792000000
        }
      ]
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/variables \
      -H "Authorization: Bearer wextl_..."
  • GET /variables/{id} Auth required

    Read one variable by id. A secret variable's value is always returned as null.

    NameInTypeDescription
    id*pathstring—
    • 200The variable (value is null when isSecret is true).
    • 403Missing variable:read scope, or the plan lacks API access.
    • 404Variable not found.
    • Common error responses
    NameInTypeDescription
    data—Variable—

    data shape (Variable)

    NameInTypeDescription
    id*—string—
    name*—string—
    isSecret*—boolean—
    value*—string | null—
    teamId*—string | null—
    createdAt*—integerEpoch milliseconds.
    updatedAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "isSecret": false,
        "value": null,
        "teamId": "team_01HXEXAMPLE",
        "createdAt": 1719792000000,
        "updatedAt": 1719792000000
      }
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/variables/var_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."
  • PUT /variables/{id} Auth required

    Create or update a variable by name (upsert) — the {id} path segment IS the variable name, not a database id. Secrets are write-only.

    NameInTypeDescription
    id*pathstringThe variable name (letters/numbers/underscores, must start with a letter or underscore) — this call upserts by name.
    NameInTypeDescription
    value*bodystringRequired for a new non-secret variable. For an existing secret, a blank value keeps the current stored value.
    isSecretbodybooleanWhether this variable is a secret. Only takes effect on create — updating an existing variable never changes its stored secret status.
    teamIdbodystring | nullMust belong to the caller's org. Omit for an org-level variable.
    • 200An existing variable was updated.
    • 201A new variable was created.
    • 400Invalid body — bad name, missing value, a secret shorter than 6 characters, or an unresolvable teamId.
    • 403Missing variable:write scope, or the plan lacks API access.
    • Common error responses
    NameInTypeDescription
    data—SetVariableResult—

    data shape (SetVariableResult)

    NameInTypeDescription
    id*—string—
    name*—string—
    isSecret*—boolean—
    teamId*—string | null—
    updatedAt*—integerEpoch milliseconds.
    created*—booleantrue when this call created a new variable, false when it updated an existing one.

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "isSecret": false,
        "teamId": "team_01HXEXAMPLE",
        "updatedAt": 1719792000000,
        "created": true
      }
    }

    Example request

    bash
    curl -X PUT https://eu1.wextl.com/api/v1/variables/var_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "value": null,
      "isSecret": false,
      "teamId": "team_01HXEXAMPLE"
    }'
  • DELETE /variables/{id} Auth required

    Soft-delete a variable by database id (not name).

    NameInTypeDescription
    id*pathstringThe variable database id from list_variables / get_variable.
    NameInTypeDescription
    data—object—

    data shape (object)

    NameInTypeDescription
    ok—boolean—

    Example response

    json
    {
      "data": {
        "ok": true
      }
    }

    Example request

    bash
    curl -X DELETE https://eu1.wextl.com/api/v1/variables/var_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."

Runs

6endpoints

  • GET /runs Auth required

    List runs of a workflow (bounded, cursor-paginated). workflowId is REQUIRED in v1 — org-wide listing is out of scope.

    NameInTypeDescription
    workflowId*querystringREQUIRED — scope the listing to this workflow.
    cursorquerystring—
    limitqueryintegerPage size. Default 50.
    qquerystringFree-text search over status + id.
    • 200A page of run summaries.
    • 400workflowId query parameter is required.
    • 403Missing workflow:read scope, or the plan lacks API access.
    • Common error responses
    NameInTypeDescription
    data*—array<RunSummary>—
    next_cursor*—string | null—

    data[] item (RunSummary)

    NameInTypeDescription
    id*—string—
    workflowId*—string | null—
    status*—string—
    createdAt*—string | nullISO-8601 timestamp.
    finishedAt—string | nullISO-8601 timestamp; null while the run is non-terminal.
    creditsUsed*—number—

    Example response

    json
    {
      "data": [
        {
          "id": "abc123",
          "workflowId": "wf_01HXEXAMPLE",
          "status": "succeeded",
          "createdAt": "2024-07-01T12:00:00.000Z",
          "creditsUsed": 50,
          "finishedAt": null
        }
      ],
      "next_cursor": null
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/runs \
      -H "Authorization: Bearer wextl_..."
  • GET /runs/{id} Auth required

    Get a run report: status, timestamps, error, and per-node status/error/output.

    NameInTypeDescription
    id*pathstring—
    • 200The run report.
    • 403Missing workflow:read scope, or the plan lacks API access.
    • 404Run not found.
    • Common error responses
    NameInTypeDescription
    data—RunReport—

    data shape (RunReport)

    NameInTypeDescription
    id*—string—
    workflowId—string—
    status*—string—
    createdAt—string | null—
    finishedAt—string | null—
    error—string | null—
    nodes—array<RunNode>—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "status": "succeeded",
        "workflowId": "wf_01HXEXAMPLE",
        "createdAt": "2024-07-01T12:00:00.000Z",
        "finishedAt": null,
        "error": null,
        "nodes": [
          {
            "nodeId": 12,
            "label": "Send a message",
            "status": "completed",
            "output": {
              "ok": true,
              "ts": "1719792000.000100"
            }
          }
        ]
      }
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/runs/run_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."
  • POST /runs/{id}/cancel Auth required

    Cancel an in-flight workflow run.

    NameInTypeDescription
    id*pathstring—
    • 200The run was cancelled.
    • 400The run is already in a terminal state.
    • 403Missing run scope, or the plan lacks API access.
    • 404Run not found.
    • Common error responses
    NameInTypeDescription
    data—CancelRunResult—

    data shape (CancelRunResult)

    NameInTypeDescription
    ok*—boolean—

    Example response

    json
    {
      "data": {
        "ok": true
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/runs/run_01HXEXAMPLE/cancel \
      -H "Authorization: Bearer wextl_..."
  • POST /runs/{id}/rerun Auth required

    Re-queue a finished run as a new attempt.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    data—RerunResult—

    data shape (RerunResult)

    NameInTypeDescription
    runId*—string—
    status*—string—
    attemptNumber*—integer—
    updatedAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": {
        "runId": "run_01HXEXAMPLE",
        "status": "queued",
        "attemptNumber": 2,
        "updatedAt": 1719792000000
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/runs/run_01HXEXAMPLE/rerun \
      -H "Authorization: Bearer wextl_..."
  • POST /runs/{id}/retry-node Auth required

    Resume a run from one failed node (same attempt).

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    nodeId*bodyinteger—
    attemptNumberbodyinteger—
    NameInTypeDescription
    data—RetryNodeResult—

    data shape (RetryNodeResult)

    NameInTypeDescription
    runId*—string—
    status*—string—
    attemptNumber*—integer—
    nodeId*—integer—
    updatedAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": {
        "runId": "run_01HXEXAMPLE",
        "status": "running",
        "attemptNumber": 1,
        "nodeId": 12,
        "updatedAt": 1719792000000
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/runs/run_01HXEXAMPLE/retry-node \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "nodeId": 0,
      "attemptNumber": 0
    }'
  • POST /runs/{id}/nodes/{nodeId}/respond Auth required

    Submit a human-in-the-loop response and resume (or complete) the run.

    NameInTypeDescription
    id*pathstring—
    nodeId*pathstring—
    NameInTypeDescription
    response*bodyobjectThe HITL response fields — shape depends on the node's configured response fields.
    attemptNumberbodyinteger—
    • 200Response recorded.
    • 400Invalid body.
    • 402Payment required for mid-flow resume.
    • 403Missing run scope.
    • 404Run not found.
    • 409Conflict — resume already in flight or run terminal.
    • Common error responses
    NameInTypeDescription
    data—RespondNodeResult—

    data shape (RespondNodeResult)

    NameInTypeDescription
    ok*—boolean—
    resumed*—booleantrue when the run resumed execution past this node.
    terminal*—booleantrue when this response completed the run (no further nodes to run).

    Example response

    json
    {
      "data": {
        "ok": true,
        "resumed": true,
        "terminal": false
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/runs/run_01HXEXAMPLE/nodes/node_1/respond \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "response": {
        "approved": true,
        "comment": "Looks good, ship it."
      },
      "attemptNumber": 0
    }'

Credentials

6endpoints

  • GET /credentials Auth required

    List the organization's stored credentials (names and metadata only; secret payloads are never returned).

    NameInTypeDescription
    cursorquerystring—
    limitqueryintegerPage size. Default 50.
    appIdquerystringOptional app id to filter by.
    • 200A page of credential summaries.
    • 403Missing credential:read scope, or the plan lacks API access.
    • Common error responses
    NameInTypeDescription
    data*—array<Credential>—
    next_cursor*—string | null—

    data[] item (Credential)

    NameInTypeDescription
    id*—string—
    name*—string—
    appId*—string—
    type*—stringThe connection type id.
    status*—string—
    folderId—string | null—
    createdAt*—integerEpoch milliseconds.
    updatedAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": [
        {
          "id": "abc123",
          "name": "My workflow",
          "appId": "slack",
          "type": "oauth2",
          "status": "succeeded",
          "createdAt": 1719792000000,
          "updatedAt": 1719792000000,
          "folderId": "fld_01HXEXAMPLE"
        }
      ],
      "next_cursor": null
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/credentials \
      -H "Authorization: Bearer wextl_..."
  • POST /credentials Auth required

    Create a credential when safe (no-auth or secrets already supplied). OAuth or missing secrets return status credential_required with a connect_url for a logged-in human.

    NameInTypeDescription
    appId*bodystring—
    connectionId*bodystring—
    name*bodystring—
    databodyobjectSecret field values when the caller already has them — keyed by the connection's parameter names (from get_module_spec / the connection spec), e.g. an api-key connection's `apiKey`. Never invent placeholders when calling this for real — the value shown here is illustrative only.
    teamIdbodystring | null—
    • 200Created credential or credential_required handoff.
    • 400Invalid body.
    • 403Missing credential:write scope, or the plan lacks API access.
    • Common error responses
    NameInTypeDescription
    data—CredentialCreateResult—

    data shape (CredentialCreateResult)

    NameInTypeDescription
    credentialId—string—
    status—string—
    appId—string—
    connectionId—string—
    connect_url—string—

    Example response

    json
    {
      "data": {
        "credentialId": "abc123",
        "status": "succeeded",
        "appId": "slack",
        "connectionId": "abc123",
        "connect_url": "..."
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/credentials \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "appId": "slack",
      "connectionId": "abc123",
      "name": "My workflow",
      "data": {
        "apiKey": "sk_live_your_api_key_here"
      },
      "teamId": "team_01HXEXAMPLE"
    }'
  • PATCH /credentials/{id} Auth required

    Rename a credential or move its folder (never returns secrets).

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    namebodystring—
    folderIdbodystring | null—
    • 200Updated credential summary.
    • 400Invalid body.
    • 403Missing credential:write scope.
    • 404Credential not found.
    • Common error responses
    NameInTypeDescription
    data—Credential—

    data shape (Credential)

    NameInTypeDescription
    id*—string—
    name*—string—
    appId*—string—
    type*—stringThe connection type id.
    status*—string—
    folderId—string | null—
    createdAt*—integerEpoch milliseconds.
    updatedAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "appId": "slack",
        "type": "oauth2",
        "status": "succeeded",
        "createdAt": 1719792000000,
        "updatedAt": 1719792000000,
        "folderId": "fld_01HXEXAMPLE"
      }
    }

    Example request

    bash
    curl -X PATCH https://eu1.wextl.com/api/v1/credentials/cred_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "folderId": "fld_01HXEXAMPLE"
    }'
  • DELETE /credentials/{id} Auth required

    Soft-delete a credential.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    data—object—

    data shape (object)

    NameInTypeDescription
    ok—boolean—

    Example response

    json
    {
      "data": {
        "ok": true
      }
    }

    Example request

    bash
    curl -X DELETE https://eu1.wextl.com/api/v1/credentials/cred_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."
  • POST /credentials/{id}/verify Auth required

    Test whether a stored credential is accepted by the third-party service (never returns the secret).

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    data—one of 2 shapes—

    Example response

    json
    {
      "data": {
        "status": "ok"
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/credentials/cred_01HXEXAMPLE/verify \
      -H "Authorization: Bearer wextl_..."
  • POST /credentials/dynamic-options Auth required

    Fetch live RPC-backed field options (tables, channels, sheets, …).

    NameInTypeDescription
    appId*bodystring—
    rpcId*bodystring—
    credentialIdbodystring—
    paramsbodyobjectOptional dependency parameters for nested RPCs, e.g. { "tableId": "users" } to get columns for a table.
    NameInTypeDescription
    data—DynamicOptionsResult—

    data shape (DynamicOptionsResult)

    NameInTypeDescription
    items*—array<object>—
    truncated—booleantrue when the result was capped at 200 items.
    total—integerPresent only when truncated.

    Example response

    json
    {
      "data": {
        "items": [
          {
            "value": "C0123ABCDE",
            "label": "#general"
          },
          {
            "value": "C0456FGHIJ",
            "label": "#engineering"
          }
        ]
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/credentials/dynamic-options \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "appId": "slack",
      "rpcId": "abc123",
      "credentialId": "abc123",
      "params": {
        "tableId": "users"
      }
    }'

Databases

6endpoints

  • GET /databases Auth required

    List the organization's built-in database tables.

    NameInTypeDescription
    limitqueryinteger—
    • 200Database table summaries.
    • 403Missing database:read scope, or the plan lacks API access.
    • Common error responses
    NameInTypeDescription
    data*—array<DatabaseSummary>—
    truncated*—boolean—

    data[] item (DatabaseSummary)

    NameInTypeDescription
    id*—string—
    name*—string—
    columnCount*—integer—
    rowCount*—integer—

    Example response

    json
    {
      "data": [
        {
          "id": "abc123",
          "name": "My workflow",
          "columnCount": 3,
          "rowCount": 3
        }
      ],
      "truncated": true
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/databases \
      -H "Authorization: Bearer wextl_..."
  • POST /databases Auth required

    Create a built-in database table (DDL). Row writes are not available on the public API.

    NameInTypeDescription
    name*bodystring—
    descriptionbodystring—
    columns*bodyarray<DatabaseColumnInput>—
    teamIdbodystring | null—
    • 201Created table with generated column ids.
    • 400Invalid body.
    • 403Missing database:write scope, or the plan lacks API access.
    • Common error responses
    NameInTypeDescription
    data—DatabaseSchema—

    data shape (DatabaseSchema)

    NameInTypeDescription
    id*—string—
    name*—string—
    columns*—array<object>—
    rowCount*—integer—
    uniqueKeyColumnId—string—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "columns": [
          {
            "id": "abc123",
            "name": "My workflow",
            "type": "action",
            "required": true,
            "indexed": true
          }
        ],
        "rowCount": 3,
        "uniqueKeyColumnId": "abc123"
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/databases \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "columns": [
        {
          "name": "Status",
          "type": "select",
          "required": false,
          "indexed": true
        }
      ],
      "description": "...",
      "teamId": "team_01HXEXAMPLE"
    }'
  • GET /databases/{id} Auth required

    Read one database table's column schema.

    NameInTypeDescription
    id*pathstring—
    • 200Schema projection.
    • 403Missing database:read scope, or the plan lacks API access.
    • 404Database not found.
    • Common error responses
    NameInTypeDescription
    data—DatabaseSchema—

    data shape (DatabaseSchema)

    NameInTypeDescription
    id*—string—
    name*—string—
    columns*—array<object>—
    rowCount*—integer—
    uniqueKeyColumnId—string—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "columns": [
          {
            "id": "abc123",
            "name": "My workflow",
            "type": "action",
            "required": true,
            "indexed": true
          }
        ],
        "rowCount": 3,
        "uniqueKeyColumnId": "abc123"
      }
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/databases/db_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."
  • PATCH /databases/{id} Auth required

    Replace a table's column definitions with the full desired list (declarative).

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    columns*bodyarray<DatabaseColumnInput>—
    • 200Updated schema.
    • 400Invalid body.
    • 403Missing database:write scope, or the plan lacks API access.
    • 404Database not found.
    • Common error responses
    NameInTypeDescription
    data—DatabaseSchema—

    data shape (DatabaseSchema)

    NameInTypeDescription
    id*—string—
    name*—string—
    columns*—array<object>—
    rowCount*—integer—
    uniqueKeyColumnId—string—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "columns": [
          {
            "id": "abc123",
            "name": "My workflow",
            "type": "action",
            "required": true,
            "indexed": true
          }
        ],
        "rowCount": 3,
        "uniqueKeyColumnId": "abc123"
      }
    }

    Example request

    bash
    curl -X PATCH https://eu1.wextl.com/api/v1/databases/db_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "columns": [
        {
          "name": "Status",
          "type": "select",
          "required": false,
          "indexed": true
        }
      ]
    }'
  • DELETE /databases/{id} Auth required

    Soft-delete a built-in database table.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    data—object—

    data shape (object)

    NameInTypeDescription
    ok—boolean—

    Example response

    json
    {
      "data": {
        "ok": true
      }
    }

    Example request

    bash
    curl -X DELETE https://eu1.wextl.com/api/v1/databases/db_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."
  • GET /databases/{id}/rows Auth required

    Read rows from a built-in database table (bounded). No public DML row writes.

    NameInTypeDescription
    id*pathstring—
    filtersquerystringJSON-encoded filter array.
    sortColumnIdquerystring—
    sortDirquerystring—
    limitqueryinteger—
    cursorquerystring—
    • 200A page of rows keyed by column name.
    • 400Invalid filters or query shape.
    • 403Missing database:read scope, or the plan lacks API access.
    • 404Database not found.
    • Common error responses
    NameInTypeDescription
    data*—array<object>—
    count*—integer—
    next_cursor*—string | null—

    Example response

    json
    {
      "data": [
        {
          "id": "row_01HXEXAMPLE",
          "Name": "Ada Lovelace",
          "Status": "active",
          "createdAt": 1719792000000,
          "updatedAt": 1719792000000
        }
      ],
      "count": 3,
      "next_cursor": null
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/databases/db_01HXEXAMPLE/rows \
      -H "Authorization: Bearer wextl_..."

Structures

4endpoints

  • GET /structures Auth required

    List the organization's structures.

    NameInTypeDescription
    limitqueryinteger—
    NameInTypeDescription
    data*—array<StructureSummary>—
    truncated*—boolean—

    data[] item (StructureSummary)

    NameInTypeDescription
    id*—string—
    name*—string—
    fieldCount*—integer—

    Example response

    json
    {
      "data": [
        {
          "id": "abc123",
          "name": "My workflow",
          "fieldCount": 3
        }
      ],
      "truncated": true
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/structures \
      -H "Authorization: Bearer wextl_..."
  • POST /structures Auth required

    Create a structure. Honours the structures_created plan limit (no bypass).

    NameInTypeDescription
    name*bodystring—
    descriptionbodystring—
    fieldsbodyarray<StructureField>—
    folderIdbodystring | null—
    teamIdbodystring | null—
    • 201Created structure.
    • 400Invalid body.
    • 403Missing structure:write scope, or plan structure limit reached.
    • Common error responses
    NameInTypeDescription
    data—Structure—

    data shape (Structure)

    NameInTypeDescription
    id*—string—
    name*—string—
    fields*—array<object>—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "fields": [
          {
            "name": "My workflow",
            "type": "action",
            "required": true
          }
        ]
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/structures \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "description": "...",
      "fields": [
        {
          "name": "email",
          "type": "text",
          "required": true
        }
      ],
      "folderId": "fld_01HXEXAMPLE",
      "teamId": "team_01HXEXAMPLE"
    }'
  • GET /structures/{id} Auth required

    Read one structure's field list.

    NameInTypeDescription
    id*pathstring—
    • 200Structure fields.
    • 403Missing structure:read scope, or the plan lacks API access.
    • 404Structure not found.
    • Common error responses
    NameInTypeDescription
    data—Structure—

    data shape (Structure)

    NameInTypeDescription
    id*—string—
    name*—string—
    fields*—array<object>—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "fields": [
          {
            "name": "My workflow",
            "type": "action",
            "required": true
          }
        ]
      }
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/structures/struct_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."
  • PATCH /structures/{id} Auth required

    Update a structure name, description, fields, or folderId.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    namebodystring—
    descriptionbodystring—
    fieldsbodyarray<StructureField>—
    folderIdbodystring | null—
    • 200Updated structure.
    • 400Invalid body.
    • 403Missing structure:write scope.
    • 404Structure not found.
    • Common error responses
    NameInTypeDescription
    data—Structure—

    data shape (Structure)

    NameInTypeDescription
    id*—string—
    name*—string—
    fields*—array<object>—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "fields": [
          {
            "name": "My workflow",
            "type": "action",
            "required": true
          }
        ]
      }
    }

    Example request

    bash
    curl -X PATCH https://eu1.wextl.com/api/v1/structures/struct_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "description": "...",
      "fields": [
        {
          "name": "email",
          "type": "text",
          "required": true
        }
      ],
      "folderId": "fld_01HXEXAMPLE"
    }'

Functions

4endpoints

  • GET /functions Auth required

    List the organization's custom functions (metadata only).

    NameInTypeDescription
    cursorquerystring—
    limitqueryinteger—
    qquerystring—
    NameInTypeDescription
    data*—array<FunctionSummary>—
    next_cursor*—string | null—

    data[] item (FunctionSummary)

    NameInTypeDescription
    id*—string—
    name*—string—
    description—string | null—

    Example response

    json
    {
      "data": [
        {
          "id": "abc123",
          "name": "My workflow",
          "description": "..."
        }
      ],
      "next_cursor": null
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/functions \
      -H "Authorization: Bearer wextl_..."
  • POST /functions Auth required

    Create a custom function. Requires the custom_functions plan feature (no bypass).

    NameInTypeDescription
    name*bodystringcamelCase name.
    code*bodystring—
    descriptionbodystring—
    parametersbodyarray<FunctionParameter>—
    folderIdbodystring | null—
    teamIdbodystring | null—
    • 201Created function.
    • 400Invalid body.
    • 403Missing function:write scope, or custom_functions not on plan.
    • Common error responses
    NameInTypeDescription
    data—Function—

    data shape (Function)

    NameInTypeDescription
    id*—string—
    name*—string—
    description—string | null—
    code*—string—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "code": "...",
        "description": "..."
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/functions \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "code": "...",
      "description": "...",
      "parameters": [
        {
          "name": "amount",
          "type": "number",
          "description": "Order total in cents.",
          "required": true
        }
      ],
      "folderId": "fld_01HXEXAMPLE",
      "teamId": "team_01HXEXAMPLE"
    }'
  • GET /functions/{id} Auth required

    Read one custom function including user-owned code.

    NameInTypeDescription
    id*pathstring—
    • 200Function with code.
    • 403Missing function:read scope, or the plan lacks API access.
    • 404Function not found.
    • Common error responses
    NameInTypeDescription
    data—Function—

    data shape (Function)

    NameInTypeDescription
    id*—string—
    name*—string—
    description—string | null—
    code*—string—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "code": "...",
        "description": "..."
      }
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/functions/fn_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."
  • PATCH /functions/{id} Auth required

    Update a custom function. Requires the custom_functions plan feature (no bypass).

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    namebodystring—
    codebodystring—
    descriptionbodystring—
    parametersbodyarray<FunctionParameter>—
    folderIdbodystring | null—
    • 200Updated function.
    • 400Invalid body.
    • 403Missing function:write scope, or custom_functions not on plan.
    • 404Function not found.
    • Common error responses
    NameInTypeDescription
    data—Function—

    data shape (Function)

    NameInTypeDescription
    id*—string—
    name*—string—
    description—string | null—
    code*—string—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "code": "...",
        "description": "..."
      }
    }

    Example request

    bash
    curl -X PATCH https://eu1.wextl.com/api/v1/functions/fn_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "code": "...",
      "description": "...",
      "parameters": [
        {
          "name": "amount",
          "type": "number",
          "description": "Order total in cents.",
          "required": true
        }
      ],
      "folderId": "fld_01HXEXAMPLE"
    }'

Teams

6endpoints

  • GET /teams Auth required

    List the organization's teams (discovery for create_workflow; requires workflow:read).

    NameInTypeDescription
    data*—array<Team>—

    data[] item (Team)

    NameInTypeDescription
    id*—string—
    name*—string—
    createdAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": [
        {
          "id": "abc123",
          "name": "My workflow",
          "createdAt": 1719792000000
        }
      ]
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/teams \
      -H "Authorization: Bearer wextl_..."
  • PATCH /teams/{teamId} Auth required

    Rename a team. Requires team:write; the key's creator must be an org owner/admin or an admin of this team.

    NameInTypeDescription
    teamId*pathstring—
    NameInTypeDescription
    name*bodystringThe new team name.
    • 200The renamed team.
    • 400Missing or too long name.
    • 403Missing team:write scope, or the key's creator may not manage this team.
    • 404Team (or team member) not found in this organization.
    • Common error responses
    NameInTypeDescription
    data*—TeamRenameResult—

    data shape (TeamRenameResult)

    NameInTypeDescription
    id*—string—
    name*—string—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow"
      }
    }

    Example request

    bash
    curl -X PATCH https://eu1.wextl.com/api/v1/teams/id_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow"
    }'
  • GET /teams/{teamId}/members Auth required

    List one team's members, one keyset page at a time (requires workflow:read; any org member may view a team).

    NameInTypeDescription
    teamId*pathstring—
    cursorquerystring—
    limitqueryinteger—
    • 200One page of team members; next_cursor is null on the last page.
    • 400Invalid cursor or limit.
    • 403Missing workflow:read scope, or the plan lacks API access.
    • 404Team not found in this organization.
    • Common error responses
    NameInTypeDescription
    data*—array<TeamMember>—
    next_cursor*—string | null—

    data[] item (TeamMember)

    NameInTypeDescription
    userId*—string—
    role*—stringThe team role (admin, member, developer, accountant; older rows may say team_member).
    createdAt*—string | nullISO 8601, when the member joined the team.

    Example response

    json
    {
      "data": [
        {
          "userId": "abc123",
          "role": "...",
          "createdAt": "2024-07-01T12:00:00.000Z"
        }
      ],
      "next_cursor": null
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/teams/id_01HXEXAMPLE/members \
      -H "Authorization: Bearer wextl_..."
  • POST /teams/{teamId}/members Auth required

    Add organization members to a team (1 to 100 per request; all or nothing). Requires team:write.

    NameInTypeDescription
    teamId*pathstring—
    NameInTypeDescription
    userIds*bodyarray<string>Organization member user ids (from list_members), 1 to 100 per request.
    • 200Added and already-present members.
    • 400Invalid userIds, or a user who is not a member of the organization.
    • 403Missing team:write scope, or the key's creator may not manage this team.
    • 404Team (or team member) not found in this organization.
    • Common error responses
    NameInTypeDescription
    data*—TeamMembersAdded—

    data shape (TeamMembersAdded)

    NameInTypeDescription
    added*—array<string>User ids added to the team.
    alreadyMembers*—array<string>User ids that were already in the team (nothing written).

    Example response

    json
    {
      "data": {
        "added": [
          "..."
        ],
        "alreadyMembers": [
          "..."
        ]
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/teams/id_01HXEXAMPLE/members \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "userIds": [
        "..."
      ]
    }'
  • POST /teams/{teamId}/members/remove Auth required

    Remove members from a team (1 to 100 per request). Requires team:write; removing an accountant needs an org owner/admin.

    NameInTypeDescription
    teamId*pathstring—
    NameInTypeDescription
    userIds*bodyarray<string>Organization member user ids (from list_members), 1 to 100 per request.
    • 200Removed members and the ids that were not in the team.
    • 400Invalid userIds.
    • 403Missing team:write scope, or the key's creator may not manage this team.
    • 404Team (or team member) not found in this organization.
    • Common error responses
    NameInTypeDescription
    data*—TeamMembersRemoved—

    data shape (TeamMembersRemoved)

    NameInTypeDescription
    removed*—array<string>User ids removed from the team.
    notMembers*—array<string>User ids that were not in the team (nothing written).

    Example response

    json
    {
      "data": {
        "removed": [
          "..."
        ],
        "notMembers": [
          "..."
        ]
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/teams/id_01HXEXAMPLE/members/remove \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "userIds": [
        "..."
      ]
    }'
  • PATCH /teams/{teamId}/members/{userId} Auth required

    Change one member's team role. Requires team:write; setting or removing accountant needs an org owner/admin.

    NameInTypeDescription
    teamId*pathstring—
    userId*pathstring—
    NameInTypeDescription
    role*bodystringThe new team role. accountant is set or removed by org owners and admins only.
    • 200The new team role.
    • 400Invalid role.
    • 403Missing team:write scope, or the key's creator may not manage this team.
    • 404Team (or team member) not found in this organization.
    • Common error responses
    NameInTypeDescription
    data*—TeamMemberRoleResult—

    data shape (TeamMemberRoleResult)

    NameInTypeDescription
    teamId*—string—
    userId*—string—
    role*—string—

    Example response

    json
    {
      "data": {
        "teamId": "team_01HXEXAMPLE",
        "userId": "abc123",
        "role": "..."
      }
    }

    Example request

    bash
    curl -X PATCH https://eu1.wextl.com/api/v1/teams/id_01HXEXAMPLE/members/id_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "role": "..."
    }'

Folders

4endpoints

  • GET /folders Auth required

    List the organization's folder tree (discovery for create_workflow; requires workflow:read).

    NameInTypeDescription
    data*—array<Folder>—

    data[] item (Folder)

    NameInTypeDescription
    id*—string—
    name*—string—
    parentId*—string | null—

    Example response

    json
    {
      "data": [
        {
          "id": "abc123",
          "name": "My workflow",
          "parentId": "abc123"
        }
      ]
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/folders \
      -H "Authorization: Bearer wextl_..."
  • POST /folders Auth required

    Create a folder (requires workflow:write).

    NameInTypeDescription
    name*bodystring—
    parentIdbodystring | null—
    NameInTypeDescription
    data*—Folder—

    data shape (Folder)

    NameInTypeDescription
    id*—string—
    name*—string—
    parentId*—string | null—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "parentId": "abc123"
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/folders \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "parentId": "abc123"
    }'
  • PATCH /folders/{id} Auth required

    Rename or reparent a folder (requires workflow:write).

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    namebodystring—
    parentIdbodystring | null—
    • 200Updated folder.
    • 400Invalid name or parentId.
    • 403Missing workflow:write scope.
    • 404Folder not found.
    • Common error responses
    NameInTypeDescription
    data*—Folder—

    data shape (Folder)

    NameInTypeDescription
    id*—string—
    name*—string—
    parentId*—string | null—

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "name": "My workflow",
        "parentId": "abc123"
      }
    }

    Example request

    bash
    curl -X PATCH https://eu1.wextl.com/api/v1/folders/fld_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "parentId": "abc123"
    }'
  • DELETE /folders/{id} Auth required

    Delete a folder (requires workflow:write). Contents are not cascade-deleted.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    data*—object—

    data shape (object)

    NameInTypeDescription
    ok—boolean—

    Example response

    json
    {
      "data": {
        "ok": true
      }
    }

    Example request

    bash
    curl -X DELETE https://eu1.wextl.com/api/v1/folders/fld_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."

Activity

3endpoints

  • GET /activity Auth required

    List the organization's activity feed (audit log). Requires activity:read.

    NameInTypeDescription
    teamIdquerystringOnly rows of this team (from list_teams).
    actorUserIdquerystringOnly rows this user did.
    targetTypequerystringOnly rows about this kind of entity.
    targetIdquerystringOnly rows about this entity id.
    actionquerystringFull action, e.g. workflow.created.
    viaquerystringOne exact surface: api_key:<keyId>, oauth:<grantId>, assistant:<chatId>, web or system.
    viaKindquerystringOnly rows that came through this kind of surface.
    sincequeryintegerEpoch ms lower bound (inclusive). Without it the first page covers the last 90 days.
    untilqueryintegerEpoch ms upper bound (exclusive).
    limitqueryintegerPage size (default 25).
    cursorquerystringThe next_cursor of the previous page.
    • 200Activity page with labeled events, the actor map and what you can see.
    • 400Invalid filter, cursor or limit.
    • 403Missing activity:read scope, or not a member of the organization.
    • Common error responses
    NameInTypeDescription
    data*—ActivityPage—

    data shape (ActivityPage)

    NameInTypeDescription
    events*—array<ActivityEvent>—
    actors*—objectactorUserId → actor, for every distinct actor referenced in events.
    next_cursor*—string | null—
    visibility*—ActivityVisibility—

    Example response

    json
    {
      "data": {
        "events": [
          {
            "key": "abc123",
            "id": "abc123",
            "ts": 1719792000000,
            "action": "...",
            "label": "My workflow",
            "targetType": "...",
            "outcome": "...",
            "targetId": "abc123",
            "actorUserId": "abc123",
            "realAdminId": "abc123",
            "teamId": "team_01HXEXAMPLE",
            "via": "...",
            "viaLabel": "...",
            "op": "...",
            "saveCount": 3,
            "firstAt": 1719792000000,
            "lastAt": 1719792000000,
            "metadata": "..."
          }
        ],
        "actors": {
          "usr_01HXEXAMPLE": {
            "id": "usr_01HXEXAMPLE",
            "name": "Ada Lovelace",
            "email": "ada@example.com"
          }
        },
        "next_cursor": null,
        "visibility": {
          "tier": "...",
          "teams": [
            "..."
          ],
          "canExport": true
        }
      }
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/activity \
      -H "Authorization: Bearer wextl_..."
  • GET /activity/export Auth required

    Download the activity you can see as CSV or JSON Lines. Requires activity:read.

    NameInTypeDescription
    formatquerystringFile format: csv (default) or jsonl (one JSON event per line).
    teamIdquerystringOnly rows of this team (from list_teams).
    actorUserIdquerystringOnly rows this user did.
    targetTypequerystringOnly rows about this kind of entity.
    targetIdquerystringOnly rows about this entity id.
    actionquerystringFull action, e.g. workflow.created.
    viaquerystringOne exact surface: api_key:<keyId>, oauth:<grantId>, assistant:<chatId>, web or system.
    viaKindquerystringOnly rows that came through this kind of surface.
    untilqueryintegerEpoch ms upper bound (exclusive).
    sincequeryintegerEpoch ms lower bound (inclusive). Without it the export covers the whole retained activity log.
    • 200The file (an attachment). CSV columns: time, key, action, label, actor_user_id, actor_name, actor_email, real_admin_id, team_id, via, via_label, op, outcome, target_type, target_id, save_count, metadata. JSON Lines: one ActivityEvent plus its `actor` per line.
    • 400Invalid filter or format.
    • 403Missing activity:read scope, or not a member of the organization.
    • 500The export could not be recorded, so nothing was exported. Retry.
    • Common error responses

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/activity/export \
      -H "Authorization: Bearer wextl_..."
  • GET /activity/{key} Auth required

    Get one activity event by its key, including every save of a merged workflow autosave. Requires activity:read.

    NameInTypeDescription
    key*pathstringThe event key ("{ts}_{id}") from GET /activity.
    • 200The event, its actors and what you can see.
    • 400Malformed key.
    • 403Missing activity:read scope, or not a member of the organization.
    • 404No such event, or one you may not see.
    • Common error responses
    NameInTypeDescription
    data*—ActivityDetail—

    data shape (ActivityDetail)

    NameInTypeDescription
    event*—object—
    actors*—object—
    visibility*—ActivityVisibility—

    Example response

    json
    {
      "data": {
        "event": {
          "saves": [
            {
              "ts": 0,
              "nodesAdded": 0,
              "nodesRemoved": 0,
              "nodesEdited": 0,
              "edgesAdded": 0,
              "edgesRemoved": 0,
              "changes": [
                {
                  "nodeId": "n_2",
                  "label": "Slack › Send message",
                  "kinds": [
                    "mapping"
                  ]
                }
              ],
              "moreChanges": 0
            }
          ],
          "overflow": {
            "count": 3,
            "firstTs": 0,
            "lastTs": 0,
            "nodesAdded": 0,
            "nodesRemoved": 0,
            "nodesEdited": 0
          }
        },
        "actors": {
          "usr_01HXEXAMPLE": {
            "id": "usr_01HXEXAMPLE",
            "name": "Ada Lovelace",
            "email": "ada@example.com"
          }
        },
        "visibility": {
          "tier": "...",
          "teams": [
            "..."
          ],
          "canExport": true
        }
      }
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/activity/id_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."

Invitations

4endpoints

  • GET /invitations Auth required

    List organization invitations, oldest first. Without cursor or limit: up to 500 in one response, no next_cursor (the original form). With cursor or limit: one keyset page (default 100) plus next_cursor. Requires invitation:read (owner/admin).

    NameInTypeDescription
    statusquerystring—
    cursorquerystring—
    limitqueryinteger—
    • 200Invitations (each with invite_url). next_cursor is present only when cursor or limit was sent; null on the last page.
    • 400Invalid status, cursor or limit.
    • 403Missing invitation:read scope, or not an org admin.
    • Common error responses
    NameInTypeDescription
    data*—array<Invitation>—
    next_cursor—string | nullOnly with cursor or limit. Pass it as cursor for the next page.

    data[] item (Invitation)

    NameInTypeDescription
    id*—string—
    email*—string—
    role—string | null—
    teamId—string | null—
    status*—string—
    expiresAt*—integerEpoch milliseconds.
    createdAt*—integerEpoch milliseconds.
    inviterId*—string—
    invite_url*—stringAbsolute URL for the invitee; relay if email delivery fails.

    Example response

    json
    {
      "data": [
        {
          "id": "abc123",
          "email": "...",
          "status": "succeeded",
          "expiresAt": 1719792000000,
          "createdAt": 1719792000000,
          "inviterId": "abc123",
          "invite_url": "...",
          "role": "...",
          "teamId": "team_01HXEXAMPLE"
        }
      ],
      "next_cursor": null
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/invitations \
      -H "Authorization: Bearer wextl_..."
  • POST /invitations Auth required

    Invite people by email with one org role (member, admin, billing, viewer; owner only by an owner), optionally into a team. Send email (one address) for one invitation object, or emails (1 to 100) for { invitations, alreadyMembers, alreadyInvited }. Requires invitation:write; a team-limited key invites only into its teams. Returns each invite_url for headless relay.

    one of 2 shapes

    • 200The emails form only - nothing created: every address was already a member or already invited.
    • 201Created. The email form: the invitation. The emails form: the bulk result (addresses already members or already invited are listed, not invited).
    • 400Invalid emails, role or teamId.
    • 403Missing invitation:write, not an org admin, an owner invite by a non-owner, a team outside the key, or the seat cap.
    • 409The email form only: a pending invitation already exists for this email, or it already belongs to a member.
    • Common error responses
    NameInTypeDescription
    data*—InvitationsCreated—

    data shape (InvitationsCreated)

    NameInTypeDescription
    invitations*—array<Invitation>—
    alreadyMembers*—array<string>Addresses that already belong to a member (not invited).
    alreadyInvited*—array<string>Addresses with a pending invitation already (use resend_invitation).

    Example response

    json
    {
      "data": {
        "invitations": [
          {
            "id": "abc123",
            "email": "...",
            "status": "succeeded",
            "expiresAt": 1719792000000,
            "createdAt": 1719792000000,
            "inviterId": "abc123",
            "invite_url": "...",
            "role": "...",
            "teamId": "team_01HXEXAMPLE"
          }
        ],
        "alreadyMembers": [
          "..."
        ],
        "alreadyInvited": [
          "..."
        ]
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/invitations \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "email": "...",
      "role": "...",
      "teamId": "team_01HXEXAMPLE"
    }'
  • DELETE /invitations/{id} Auth required

    Cancel a pending invitation. Requires invitation:write.

    NameInTypeDescription
    id*pathstring—
    • 200Cancelled.
    • 403Missing invitation:write scope, or not an org admin.
    • 404Invitation not found.
    • 409Invitation is not pending.
    • Common error responses
    NameInTypeDescription
    data*—object—

    data shape (object)

    NameInTypeDescription
    ok—boolean—

    Example response

    json
    {
      "data": {
        "ok": true
      }
    }

    Example request

    bash
    curl -X DELETE https://eu1.wextl.com/api/v1/invitations/inv_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."
  • POST /invitations/{id}/resend Auth required

    Send a pending invitation's email again with a fresh 48-hour link. Requires invitation:write (decided with the invitation's own role and team).

    NameInTypeDescription
    id*pathstring—
    • 200The invitation with its new expiry.
    • 403Missing invitation:write scope, not an org admin, or an owner invitation resent by a non-owner.
    • 404Invitation not found.
    • 409Invitation is not pending.
    • Common error responses
    NameInTypeDescription
    data*—Invitation—

    data shape (Invitation)

    NameInTypeDescription
    id*—string—
    email*—string—
    role—string | null—
    teamId—string | null—
    status*—string—
    expiresAt*—integerEpoch milliseconds.
    createdAt*—integerEpoch milliseconds.
    inviterId*—string—
    invite_url*—stringAbsolute URL for the invitee; relay if email delivery fails.

    Example response

    json
    {
      "data": {
        "id": "abc123",
        "email": "...",
        "status": "succeeded",
        "expiresAt": 1719792000000,
        "createdAt": 1719792000000,
        "inviterId": "abc123",
        "invite_url": "...",
        "role": "...",
        "teamId": "team_01HXEXAMPLE"
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/invitations/inv_01HXEXAMPLE/resend \
      -H "Authorization: Bearer wextl_..."

Tags

4endpoints

  • GET /tags Auth required

    List workflow tags (requires workflow:read).

    NameInTypeDescription
    data—array<Tag>—

    data[] item (Tag)

    NameInTypeDescription
    id*—string—
    name*—string—
    color*—string—
    createdAt*—integerEpoch milliseconds.
    updatedAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": [
        {
          "id": "tag_01HXEXAMPLE",
          "name": "Priority",
          "color": "amber",
          "createdAt": 1719792000000,
          "updatedAt": 1719792000000
        }
      ]
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/tags \
      -H "Authorization: Bearer wextl_..."
  • POST /tags Auth required

    Create a workflow tag.

    NameInTypeDescription
    name*bodystring—
    color*bodystring—
    NameInTypeDescription
    data—Tag—

    data shape (Tag)

    NameInTypeDescription
    id*—string—
    name*—string—
    color*—string—
    createdAt*—integerEpoch milliseconds.
    updatedAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": {
        "id": "tag_01HXEXAMPLE",
        "name": "Priority",
        "color": "amber",
        "createdAt": 1719792000000,
        "updatedAt": 1719792000000
      }
    }

    Example request

    bash
    curl -X POST https://eu1.wextl.com/api/v1/tags \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "color": "..."
    }'
  • PATCH /tags/{id} Auth required

    Rename or recolour a tag.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    namebodystring—
    colorbodystring—
    NameInTypeDescription
    data—Tag—

    data shape (Tag)

    NameInTypeDescription
    id*—string—
    name*—string—
    color*—string—
    createdAt*—integerEpoch milliseconds.
    updatedAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": {
        "id": "tag_01HXEXAMPLE",
        "name": "Priority",
        "color": "amber",
        "createdAt": 1719792000000,
        "updatedAt": 1719792000000
      }
    }

    Example request

    bash
    curl -X PATCH https://eu1.wextl.com/api/v1/tags/tag_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..." \
      -H "Content-Type: application/json" \
      -d '{
      "name": "My workflow",
      "color": "..."
    }'
  • DELETE /tags/{id} Auth required

    Delete a tag and its assignments.

    NameInTypeDescription
    id*pathstring—
    NameInTypeDescription
    data—object—

    data shape (object)

    NameInTypeDescription
    ok—boolean—

    Example response

    json
    {
      "data": {
        "ok": true
      }
    }

    Example request

    bash
    curl -X DELETE https://eu1.wextl.com/api/v1/tags/tag_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."

Webhooks

2endpoints

  • GET /webhooks Auth required

    List inbound webhooks (requires workflow:read).

    NameInTypeDescription
    cursorquerystring—
    limitqueryinteger—
    qquerystring—
    NameInTypeDescription
    data*—array<WebhookSummary>—
    next_cursor*—string | null—

    data[] item (WebhookSummary)

    NameInTypeDescription
    id*—string—
    name*—string—
    url*—string—
    enabled*—boolean—
    method*—string—
    workflowId*—string | null—
    nodeId*—string | null—
    createdAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": [
        {
          "id": "wh_01HXEXAMPLE",
          "name": "Webhook",
          "url": "https://eu1.wextl.com/hooks/wh_01HXEXAMPLE",
          "enabled": true,
          "method": "POST",
          "workflowId": "wf_01HXEXAMPLE",
          "nodeId": "12",
          "createdAt": 1719792000000
        }
      ],
      "next_cursor": null
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/webhooks \
      -H "Authorization: Bearer wextl_..."
  • DELETE /webhooks/{id} Auth required

    Delete a webhook. Pass force=1 if still bound to a workflow.

    NameInTypeDescription
    id*pathstring—
    forcequerystring—
    • 204Deleted.
    • 403Missing workflow:write scope.
    • 404Webhook not found.
    • 409Webhook in use — pass force=1.
    • Common error responses

    Example request

    bash
    curl -X DELETE https://eu1.wextl.com/api/v1/webhooks/wh_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."

Members

1endpoint

  • GET /members Auth required

    List organization members, bounded and cursor-paginated (requires invitation:read / owner-admin).

    NameInTypeDescription
    cursorquerystringOpaque continuation token from a previous response.
    limitqueryintegerPage size. Default 100.
    NameInTypeDescription
    data*—array<Member>—
    next_cursor*—string | null—

    data[] item (Member)

    NameInTypeDescription
    userId*—string—
    email*—string | null—
    name*—string | null—
    role*—string—
    createdAt*—integerEpoch milliseconds.

    Example response

    json
    {
      "data": [
        {
          "userId": "usr_01HXEXAMPLE",
          "email": "ada@example.com",
          "name": "Ada Lovelace",
          "role": "admin",
          "createdAt": 1719792000000
        }
      ],
      "next_cursor": null
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/members \
      -H "Authorization: Bearer wextl_..."

Catalog

3endpoints

  • GET /catalog/apps Auth required

    Search the app and module catalog by keyword. Use the returned app and module ids when creating or updating workflow nodes.

    NameInTypeDescription
    query*querystringSearch keywords (app or capability name).
    limitqueryintegerMax apps to return. Default 10.
    • 200Matching apps with their modules.
    • 400query is required.
    • 403Missing workflow:read scope, or the plan lacks API access.
    • Common error responses
    NameInTypeDescription
    data—array<CatalogApp>—

    data[] item (CatalogApp)

    NameInTypeDescription
    appId*—string—
    name*—string—
    description—string | null—
    modules*—array<object>—

    Example response

    json
    {
      "data": [
        {
          "appId": "slack",
          "name": "My workflow",
          "modules": [
            {
              "id": "abc123",
              "label": "My workflow",
              "type": "action"
            }
          ],
          "description": "..."
        }
      ]
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/catalog/apps \
      -H "Authorization: Bearer wextl_..."
  • GET /catalog/apps/{appId}/modules/{moduleId} Auth required

    Read a module's parameter schema and metadata. Does not expose internal request implementation details.

    NameInTypeDescription
    appId*pathstring—
    moduleId*pathstring—
    • 200The module spec (lean projection — meta + mappable/static fields).
    • 400appId and moduleId are required, or the module cannot be projected for the public API.
    • 403Missing workflow:read scope, or the plan lacks API access.
    • 404Module not found.
    • Common error responses
    NameInTypeDescription
    data—ModuleSpec—

    data shape (ModuleSpec)

    NameInTypeDescription
    meta*—objectCompact module metadata — label, description, which connection it needs, etc. Shape varies per module.
    mappableFields*—array<object>The fields the caller fills at run time (bindable to upstream data). Shape depends on the field type.
    staticFields*—array<object>Fixed UI-configuration params for this module — often empty. Shape depends on the field type.
    emitsMultipleBundles—boolean—
    requiresConnection—boolean—
    connectionOptional—boolean—

    Example response

    json
    {
      "data": {
        "meta": {
          "label": "Send a message",
          "description": "Post a message to a channel.",
          "connection": "oauth2"
        },
        "mappableFields": [
          {
            "name": "channel",
            "label": "Channel",
            "type": "select",
            "required": true
          }
        ],
        "staticFields": [
          {
            "name": "includeAttachments",
            "label": "Include attachments",
            "type": "boolean",
            "required": false
          }
        ],
        "emitsMultipleBundles": true,
        "requiresConnection": true,
        "connectionOptional": true
      }
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/catalog/apps/slack/modules/send_message \
      -H "Authorization: Bearer wextl_..."
  • GET /catalog/nodes/{kind} Auth required

    Read the machine-readable spec for a NATIVE (built-in) workflow node kind — where its data persists, the exact field shape, a copyable example, and its outgoing routes. App/module nodes are not covered here; use GET /catalog/apps/{appId}/modules/{moduleId} for those.

    NameInTypeDescription
    kind*pathstringNative node kind, e.g. 'condition', 'splitter', 'wait', 'js_code'.
    • 200The native node-kind spec.
    • 403Missing workflow:read scope, or the plan lacks API access.
    • 404Unknown kind — use search_catalog for app/module nodes.
    • Common error responses
    NameInTypeDescription
    data—NodeSpec—

    data shape (NodeSpec)

    NameInTypeDescription
    kind*—string—
    label*—string—
    description*—string—
    insertable*—booleanTrue when this kind appears in the builder palette.
    persists_under*—stringWhere this kind's data lives on the node.
    shape*—objectField name -> { type, required, description }.
    example*—objectA filled config/params object for this kind, ready to copy into update_config / update_params.
    routes*—array<string>Outgoing edge types this kind can emit, e.g. 'normal', 'error', 'fallback'.
    expressionGrammar*—stringHow to reference upstream values inside wire strings.
    edgeModel*—stringEdge topology notes — how to wire this kind's outgoing/incoming edges.

    Example response

    json
    {
      "data": {
        "kind": "condition",
        "label": "Condition",
        "description": "Branches execution based on a boolean expression.",
        "insertable": true,
        "persists_under": "config",
        "shape": {
          "conditions": {
            "type": "array",
            "required": true,
            "description": "Ordered list of condition branches."
          }
        },
        "example": {
          "conditions": [
            {
              "expression": "{{1.status}} == \"ok\"",
              "label": "OK"
            }
          ]
        },
        "routes": [
          "normal"
        ],
        "expressionGrammar": "{{nodeId.path}} references an upstream node's output.",
        "edgeModel": "Each condition branch has its own outgoing port, in the order listed."
      }
    }

    Example request

    bash
    curl -X GET https://eu1.wextl.com/api/v1/catalog/nodes/id_01HXEXAMPLE \
      -H "Authorization: Bearer wextl_..."