master-zapier-plan-draft/research/zapier/getting-started.md
George Lambert b4150c8250 Milestone 0: import zappier billing, Verae middleware, and Zapier research
Compose-ready workspace: packages/zappier (rate card, portal, Stripe),
packages/verae-zapier-middleware (timestamp + NATS), packages/verae-zapier
(CLI app), vendor/zapier-platform, and research/zapier vendor corpus.

Gate 0 structure checks pass. Product code and research are not yet wired.
2026-09-09 02:37:36 -04:00

38 KiB
Raw Blame History

Getting started — Verae Time × Zapier

System architecture, functionality, integration guide, and next steps

This is the working document for the research workspace at /Users/marchon/research/zapier. It covers the full stack that connects Zapier automations to the Verae Timestamping Service, how to run and extend it locally, Zapier vs Verae billing, a client pattern for timestamped files on Peergos/IPFS with cold retrieve-on-demand, and what remains before a private Zapier listing.

Grok (and humans) should start here, then follow the playbook in PLATFORM-REFERENCE.md.


1. How to start this workspace

cd /Users/marchon/research/zapier
./scripts/restart-grok.sh    # Mongo tunnel + grok --resume

Already in Grok:

/zapier-build

Mandatory first query (same playbook as PLATFORM-REFERENCE.md):

db.platform_reference.findOne({ kind: "guide", key: "build-new-connector" })

Keep the Mongo tunnel up (./scripts/ensure-mongo-tunnel.sh). Check readiness with ./scripts/zapier-status.sh. Load CLI PATH and env with source scripts/dev-env.sh.

Leave the TUI with /quit (not /new). Restart details: RESTART.md.


2. System architecture

2.1 Purpose

Connect Zapier automations to Verae blockchain timestamping without:

  • exposing raw Verae JWTs to Zapier end users
  • requiring Zapier to poll async jobs on api.veraetime.net
  • coupling billing and plan limits to the core timestamping API
  • running a multi-instance edge with only in-memory job queues

2.2 Bottom line

High-level architecture: Zapier cloud, middleware, NATS workers, Verae API, and REST Hooks

