# Node replace a Zap

A lead intake workflow accepts form submissions, routes urgent and event requests, rejects duplicates, and builds a daily digest with a JSON archive. Tokay runs the receiver as a Function and the digest as a Scheduled Service over one PostgreSQL database.

Use this example when a visual automation has become important enough that you want its decisions in ordinary code. You can inspect each trigger, change the routing rule, and keep the resulting data in your own Project.

## Facts

- Runtime: Node.js
- Framework: Express
- Service types: Function, Scheduled Service
- Resources: PostgreSQL, Persistent files
- Required secrets: None

## What it does

Send a name, email, service, and optional notes to `/submit`. The response tells you whether the lead entered the `priority`, `events`, or `general` route.

Repeat the same duplicate key and PostgreSQL keeps one lead while reporting the second request as a duplicate.

When the digest runs, its result counts each route and lists the last 24 hours of requests. **Saved Files** keeps a complete JSON archive for every run.

## Deploy it

Bring this folder to Tokay any way you like. Paste or upload it in the dashboard, push it with git, or hand it to your AI agent along with [our agent instructions](https://app.tokay.io/llms.txt). Tokay figures out the rest.

Working in Claude, ChatGPT, VS Code, or another MCP client? Connect the [Tokay MCP server](https://tokay.io/docs/platform-mcp) and ask your agent to deploy this example. It signs in through your browser, so there is no token to paste.

New to Tokay? The [getting started guide](https://tokay.io/getting-started) walks you through your first deploy.

## Try it

1. Copy the Function URL from the top of the receiver Service page. Replace the placeholder below with that URL, then send this urgent lead.

```sh
export FUNCTION_URL="https://your-function-url"
curl -X POST "$FUNCTION_URL/submit" \
  -H 'Content-Type: application/json' \
  -H 'x-dedupe-key: patio-lights-001' \
  -d '{"name":"Mira Chen","email":"mira@example.test","service":"patio lighting","notes":"The old transformer is broken and the event is Friday."}'
```

2. Send the same command again and confirm the response now reports a duplicate.
3. Choose **Run Now** on the digest Service. Mira appears once under `priority`, and the archive is available in **Saved Files**.

## How it works

You can find the whole automation boundary in two places. `/submit` replaces the trigger and `routeLead` owns the decision, while the schedule lives in Tokay where you can inspect or start a run.

The receiver honors `x-dedupe-key` or derives one from the payload. PostgreSQL increments a duplicate count instead of inserting the same lead twice. The digest reads the last 24 hours and writes its archive under Tokay's persistent data directory.

When you move another workflow, add a route for its trigger and express the decision in code. Give it another Scheduled Service only when it truly needs a separate clock.

## Secrets

| Name | Required | Purpose |
| --- | --- | --- |
| `ALERT_WEBHOOK_URL` | No | Delivers the digest to a Discord or Slack compatible webhook. Add it as a Project Secret on the digest only. |

`DATABASE_URL` comes from the shared managed PostgreSQL resource. It is not a Project Secret.

## Grow from here

Try the [webhook inspector](/examples/node-webhook-inspector) when you want to study request validation and replay before adding workflow logic.

## Source files

- [digest/digest.js](https://tokay.io/examples/src/node-replace-a-zap/digest/digest.js)
- [digest/package.json](https://tokay.io/examples/src/node-replace-a-zap/digest/package.json)
- [receiver/.gmrc](https://tokay.io/examples/src/node-replace-a-zap/receiver/.gmrc)
- [receiver/migrations/committed/000001-lead-requests.sql](https://tokay.io/examples/src/node-replace-a-zap/receiver/migrations/committed/000001-lead-requests.sql)
- [receiver/package.json](https://tokay.io/examples/src/node-replace-a-zap/receiver/package.json)
- [receiver/server.js](https://tokay.io/examples/src/node-replace-a-zap/receiver/server.js)

## Download and source

- [Download the complete project](https://tokay.io/examples/downloads/node-replace-a-zap.zip)
- Last updated: 2026-07-31
- Example revision: `52c7b7f`
- [View this revision on GitHub](https://github.com/tokayio/tokay-examples/tree/52c7b7ffd52e157375b08f1f11ff4fbe6c498642/node-replace-a-zap)
- [Replace Zapier with code](https://tokay.io/use-cases/replace-zapier-with-code)
