WebApps and ProcessFlow Integration Guide

Document information
  • Canonical URL: /docs/05_apps-webhooks-and-surfaces/18_webapp-processflow-integration-guide
  • Version: 2026-09-26
  • Tags: webapps, processflow, triggers, guides

This guide connects the WebApp runtime to ProcessFlow execution: when a published WebApp starts its linked process, which HTTP methods apply, what lands in process_input, and how responses flow back to browsers, webhooks, and API callers. Use it after the WebApps User Guide when you need the full request-to-process contract, not only UI setup.

WebApp lifecycle illustration showing authoring, process integration, version publishing, public URL access, and execution log monitoring.

How WebApps attach to ProcessFlow

Every published WebApp record points at exactly one ProcessFlow process through process_id. When the runtime decides a request should run automation, it calls executeProcess synchronously (async: false) for that process_id only. The process runs as the configured webapp_user_id service account, not as the tenant admin who authored the WebApp.

That model is different from ProcessFlow triggers configured on a process (schedule, platform event, or fire-trigger with a compiled trigger_id). Triggers start runs from the scheduler or event bus. WebApp runs start from HTTP traffic on the published URL. A single process can have UI triggers and separate trigger definitions; the WebApp link is always “run this process when this surface receives an executable request.”

ConceptWebApp-linked executionProcessFlow trigger (schedule / event / API)
Starts fromPublished WebApp URL (GET/POST on tenant host)Scheduler, event broker, or POST /api/v1/processflow?action=fire-trigger
Process bindingFixed process_id on the WebAppDefined on trigger configuration
Default syncYes — HTTP waits for steps to finishOften async when invoked via execute-process with options.async
Input shapeHTTP payload → process_input (+ sandbox metadata)input_data from API or trigger payload

For long-running work without blocking HTTP, use the WebApp Async Process Trigger Guide (stub process + queued target process).

WebApp types and when the process runs

The WebApp type controls HTML vs JSON surfaces and whether GET can execute the linked process.

