Web-Nothing Docs
Guides

Cross-App Workflows

Cross-App Workflows

Workflows connect your Web-Nothing apps so that events in one app automatically trigger actions in another. When something happens in a source app (e.g., a new order is created), a workflow can automatically create a record in a target app, send a webhook, or send an email -- no manual intervention needed.


How Workflows Work

A workflow has four parts:

  1. Trigger -- what event to watch for (e.g., a new record is created)
  2. Condition (optional) -- a filter that must be true for the workflow to fire (e.g., amount > $500)
  3. Field Mapping -- how to transform the source data for the target
  4. Action -- what to do (create a record, send a webhook, or send an email)

Workflows run automatically in the background whenever the trigger event occurs. They never slow down the original action.


Triggers

Every workflow watches for one trigger type on a source app:

TriggerFires when
Record createdA new record is added to the source data table
Record updatedAn existing record is modified
Record deletedA record is removed
Webhook receivedAn external service sends data to the app's webhook
API response receivedAn API connector call completes and stores data
Time-based reminderN minutes before or after a record's datetime field — see below

Webhook and API response triggers fire in addition to the record-created trigger, so a single inbound event can match multiple workflows.


Time-based reminders

Use the time-based reminder trigger to fire a workflow N minutes before or after a record's datetime field. Common use cases:

  • Booking reminders — email a customer 24 hours before their appointment so they actually show up.
  • Follow-up surveys — send a feedback form 60 minutes after a session ends.
  • Renewal warnings — heads-up email 7 days before a subscription auto-renews.
  • Dunning campaigns — escalation email 3 days after an invoice goes unpaid.

How it works

When a record is created (or updated, with the datetime field changed), the platform queues a reminder for record[dateField] + offsetMinutes. A scheduled background worker fires due reminders.

You provide two extra fields when configuring the workflow:

FieldMeaningExample
dateFieldName of the datetime field driving the schedule"slot_datetime"
offsetMinutesMinutes from the datetime field. Negative = before, positive = after.-1440 (24h before), 60 (1h after)

Example — 24-hour booking reminder

{
  "name": "Lesson Reminder",
  "description": "Email tutor + student 24h before each lesson",
  "sourceAppId": "...",
  "sourceSchema": "appointments",
  "trigger": "scheduled_offset_from_field",
  "offsetMinutes": -1440,
  "dateField": "slot_datetime",
  "action": "send_email",
  "fieldMapping": {
    "_email_to": "{{source.student_email}}",
    "_email_subject": "Reminder: lesson with {{source.tutor_name}} tomorrow",
    "_email_body": "Hi {{source.student_name}}, reminder that your lesson is tomorrow at {{source.slot_datetime}}."
  }
}

Reminder timing precision (depends on plan)

The scheduled worker runs on a fixed cron interval set by the platform's hosting plan:

PlanCron intervalPractical precision
HobbyDaily (09:00 UTC)±24 hours
ProEvery 5 minutes±5 minutes

Choose offsets that match your plan's precision:

  • 24-hour-before reminders work on both plans. The reminder fires on the morning of the target day.
  • 1-hour-before reminders are only reliable on Pro. On Hobby, they may fire 0–23 hours early because the worker only runs once per day.
  • For sub-hour precision, upgrade to Pro.

This is explicit degradation, not silent. Reminders always fire for the correct event, just possibly earlier than the exact offsetMinutes would suggest.

What happens when the source record changes