Users → Zapier UI
Zapier cloud runs the Platform CLI app (verae-zapier or scratch/veraetime)
  → HTTPS only → verae-zapier-middleware  /zapier/v1/*
       → (sync)  HTTPS → https://api.veraetime.net
       → (async) NATS JetStream → workers
                    → HTTPS → api.veraetime.net  (status poll)
                    → HTTPS → hooks.zapier.com   (REST Hook delivery)
  • Zapier never connects to NATS.
  • Zapier never calls api.veraetime.net directly.
  • Middleware HTTP owns auth, tenancy, entitlements, metering, and the public API surface.
  • NATS owns durable job watching, completion events, and reliable webhook delivery (when NATS_ENABLED=true).
  • With NATS_ENABLED=false, an in-process poller still implements the same HTTP product path (Phase 6).

2.3 Components

Component Runs where Role
Zapier Platform CLI app Zapier cloud (when a Zap step runs) Auth fields, map operations to /zapier/v1/*, attach Bearer token, translate 402/403
verae-zapier-middleware Your infrastructure, public HTTPS Tenant identity, API keys, Verae login bridge, entitlements, REST Hook storage, publish work to NATS
NATS + JetStream Private network with middleware Work queues for job watch and webhook delivery; event stream for terminal job states
Workers Same deploy or separate processes Job poller, event router, webhook deliverer
api.veraetime.net Verae production Source of truth: login, timestamp jobs, status, verification

Zapier app (two copies in this repo)

Path Language Auth Status
verae-zapier-api/verae-zapier/ JavaScript Custom API key (zmw_…) Phase 11 package; MIDDLEWARE_BASE_URL env
scratch/veraetime/ TypeScript (CLI 19.1.0) Session: username/password or API key → accessToken Local golden connector; build + validate

Both talk only to middleware. The TypeScript app is the one this workspace validates day-to-day. The JavaScript app is the vendored product package from the middleware monorepo.

The Zapier app does not: call api.veraetime.net, speak NATS, or enforce plan quotas.

Middleware HTTP edge

Middleware internals: public and protected /zapier/v1 routes, store, and flags

Path: verae-zapier-api/verae-zapier-middleware/

  • Express app: GET /health, mount /zapier
  • Public: POST /zapier/v1/auth/login, GET /zapier/v1/auth/me, tenant signup
  • Protected (Bearer or x-api-key + rate limit): timestamp, verify, status, webhooks
  • Admin: /zapier/v1/admin/* behind X-Admin-Secret
  • Store: file JSON MVP (STORE_PATH, default ./data/store.json) — single-node only

NATS + workers

Worker Consumes Calls
Job poller verae.zapier.jobs.watch GET /api/status/{jobId} on Verae
Event router verae.zapier.jobs.events Enqueues webhook deliveries
Webhook deliver verae.zapier.webhooks.deliver POST Zapier targetUrl

Streams: ZAPIER_JOBS, ZAPIER_EVENTS, ZAPIER_WEBHOOKS (optional ZAPIER_USAGE).

Verae Timestamping Service

2.4 Security boundaries

Security boundaries: public HTTPS versus private NATS, store, and Verae JWT

Public Internet
  ├─ Zapier cloud → Middleware HTTPS only
  └─ Middleware → Zapier REST Hook HTTPS only

Private
  ├─ Middleware ↔ NATS  (never expose NATS ports)
  └─ Middleware / workers → api.veraetime.net HTTPS

Rules:

  • Never put raw Verae JWTs in NATS when a tokenRef will do.
  • Never expose NATS (4222) to the public internet.
  • Debug logs must redact Bearer, zmw_, zmt_, passwords, and hook query secrets.
  • Treat targetUrl as untrusted egress (timeouts; SSRF allowlist is Phase 15).
  • Do not commit ~/.zapierrc, .env, store.json, or ~/.mcp-env.

2.5 Scaling model

  • HTTP edge: stateless replicas behind a load balancer, except they share a store. File JSON is single-node. Multi-node needs Postgres/Redis (Phase 15).
  • NATS consumers: queue groups — more workers increase poll/deliver throughput; two workers must not double-complete the same job.
  • Rollback: NATS_ENABLED=false still serves the full HTTP API with the in-process poller.

3. Functionality

3.1 Authentication (two hops)

Two-hop authentication: user to middleware tokens; middleware to Verae JWT

End user → middleware

Mode What the user enters What happens
Session (TypeScript app) Username + password, or middleware API key POST /zapier/v1/auth/login{ accessToken } stored as sessionKey
Custom key (JS app) Tenant API key zmw_… Sent as Authorization: Bearer on every request; test is GET /zapier/v1/auth/me

Connection test: GET /zapier/v1/auth/me → tenant, plan, usage. Connection label: username/plan (TS) or tenantId (plan) (JS).

401 on later calls: TypeScript app throws z.errors.RefreshAuthError so Zapier re-runs session perform.

Middleware → Verae

Middleware logs into Verae with the tenants Verae credentials (or mock client when MOCK_VERAE=true) and holds the JWT server-side. Zapier never sees that JWT.

Token types issued by middleware:

Prefix Kind
zmw_ Tenant API key (long-lived)
zmt_ Middleware session token (HMAC, TOKEN_SECRET)

3.2 Zapier operations ↔ middleware ↔ Verae

Operations map: Zapier nouns to /zapier/v1 to Verae

All Zapier routes are under /zapier/v1. Connector default base: http://127.0.0.1:3100. Production base is the deployed middleware, not api.veraetime.net.

Zapier noun Type Middleware Verae (what middleware wraps) Notes
Create Timestamp create POST /timestamp POST /api/timestamp Returns { jobId } (202). Use with the hook trigger.
Create Timestamp and Wait create POST /timestamp/wait create + poll/wait Returns terminal status, or pending + jobId on timeout.
Create Batch Timestamps create POST /timestamp/batch POST /api/batch/timestamp { items: [{ data, hashAlg? }] }
Verify Certificate create POST /verify POST /api/verify { certificate }{ valid, timestamp, blockIndex }
Find Job Status search GET /status/{jobId} GET /api/status/{jobId} Search: empty array if 404.
Find Job Verification search (TS only) GET /status/{jobId}/verification GET /api/verify/{jobId} Search.
Timestamp Completed hook trigger POST /webhooks/subscribe · DELETE /webhooks/unsubscribe (no Verae hook) Event timestamp.completed; Zapier supplies targetUrl.

Not in v1 (admin HTML / user admin on Verae): dashboard, metrics, queue UI, user CRUD, batch verify/status, get-block-by-hash. Add later if a Zap needs them.

Create input (timestamp): required data (text), optional hashAlg (default SHA256).

3.3 Request flows

A. Create Timestamp (async + hook)

Create Timestamp sequence: async job plus REST Hook

Zapier → POST /zapier/v1/timestamp
Middleware: authenticate, checkEntitlement, POST /api/timestamp
Middleware: publish jobs.watch → return 202 { jobId }
Worker: poll GET /api/status/{jobId} until terminal → publish jobs.events
Event router: match webhooks → publish webhooks.deliver
Webhook worker: POST hooks.zapier.com/...  (timestamp.completed)
Zapier trigger: Timestamp Completed fires the rest of the Zap

B. Create Timestamp and Wait

Create Timestamp and Wait: in-process path versus Phase 9 NATS

Zapier → POST /zapier/v1/timestamp/wait
Middleware: create + wait (in-process if NATS off; NATS events when Phase 9 lands)
→ StatusResponse (completed/failed) or { jobId, status: "pending" } on timeout

Today, wait works on the in-process path (NATS_ENABLED=false). Wait-via-NATS is Phase 9 (open).

C. Auth connection test

Zapier → GET /zapier/v1/auth/me   Authorization: Bearer zmw_… or zmt_…
Middleware: resolve key/session → tenant → optional validate Verae token
→ { tenantId, plan, usage, ... }

3.4 NATS subjects (private)

NATS topology: streams, subjects, consumers, and ack rules

Subject Publisher Consumer Payload gist
verae.zapier.jobs.watch HTTP edge after create job-poller (queue) tenantId, jobId, tokenRef, attempts, traceId
verae.zapier.jobs.events Job poller (terminal) Event router; optional HTTP waiters timestamp.completed|failed|timeout, status object
verae.zapier.webhooks.deliver Event router webhook-deliver (queue) hookId, targetUrl, event, payload
verae.zapier.usage optional usage-writer metering increment

Ack: still-pending jobs Nak with delay; terminal Ack after publishing the event; webhook 2xx Ack; 5xx redeliver until max_deliver.

3.5 Entitlements and errors the connector must surface

HTTP Meaning Zapier mapping
401 Bad or expired session/key RefreshAuthError (session) or auth error
402 Quota exceeded User-visible error + upgrade URL when present
403 PLAN_UPGRADE_REQUIRED Action not on this plan User-visible error
404 on status search Unknown job Return [] (search contract)

JS app afterResponse already maps 402/403. TypeScript app currently remaps 401 only — 402/403 mapping is a next-step item.

3.6 Feature flags and environment

Variable Default Purpose
PORT 3100 Middleware listen port
VERAE_API_BASE_URL http://localhost:8080 Upstream Verae (prod: https://api.veraetime.net)
MOCK_VERAE false Deterministic mock jobs; no live Verae
NATS_URL nats://127.0.0.1:4222 NATS server
NATS_ENABLED false JetStream workers vs in-process poller
TOKEN_SECRET dev secret HMAC for zmt_ session tokens
DEBUG_VERAE unset Namespaces: auth, nats, jobs, webhooks, http, billing (or 1 for all)
DEBUG_VERAE_LEVEL debug debug | info | warn | error
STORE_PATH ./data/store.json MVP tenant/usage/webhook store
MIDDLEWARE_BASE_URL http://127.0.0.1:3100 Used by the JS Zapier package

Local compose: verae-zapier-api/docker-compose.yml (NATS + middleware). Middleware can run without NATS when the flag is off.


4. Integration guide

4.1 Which CLI you are holding

Goal Tool Version in this workspace
Publish a directory integration zapier-platform 19.1.0 (~/.npm-global/bin)
Consume existing Zapier apps from code zapier-sdk 0.77.1
AI client over the 9k catalog Hosted MCP https://mcp.zapier.com/api/v1/connect 14 official meta-tools; live 17

Do not mix zapier-platform (build/publish) with zapier-sdk (consume).
Do not recommend retired NLA / AI Actions.
Do not invent selected_api ids or action keys.

4.2 Run middleware locally

cd verae-zapier-api/verae-zapier-middleware
npm install
MOCK_VERAE=true NATS_ENABLED=false npm start
# GET http://127.0.0.1:3100/health → { "status": "ok" }

With NATS:

cd verae-zapier-api
docker compose up nats
# then start middleware with NATS_ENABLED=true NATS_URL=nats://127.0.0.1:4222

Gates (from verae-zapier-api/):

npm run gate:0     # structure + docs
npm run gate:6     # full HTTP path, NATS off
npm run gate:8     # workers (NATS on)
npm run gate:11    # JS Zapier package tests
npm run gate:all   # 012 in order; stops on first failure

Implementation order is verae-zapier-api/TODO.md. Do not skip gates.

4.3 Build and validate the TypeScript connector

source scripts/dev-env.sh
cd scratch/veraetime
npm install
zapier-platform build && zapier-platform validate

Golden OAuth2 lab (generic, not Verae): scratch/oauth2-typescript — already validates after build.

Copy a template only when starting a new integration:

zapier-platform init my-app --template session --language typescript
# or copy scratch/oauth2-typescript / scratch/veraetime

4.4 Perform contracts (Zapier)

Implement every operation as (z, bundle) => … using z.request only.

  • Triggers and searches return arrays of objects. Polling items need a stable id.
  • Creates return one object.
  • Refreshable 401 → throw new z.errors.RefreshAuthError().
  • Hook triggers implement performSubscribe / performUnsubscribe / perform / performList (sample for the editor).
  • Do not call Verae or NATS from the app.

4.5 Login and publish (blocked until you authenticate)

There is no ~/.zapierrc until you finish a browser login. Local validate works. register and push do not.

source scripts/dev-env.sh
zapier-platform login          # or: zapier-platform login --sso
cd scratch/veraetime
zapier-platform register "Verae Time"
zapier-platform push

Details: LOGIN.md. Never commit the deploy key.

Production Zapier cloud cannot reach http://127.0.0.1:3100. Before a real Zap you need a public HTTPS middleware URL and api_base_url / MIDDLEWARE_BASE_URL pointed at it (Phase 1314).

4.6 Optional consume path (not how we publish Verae)

  • zapier-sdk login — call existing Zapier apps from code (kind: "sdk_function").
  • Hosted Zapier MCP — discover → enable → inspect → execute. Writes need explicit user approval. Successful executes cost 2 Zapier tasks. See MCP-REFERENCE.md.

4.7 Research dataset and Grok reference (NS1 Mongo)

Canonical store: MongoDB 7 in Docker on NS1 (70.88.205.138), bound to 127.0.0.1:27017 only. Connect only through the SSH tunnel:

./scripts/mongo-tunnel.sh
# ssh -N -L 27017:127.0.0.1:27017 ns1

Database zapier:

Collection Contents
apps ~9,986 public Zapier apps (identity, contacts, controls)
templates ~332k public Zap recipes
help_articles 1,272 help-center pages
platform_reference CLI, z.*, schema, official docs, example apps, MCP/SDK functions
meta Last ingest

Do not point Compass at mongodb://70.88.205.138:27017. Credentials live in ~/.mcp-env (mode 600), not git. Full notes: MONGO.md.

Useful queries:

db.platform_reference.findOne({ kind: "guide", key: "build-new-connector" })
db.platform_reference.find({ kind: "core_function", key: "z.request" })
db.platform_reference.find({ kind: "cli_function", key: "init" })
db.platform_reference.find({ kind: "template", key: "session-auth" })
db.platform_reference.find({ kind: "mcp_function" })

Official Zapier clones stay in repos/ (gitignored). Refresh with ./scripts/clone-zapier-repos.sh.


5. Workspace map

Workspace: repo, CLIs, Mongo tunnel, publish versus consume

Path Use
getting-started.md / getting-started.pdf This architecture + integration guide
PLATFORM-REFERENCE.md Routing table for all Zapier work
FUNCTIONS-REFERENCE.md Every CLI / z.* / SDK function
MCP-REFERENCE.md Hosted MCP meta-tools
LOGIN.md Browser login for platform + SDK
RESTART.md Quit and resume this session
MONGO.md NS1 Mongo, tunnel, collections
.grok/skills/zapier-build/ /zapier-build skill
scratch/veraetime/ TypeScript Verae connector (session auth)
scratch/oauth2-typescript/ Golden OAuth2 TypeScript app
scratch/our-api/ Verae OpenAPI + hop notes
verae-zapier-api/ Middleware + JS Zapier app + architecture docs + gates
docs/diagrams/ SVG architecture and flow diagrams (source for this guide and the PDF)
verae-zapier-api/docs/architecture/overview.md Component diagram (source of truth for the edge)
verae-zapier-api/docs/architecture/nats-subjects.md Subjects, streams, payloads
verae-zapier-api/docs/api/middleware-openapi.yaml Zapier-facing OpenAPI
verae-zapier-api/TODO.md Phased plan with test gates
scripts/dev-env.sh PATH + env
scripts/ensure-mongo-tunnel.sh / mongo-tunnel.sh NS1 tunnel
scripts/restart-grok.sh / zapier-status.sh Session + readiness
repos/ Official Zapier clones (local only)

6. What is already here vs what is not

Already here

  • Public catalog research (~9,986 apps, contacts, capabilities, templates, help).
  • Platform reference in Mongo + on disk; /zapier-build skill.
  • Platform CLI 19.1.0 and SDK CLI 0.77.1 on PATH via dev-env.sh.
  • Golden apps that validate locally without a Zapier login.
  • Verae OpenAPI ingested (scratch/our-api/openapi.yaml).
  • Full middleware source: auth, tenants, entitlements, timestamp/verify/status/webhooks, mock Verae, NATS publishers, workers, debug redaction.
  • Two Zapier app implementations wired to /zapier/v1.
  • Gates 08, 10, 11 recorded as passed in TODO.md (as of 2026-08-11 on the original monorepo).

Not here yet

  1. Zapier developer login — no ~/.zapierrc; cannot register / push.
  2. Public HTTPS middleware — Zapier cloud cannot hit localhost.
  3. Live invoke of scratch/veraetime against middleware + real or mock Verae in this workspace (validate is schema-only).
  4. Phase 9/timestamp/wait subscribed to NATS events (multi-instance wait).
  5. Phase 12 — compose E2E smoke (health + auth + wait + webhook) as a gate.
  6. Phase 13 — production VERAE_API_BASE_URL, dedicated Zapier service user, secrets, TLS.
  7. Phase 14 — private push + human Zap (Drive/Sheets → Timestamp → Slack).
  8. Phase 15 — Postgres/Redis store, NATS mTLS, webhook SSRF allowlist.
  9. TS connector polish — map 402/403 like the JS app; optional polling admin trigger for /admin/timestamps.
  10. Grok MCP handshake — Mongo MCP and chrome-bridge need a healthy tunnel / Chrome Connect after restart (/mcps).
  11. Peergos / pin / Glacier retrieval service — proposed in §10; not a v1 connector operation.

This repo has the Zapier platform docs and the Verae OpenAPI. It still cannot invent new Verae endpoints. If a Zap needs an admin route that is not in the v1 table, add middleware + connector operations from the OpenAPI — do not guess.


Phase roadmap: gates 0–15, Phase 9 open

Work the product path in this order. Parallelism is only safe where TODO.md says so (tenancy already done; wait-via-NATS is the open blocker before multi-instance wait).

Now — local integration (this workspace)

  1. Start middleware with MOCK_VERAE=true and NATS_ENABLED=false.
  2. Create a free tenant (POST /zapier/v1/signup or seed script) and confirm GET /health + GET /zapier/v1/auth/me.
  3. zapier-platform build && zapier-platform validate in scratch/veraetime.
  4. After zapier-platform login, zapier-platform invoke auth test and invoke create/search against local middleware (--debug).
  5. Map 402/403 in scratch/veraetime/src/middleware.ts to match the JS app.

Next — close middleware gaps

  1. Phase 9: wait on verae.zapier.jobs.events with a hard timeout (pending + jobId).
  2. Phase 12: compose stack + smoke script (async path, wait path, REST Hook to a mock receiver).
  3. Confirm NATS_ENABLED=true and false both still pass their gates.

Then — production and private listing

  1. Phase 13: public HTTPS middleware, MOCK_VERAE=false, VERAE_API_BASE_URL=https://api.veraetime.net, dedicated Verae service user, managed secrets.
  2. Point the connector api_base_url at that origin. Zapier cloud must reach it.
  3. Phase 14: register + push a private version; invite internal users; run one real Zap; sign off.
  4. Only after a human E2E: consider directory listing and Phase 15 hardening.

Ongoing — research / Grok

  1. Keep ./scripts/ensure-mongo-tunnel.sh running; after restart hit /mcps and refresh mongodb.
  2. Re-ingest platform_reference on NS1 after recloning official repos.
  3. Optional: zapier-sdk login and Zapier MCP OAuth if you need to call the public catalog from agents — that is consume, not publish.

8. Hard rules

  • Start Zapier coding from guide/build-new-connector or PLATFORM-REFERENCE.md.
  • Connector → middleware /zapier/v1 only. Never api.veraetime.net from Zapier. Never NATS from Zapier.
  • Use z.request in performs. Triggers/searches return arrays; creates return one object.
  • zapier-platform publishes; zapier-sdk / hosted MCP consume. Do not mix.
  • Do not recommend retired NLA / AI Actions.
  • Do not invent vendor APIs, auth schemes, or Zapier selected_api keys.
  • Mongo on NS1 is localhost-only; always tunnel.
  • No secrets in git or in DEBUG_VERAE output.

9. Zapier billing models

Zapier and Verae bill separately. A client Zap that timestamps a file pays Zapier for successful tasks and pays Verae (via middleware entitlements) for timestamp / verify operations. Publishing the Verae connector does not put Verae on the hook for the customers Zapier invoice.

Figures below are USD, August 2026, from zapier.com/pricing. Annual prices are the discounted per-month equivalent. Confirm live rates before quoting a customer.

Zapier and Verae billing layers

9.1 What a Zapier “task” is

A task is one successful unit of work Zapier does for the customer. Failed steps are free.

Counts as tasks Does not count
Successful action in a third-party app (Create Timestamp, Slack post, Drive upload, …) Triggers and polling for new data
Zapier MCP / SDK execute (see multipliers) Filter, Paths, Formatter, Delay, Looping, Sub-Zap, Digest, Manager, Storage
AI by Zapier and Code-by-Zapier beyond included runtime Zapier Tables and Forms triggers/actions
Building or testing a Zap until it actually runs

Shared pool: Zap workflows, AI steps, Code steps, MCP, and SDK all draw from one monthly (or Enterprise annual) task allowance. There is no separate MCP budget.

Multipliers (official rate card; confirm zapier.com/pricing/rates):

Work Tasks
Typical third-party action (including Verae Create Timestamp) 1
Standard AI by Zapier 1
Advanced AI by Zapier 3
Premium AI by Zapier 5
Successful Zapier MCP tool call (read or write) 2
Code by Zapier included runtime free; then 1 task per extra 30-second block

Example: trigger “new file in Drive” (0) → Filter (0) → Create Timestamp (1) → Formatter (0) → write metadata row (1) = 2 tasks per file that passes the filter.

9.2 Self-serve plans (feature set + task tier)

A paid subscription is plan level × task tier.

Plan Seats Workflows Polling Entry task tier (annual) Standout
Free 1 Two-step only 15 min 100 tasks / month, $0 Try automation; no pay-per-task overflow
Professional 1 Multi-step; premium apps; webhooks 2 min 750 tasks from $19.99/mo annual ($29.99 monthly) Filters, Paths, Formatter, AI by Zapier, Autoreplay
Team 25 Same as Pro 1 min 2,000 tasks from $69/mo annual ($103.50 monthly) Shared Zaps, shared connections, SAML SSO, priority support
Enterprise Unlimited Same as Team + governance 1 min Custom; annual task limit (not monthly reset) SCIM, app controls, custom retention, observability, TAM, BYOM

Higher task tiers (2k → 2M/mo) lower the per-task price. Team starts at 2,000. Volumes above 2M go through Sales. 14-day Professional trial (no card). Non-profit: extra 15% off (not on pay-per-task).

9.3 Overflow: pay-per-task

Paid plans can keep running after the included allowance:

  • Pay-per-task on: extra tasks bill at 1.25× the plans base task rate (annual) or 2.5× (monthly). Ceiling is 3× the subscribed tasks, then Zaps pause until the next cycle or an upgrade.
  • Pay-per-task off: usage stops at the allowance.
  • Free has no overflow. Enterprise uses an annual pool instead of a monthly reset.

9.4 Add-ons outside the task pool

Product Unit Notes
Zapier Agents Activities (not tasks) Free 400/mo; paid Pro ~$33.33/mo annual for 1,500. Does not consume Zap tasks.
Zapier Chatbots Feature tiers (count of bots) Free includes 2; paid adds more. Not usage-metered on tasks.

9.5 Partner / platform billing (Verae as publisher)

Model Who pays Zapier Who pays Verae
Public or private directory integration The end customers Zapier plan (tasks). Publishing is free; Zapier does not bill the partner for usage of their app. The customers Verae tenant (middleware plan / API key).
Zapier MCP / SDK (consume) Same customer task pool (MCP execute = 2 tasks). SDK is free in beta; Zapier will announce when beta pricing starts. Only if the MCP/SDK action hits Verae.
Powered by Zapier / White Label / embed Usually the product company (usage-based). End users authorize apps in your UI; Zapier has said end users need not have their own Zapier bill for background runs. Contract with Zapier Sales. Verae bills the product company or the tenant, depending on how you provision keys.
Retired NLA / AI Actions Do not sell or design around this.

Verae should not promise “unlimited Zapier” or absorb a customers Zapier invoice unless a White Label contract says so.

9.6 Verae middleware billing (second meter)

Middleware enforces Verae quotas, independent of Zapier tasks. Current plan table in verae-zapier-middleware PLAN_LIMITS:

Verae plan Timestamps / mo Verifications / mo Batch RPM
free 50 50 no 30
starter 500 500 yes, max 10 120
pro 5,000 5,000 yes, max 100 600
enterprise contract / unlimited contract yes contract

Over-quota → HTTP 402 QUOTA_EXCEEDED (upgrade URL). Wrong plan for batch → 403 PLAN_UPGRADE_REQUIRED. Those errors must surface in the Zap; they are not Zapier task overages.

A client therefore sees two invoices: Zapier (tasks) and Verae (timestamps). Design Zaps so a 402 does not retry in a tight loop (that still burns Zapier tasks on each failed? — failed actions are not Zapier tasks, but Autoreplay/retries can still hammer Verae).

9.7 Estimating a timestamping Zap

Zap shape Zapier tasks / successful file Verae units
Trigger → Create Timestamp 1 1 timestamp
Trigger → Create Timestamp and Wait 1 1 timestamp
Trigger → Timestamp + write catalog row + Slack 3 1 timestamp
Same via Zapier MCP execute of those three actions 6 1 timestamp
Trigger filtered out before any action 0 0

Prefer the hook (Timestamp Completed) plus a cheap catalog write over polling status in a loop.


10. Client pattern — timestamp, metadata, Peergos, and tiered IPFS

This section is a client architecture for using the Verae Zapier tools together with Peergos (end-to-end encrypted filesystem on IPFS) and external IPFS / object-store backends. It is not implemented as connector operations today. Do not invent Peergos or AWS APIs in the Zapier app; add middleware routes only when those APIs exist and are documented.

Goal: clients can (1) timestamp content, (2) append that proof to metadata, (3) store the file in Peergos, (4) pin a hot cache on one or more IPFS providers, (5) migrate bytes to long-term low-cost object storage (Amazon S3 Glacier family, or an Apache Iceberg catalog on S3), and (6) rehydrate on demand when an IPFS request hits an index — without keeping every file live on a gateway 24/7.

Timestamped files: Peergos, pin cache, and cold retrieve-on-demand

10.1 What each layer is for

Layer Role Stays hot?
Zapier + Verae connector Orchestrate: hash → timestamp → write metadata; notify on timestamp.completed n/a (control plane)
Verae Time Blockchain timestamp of a payload (typically a content hash or a metadata JSON, not the raw file bytes) Proof is small; keep forever
Metadata / index Maps cidjobId, Verae certificate fields, Peergos path, storage class, restore handle Yes — this is the only always-on map
Peergos User-owned, e2e-encrypted filesystem on IPFS/libp2p. Host cannot read file or most metadata. Sharing and apps stay in the users graph. Users chosen Peergos host; not a public CDN
Cached pin (hot IPFS) Pinning service or your Kubo cluster (Pinata, Filebase, web3.storage, self-hosted). Serves frequent ipfs get / gateway hits. Only for a TTL or working set
Cold object store Amazon S3 Glacier Instant Retrieval, Flexible Retrieval, or Deep Archive; or another cheap archive (Filecoin deal, Storj, Backblaze B2 + lifecycle). Optional Apache Iceberg table on S3 as the catalog of CID → bucket/key → storage class → restore job. No — retrieve on demand

Amazon “Iceberg” in this design is the table format (Apache Iceberg) used as a durable index, not a substitute for Glacier. Long-term bytes live in Glacier-class (or equivalent) object storage. The user-facing name “Iceberg” is easy to mix with Glacier; keep the two distinct in customer docs.

10.2 Ingest Zap (write path)

Typical multi-step Zap (Professional+; Filters/Formatter are free):

  1. Trigger — new file in Drive, Dropbox, email, or a Peergos outbox / webhook. (0 Zapier tasks)
  2. Hash — SHA-256 (or the hashAlg Verae accepts) of the bytes, or of the canonical metadata envelope. Prefer hashing ciphertext if the file is already encrypted for Peergos, so the timestamp commits to what is stored.
  3. Create Timestamp (or Create and Wait) — data = hash or compact JSON { cid?, sha256, size, mime, source }. (1 Zapier task, 1 Verae timestamp)
  4. Store file in Peergos — user or service account writes the file into /cubes/… or a shared folder via a documented Peergos API or a future middleware route. Peergos assigns / retains an IPFS CID for the blocks.
  5. Hot pin (optional) — Pinning Services API (or Filebase/Pinata) pins that CID for a cache TTL (hoursdays), not forever.
  6. Append metadata — write one index record (Zapier Tables is free; or Sheets/Postgres/Iceberg):
cid                # IPFS content id (or Peergos block root)
sha256             # digest that Verae timestamped
veraeJobId
veraeStatus        # pending | completed | failed
certificateRef     # verify payload / block index when complete
peergosPath        # /home/… or /cubes/<id>/…
storageClass       # pin-hot | peergos-only | glacier-ir | glacier-deep
coldBucket / key   # S3 (or other) locator; empty until migrated
restoreId          # last Glacier restore job, if any
pinnedUntil        # when hot pin may be dropped
createdAt
  1. Timestamp Completed hook — when middleware finishes the job, update the same row with certificate fields and notify Slack/email. (1 Zapier task)

Do not put the raw file or Verae JWT in Zapier Storage, Slack, or NATS.

10.3 Lifecycle (keep the index, drop the heat)

ingest
  → Peergos write (encrypted) + optional hot pin
  → Verae timestamp of hash / envelope
  → index row (always on)

after pinnedUntil or size/age policy
  → copy ciphertext (or original bytes, if policy allows) to S3
  → set storage class Glacier Instant / Flexible / Deep Archive
  → record bucket/key + storageClass in the index (and Iceberg snapshot if used)
  → unpin from the paid pinning cluster
  → Peergos may keep a thumbnail / stub; full blocks need not stay on the gateway

IPFS / gateway GET cid
  → if pin-hot hit: serve
  → else index lookup
       → if peergos-only: fetch via users Peergos capability
       → if cold: StartRestore / vendor retrieve API → wait →
         optionally re-pin for a short cache TTL → serve
  → never require every historical CID to be live on an IPFS node

Glacier retrieval notes (AWS, conceptual): Instant Retrieval is milliseconds and priced as a storage class; Flexible Retrieval and Deep Archive need a restore job (minutes to hours) before GetObject. The index must store enough to call the restore API (bucket, key, versionId, restoreId). Map IPFS requests to that restore; return 202 + Retry-After to the gateway until the object is hydrated.

Apache Iceberg (optional): partition the catalog by storageClass and date so you can expire pin rows and audit restores with SQL, without loading every object. Iceberg does not store the file bytes.

10.4 External IPFS and pinning options

Clients can mix providers; the index is the source of truth, not any one pinset.

Backend Typical use
Self-hosted Kubo / cluster Hot working set you control
Pinata, Filebase, web3.storage, Pinning Services API Paid cached pins, metadata tags, S3-compatible gateways
Peergos server (user or org host) Encrypted personal/org filesystem; not a public pin service
Filecoin / cold deals Alternative long-term availability (different retrieve SLA)
S3 + lifecycle → Glacier IR / Flexible / Deep Archive Lowest $/TB; retrieve-on-demand via AWS APIs
Storj, Backblaze B2, GCS Archive Same pattern, different restore API

A request path should be: CID → index → (pin | Peergos | restore). Do not walk every pin provider on every miss.

10.5 What Zapier is bad at (keep it out of the Zap)

  • Holding multi-GB files in a Zap step (timeouts, payload limits). Hash and pass references (Drive id, Peergos path, CID).
  • Being the IPFS gateway. Use a small retrieval service (your infra) that reads the index and talks to Peergos / pin / Glacier.
  • Polling Glacier restore every second (burns tasks). Use a webhook, queue, or “Find Job Status”-style search on a timer Zap with a Filter.

10.6 Security and tenancy

  • Peergos ciphertext: the timestamp should commit to the CID and/or ciphertext hash, not a plaintext the host can reconstruct.
  • Capabilities / sharing stay in Peergos; the public index should not leak readable paths or unencrypted names if the threat model forbids it (store opaque ids).
  • Middleware still never exposes Verae JWTs. Retrieval workers use tenant-scoped cloud credentials, not the Zapier connection.
  • 402/403 from Verae must not be “fixed” by falling back to an unauthenticated public pin of customer data.

10.7 Implementation status

Piece Status in this repo
Verae timestamp / wait / verify / hook via middleware Implemented (scratch/veraetime, verae-zapier)
Zapier task + Verae quota as two meters Documented (this section); connector should map 402/403
Peergos write / capability APIs in the Zapier app Not in v1 — handbook lives outside this repo (verae-peergos-app-handbook); do not invent routes
CID index, pin TTL, Glacier restore worker Proposed — add as middleware + retrieval service when APIs are chosen
Apache Iceberg catalog Optional index implementation; not required for MVP

Next build slice, when product asks for it: a retrieval service with GET /ipfs/{cid} → index → pin or restore, plus one Zapier search (“Find File Record by CID”) against that index — still no direct api.veraetime.net from Zapier.