TypeTypical useGET without previewPOST (and uploads)
webappHTML forms and pagesServes published HTML onlyRuns linked process
webhookInbound HTTP integrationsRuns linked process (query → process_input)Runs linked process
callbackPartner callbacksSame as webhookRuns linked process
websocketRealtime entry (JSON contract)Serves HTML shell (no process on GET)Runs linked process
document-viewerControlled document accessHTML + /api/* routing/api/* via api_router process

Preview mode (?preview=true or console referer) always serves HTML and does not execute the process on GET, even for webhook types.

Supported methods on the published runtime are GET, POST, and OPTIONS (CORS preflight). Other methods receive 405 Method Not Allowed.

HTTP methods in detail

GET

  • webapp and websocket: Return the published page (HTML, optional custom Content-Type from WebApp headers). No process execution.
  • webhook and callback: If process_id is set and the request is not preview, the runtime runs the linked process. Query string parameters become top-level keys in process_input (same as form fields on POST).

POST

POST always targets automation when a process is configured (after auth, rate limits, and upload handling):

  1. Chunked file upload — When the body includes chunk, chunks, unique_id, and name, the runtime stores file parts and responds with JSON upload status; the full process runs on the final submit that includes assembled _attachments.
  2. Multipart or urlencoded forms — Field names map directly into process_input.
  3. application/json — Parsed body fields merge into process_input. A legacy payload string field may wrap JSON; invalid JSON falls back to other body fields.
  4. Auth-gated POST — When auth_require is enabled, missing or invalid end-user tokens return 401 and the process does not run. See WebApps Authentication.

OPTIONS

Returns CORS headers allowing GET, POST, and OPTIONS with common request headers. Credentials are not enabled on CORS (Access-Control-Allow-Credentials: false); cross-origin clients should use Bearer tokens.

/api/* paths

Requests whose path tail starts with api/ are handled separately:

  • If the linked process is an api_router process, the runtime builds a dedicated process_input (see below) and returns HTTP status, headers, and body from process output.
  • Otherwise the runtime may proxy to the tenant product API with the caller’s Authorization and Content-Type.

Login and session issuance for custom WebApps normally use the root POST JSON contract, not product /api/v1/auth/login.

What becomes process_input

For standard form and JSON POST (and webhook/callback GET), the runtime passes a flat object as ProcessFlow input_data, which step code reads as process_input.

SourceMaps to process_input
Form fields / JSON bodySame key names as submitted
Query string (webhook/callback GET)Query keys
Verified end-user JWTauth_token, auth (user_id, email, role, webapp_id, type)
File uploads_attachments (metadata array), _storage_path
Client correlation_execution_id (reuse client value when valid, else new UUID)

The runtime also attaches a webapp execution context (webapp_execution_context) so internal api calls from the process stay scoped to the WebApp’s bound process_id and tenant.

Sandbox envelope (HTTP metadata in steps)

Alongside process_input, WebApp-triggered runs receive sandbox fields derived from the incoming HTTP request:

VariableMeaning
raw_inputRaw request body string (empty when none); use for signature verification (e.g. Stripe webhooks)
http_headersIncoming headers (title-cased names)
request_methodHTTP method
request_uriRequest URI path and query
remote_addrClient IP (respects X-Forwarded-For where configured)
simulated_httpLegacy $_SERVER-style map for compatibility
webapp_tenant_idTenant resolved from host / headers / query

These fields exist so step code can validate signatures, branch on headers, or audit callers without re-parsing the outer HTTP layer.

api_router POST to /api/...

When the linked process type is api_router, process_input is structured for routing logic:

{
  "request_uri": "/api/your/route",
  "request_method": "POST",
  "request_headers": { "Authorization": "Bearer …", "Content-Type": "application/json" },
  "request_body": "{ … raw string … }",
  "query_string": "limit=10",
  "token": "<optional>",
  "auth_token": "<optional>",
  "auth": { "user_id": "…", "email": "…", "role": "…", "webapp_id": "…", "type": "webapp_access" },
  "tenant_id": "<TENANT_ID>",
  "webapp_id": "<WEBAPP_ID>",
  "process_config": { }
}

Return http_code, headers, and string body from the last step when you need full control over the HTTP response.

Outbound response envelopes

Trace AI and platform-code-specialist should treat this section as the canonical HTTP POST JSON contract (webapp_post_http_envelope). Step-level return fields (process_step_return) live inside result.output_data. Agent summary: Platform code generation — WebApp POST response.

Process step output is normalized, then the runtime maps it to HTTP based on WebApp type and entry path (subdomain vs public URI).

JSON types (webapp, webhook, callback, websocket)

Successful POST responses use a wrapper envelope:

{
  "success": true,
  "result": {
    "success": true,
    "execution_id": "<EXECUTION_ID>",
    "process_id": "<PROCESS_ID>",
    "output_data": { },
    "data": { }
  },
  "execution_time_ms": 42
}

Failed runs return success: false with an errors array (and optional http_code from process output). Field-level contracts inside result / output_data — redirects, cookies, custom status — are documented in WebApps Process Response Reference.

Auth cookies (tf_session) are applied from process output when auth_transport is cookie or both. Bearer-only WebApps skip cookie rewrite.

Browser HTML (webapp on some entry paths)

When the runtime serves HTML after POST, success may re-render the published page, follow action_url redirects, or show an error HTML page. JSON POST types always return JSON, even on subdomain hosts.

Calling from step code vs from outside

Inside a WebApp-triggered process, use the injected api client to call product endpoints or execute-process (tenant context and execution auth stay consistent). External systems calling Tealfabric directly use X-API-Key and X-Tenant-ID as described in ProcessFlow API documentation. Do not use raw fetch to internal URLs from step code unless you intentionally bypass those guards.

End-to-end flow

Browser or partner HTTP client
        │
        ▼
Published WebApp URL (tenant host)
        │  resolve tenant, rate limit, load published version
        ▼
Auth (optional) ──401──► stop
        │
        ▼
Build process_input + sandbox envelope
        │
        ▼
executeProcess(process_id, input_data, webapp_execution_context)
        │  runs as webapp_user_id, sync by default
        ▼
Map process output → JSON / HTML / redirect / api_router HTTP
        │
        ▼
WebApp execution log (method, status, masked request_data)

Troubleshooting checklist

  1. Published version — Draft WebApps are not served on public URLs; confirm the intended version is published.
  2. process_id and webapp_user_id — Both must be set; missing either fails before or during execution.
  3. Wrong HTTP method — Standard pages only run the process on POST; webhook verification on GET requires type webhook or callback.
  4. Preview — Preview GET never runs the process; test with a real published URL.
  5. Timeouts — Sync execution blocks the HTTP request; queue long work via async trigger pattern.
  6. Response drift — Compare execution logs and process output to Process Response Reference if clients expect fields that changed.

See also

Treat the WebApp URL as the public contract and process_input as the automation contract. When both stay stable, you can change step implementations without breaking forms, partners, or client JavaScript.