EventBehaviour
dateField changed (e.g. customer reschedules)Old pending reminder is cancelled; new one queued for the new fireAt
Other fields changed (dateField unchanged)Reminder unchanged — same fireAt
Source record deletedAll pending reminders for that record are cancelled
Past-due at creation (e.g. record's slot already happened)Schedule is silently cancelled — no spam reminders for already-happened events
Cron is late (Vercel retry, server downtime)Reminder still fires when the worker next runs — better late than never

Limits

  • Maximum pending reminders per app: 10,000. New schedules beyond the cap are rejected with a clear audit-trail entry.
  • Per-workflow rate limit: scheduled fires share the workflow's maxPerHour cap (default 10) with immediate fires.
  • Offset range: offsetMinutes must be between -525600 (1 year before) and 525600 (1 year after).

Owner observability

Each workflow exposes a summary endpoint (GET /api/apps/[appId]/workflows/[workflowId]/scheduled-summary) returning:

{ "pending": 3, "lastFireAt": "2026-05-07T09:00:00.000Z" }
  • pending = number of reminders queued and waiting to fire
  • lastFireAt = timestamp of the most recent successful fire (null if never fired)

Use this in your dashboards or admin UI to surface "Next 3 reminders queued · last fired 2 hours ago".


Conditions

A workflow can include an optional condition. If the condition evaluates to false, the workflow is skipped.

Condition structure

{
  "field": "amount",
  "operator": "gt",
  "value": 500
}

Available operators

OperatorMeaning
eqEqual
neqNot equal
gtGreater than
gteGreater than or equal
ltLess than
lteLess than or equal
containsContains substring (case-insensitive)
existsField has a value
not_existsField is empty or missing

Actions

ActionWhat it does
Create recordCreates a new record in the target app's data table
Send webhookPOSTs the mapped data to an external URL (HTTPS required)
Send emailSends an email using the platform's email service
Send SMSSends a text message via your configured SMS provider (e.g. Twilio)

Send Email Details

The send email action sends transactional emails triggered by workflow events.

Required field mapping keys:

KeyRequiredDescription
_email_toYesRecipient email address
_email_subjectYesEmail subject line
_email_bodyYesEmail body (rendered as HTML and plain text)
_email_reply_toNoReply-to address

Example field mapping for email:

{
  "_email_to": "{{source.customer_email}}",
  "_email_subject": "Booking Confirmed: {{source.service_name}}",
  "_email_body": "Hi {{source.customer_name}},\n\nYour booking for {{source.service_name}} on {{source.date}} at {{source.time}} is confirmed.\n\nThank you!"
}

Email rate limits:

LevelLimitWindow
Platform-wide80 emails24 hours
Per user50 emails24 hours
Per recipient5 emails24 hours

Every email includes an automatic unsubscribe link. When a recipient unsubscribes, all future emails from that app to them are silently skipped.

Send SMS Details

The send SMS action sends transactional text messages triggered by workflow events. The platform itself does not provide SMS sending — instead, you connect your own SMS provider account (Twilio or a Twilio-compatible REST API) via an API connector, and the workflow dispatches messages on your behalf using your provider credentials.

Required field mapping keys:

KeyRequiredDescription
_sms_toYesRecipient phone number in E.164 format (e.g. +14155551234)
_sms_bodyYesText message body (max 1600 characters, roughly 10 SMS segments)
_sms_fromYesSender phone number from your SMS provider account
_sms_connector_idYesThe id of the SMS API connector you configured (see below)

Setting up the SMS connector (one-time):

  1. Sign up for a Twilio account (or any Twilio-compatible SMS provider) and obtain an Account SID, Auth Token, and a sending phone number.
  2. In the Web-Nothing API connectors page, create a new connector:
    • Base URL: https://api.twilio.com/2010-04-01/Accounts/<YourAccountSid>
    • Auth type: Basic Auth
    • Username: your Account SID
    • Password: your Auth Token
  3. Save the connector and copy its id — you'll paste this into _sms_connector_id on workflows.

Credentials are encrypted at rest with the same key-encryption-key used for all API connector secrets. The platform decrypts only at send time, builds the HTTP Basic auth header in memory, and never logs or returns the username or password.

Example field mapping for an appointment reminder SMS:

{
  "_sms_to": "{{source.customer_phone}}",
  "_sms_body": "Hi {{source.customer_name}}, this is a reminder of your appointment for {{source.service_name}} at {{source.appointment_at}}. Reply STOP to opt out.",
  "_sms_from": "+15551234567",
  "_sms_connector_id": "ck_abc123..."
}

SMS rate limits:

LevelLimitWindow
Platform-wide80 messages24 hours
Per user50 messages24 hours
Per recipient5 messages24 hours

These are defense-in-depth caps. Your provider also enforces its own rate and cost limits — review them in your provider dashboard.

Regulatory note (customer responsibility):

Twilio (and most major SMS providers) automatically handle STOP / UNSUBSCRIBE replies at the carrier level — opt-out is enforced by your provider, not by Web-Nothing. If you operate in regulated markets (US TCPA, UK ICO, EU GDPR), review your provider's opt-out behavior and obtain prior consent before sending marketing SMS. Time-of-purchase and appointment-confirmation SMS to customers who explicitly opted in is generally permissible; broadcast marketing without consent is not. This is not legal advice — consult your own legal counsel.


Field Mapping

Field mapping defines how source record values are transformed for the target. Use {{source.fieldName}} to reference fields from the source record.

{
  "customer_name": "{{source.name}}",
  "order_total": "{{source.amount}}",
  "source_info": "Order from {{source.store}} on {{source.date}}",
  "priority": "high"
}

Rules:

  • {{source.fieldName}} is replaced with the value from the source record. Missing fields resolve to empty string.
  • Multiple templates can appear in one value (e.g., "{{source.first}} {{source.last}}").
  • Numeric values are preserved as numbers.
  • Literal values (no templates) are passed through as-is.

Creating Workflows

The easiest way to create workflows is through the platform MCP endpoint. Describe what you want in natural language, and the AI generates the full workflow.

Example prompt:

"When an expense over $500 is created in my Finance app, create a high-priority task in my CRM"

The AI generates the complete workflow with the correct source/target apps, trigger, condition, and field mapping.

MCP tools for workflow management:

ToolDescription
workflows_createCreate a workflow from a natural language prompt
workflows_listList all your workflows with execution stats
workflows_toggleEnable or disable a workflow

All workflow tools require a PLATFORM-scoped agent token.

Requirements

  • You need at least 1 active app to create a workflow
  • Create record actions require 2 apps (source + target)
  • Send webhook and send email actions only require a source app

Chaining

Workflows can chain: when a workflow creates a record in App B, that creation can fire workflows watching App B, which may create records in App C, and so on.

App A (new record) → Workflow 1 → App B (create record)
                                      → Workflow 2 → App C (create record)
                                                         → Workflow 3 → App D
                                                              (chain limit reached → stop)

Safety limits:

  • Default chain depth: 3 levels (configurable per workflow, up to 10)
  • Hard safety cap: 10 levels maximum
  • Send webhook and send email actions do not trigger downstream chains

Rate Limits

Each workflow is limited to 10 executions per hour by default. This prevents a single misconfigured workflow from flooding your apps with data. The limit resets every hour.


Example: Order to Audit Trail

Scenario: Every time a high-value order (over $1,000) is created in your Order Tracker app, automatically log it in your Audit Log app.

Workflow definition:

{
  "name": "High-Value Order Audit",
  "description": "Logs orders over $1000 to the audit trail",
  "sourceAppId": "<order-tracker-id>",
  "sourceSchema": "orders",
  "trigger": "record_created",
  "condition": {
    "field": "total",
    "operator": "gt",
    "value": 1000
  },
  "action": "create_record",
  "targetAppId": "<audit-log-id>",
  "targetSchema": "entries",
  "fieldMapping": {
    "event_type": "high_value_order",
    "description": "Order #{{source.order_number}} for ${{source.total}} by {{source.customer}}",
    "severity": "warning",
    "source_id": "{{source.id}}"
  }
}

What happens: When a user creates an order for $2,500, the workflow fires, the condition passes (2500 > 1000), the fields are mapped, and a new record appears in the Audit Log with the order details.


Live execution status

Cross-app workflows fire asynchronously — the source action commits and returns immediately while the target write happens in the background. To surface a "your order has been received → being prepared → ready" view to a customer, drop a workflow-status component on the page and bind it to the source record id.

The component polls every 2 seconds and shows one badge per execution: queued, processing, succeeded, failed, skipped, or retrying. Polling stops automatically once all executions reach a terminal state.

For public order-status pages, enable visibility on the app, then link customers to /?order_id=<id> so the component reads {{query.order_id}} to scope the status surface to their record only.

If the source record is committed but the workflow fails (e.g. the target app rejects the schema), the source data is kept — workflows are status-tracked, not transactional, across apps.


TopicDocument
Receiving data from external servicesWebhooks
Connecting external APIsAPI Connectors
Connecting AI agentsMCP Quick Start
Full MCP referenceMCP Integration Guide
Modifying apps via chatAgent Chat Guide
Full user guideUser Guide

On this page