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.
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.”
| Concept | WebApp-linked execution | ProcessFlow trigger (schedule / event / API) |
|---|---|---|
| Starts from | Published WebApp URL (GET/POST on tenant host) | Scheduler, event broker, or POST /api/v1/processflow?action=fire-trigger |
| Process binding | Fixed process_id on the WebApp | Defined on trigger configuration |
| Default sync | Yes — HTTP waits for steps to finish | Often async when invoked via execute-process with options.async |
| Input shape | HTTP 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.
| Type | Typical use | GET without preview | POST (and uploads) |
|---|---|---|---|
webapp | HTML forms and pages | Serves published HTML only | Runs linked process |
webhook | Inbound HTTP integrations | Runs linked process (query → process_input) | Runs linked process |
callback | Partner callbacks | Same as webhook | Runs linked process |
websocket | Realtime entry (JSON contract) | Serves HTML shell (no process on GET) | Runs linked process |
document-viewer | Controlled document access | HTML + /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
webappandwebsocket: Return the published page (HTML, optional customContent-Typefrom WebApp headers). No process execution.webhookandcallback: Ifprocess_idis set and the request is not preview, the runtime runs the linked process. Query string parameters become top-level keys inprocess_input(same as form fields on POST).
POST
POST always targets automation when a process is configured (after auth, rate limits, and upload handling):
- Chunked file upload — When the body includes
chunk,chunks,unique_id, andname, the runtime stores file parts and responds with JSON upload status; the full process runs on the final submit that includes assembled_attachments. - Multipart or urlencoded forms — Field names map directly into
process_input. application/json— Parsed body fields merge intoprocess_input. A legacypayloadstring field may wrap JSON; invalid JSON falls back to other body fields.- Auth-gated POST — When
auth_requireis 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_routerprocess, the runtime builds a dedicatedprocess_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
AuthorizationandContent-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.
| Source | Maps to process_input |
|---|---|
| Form fields / JSON body | Same key names as submitted |
| Query string (webhook/callback GET) | Query keys |
| Verified end-user JWT | auth_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:
| Variable | Meaning |
|---|---|
raw_input | Raw request body string (empty when none); use for signature verification (e.g. Stripe webhooks) |
http_headers | Incoming headers (title-cased names) |
request_method | HTTP method |
request_uri | Request URI path and query |
remote_addr | Client IP (respects X-Forwarded-For where configured) |
simulated_http | Legacy $_SERVER-style map for compatibility |
webapp_tenant_id | Tenant 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
- Published version — Draft WebApps are not served on public URLs; confirm the intended version is published.
process_idandwebapp_user_id— Both must be set; missing either fails before or during execution.- Wrong HTTP method — Standard pages only run the process on POST; webhook verification on GET requires type
webhookorcallback. - Preview — Preview GET never runs the process; test with a real published URL.
- Timeouts — Sync execution blocks the HTTP request; queue long work via async trigger pattern.
- Response drift — Compare execution logs and process output to Process Response Reference if clients expect fields that changed.
See also
- WebApps User Guide
- ProcessFlow Triggers Guide
- WebApps Process Response Reference
- WebApps Authentication
- WebApp Async Process Trigger Guide
- Automations and ProcessFlow Introduction
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.