Cookbook
Complete examples you can adapt. Each one calls only endpoints that are live today.
Push leads from your own signup form
Section titled “Push leads from your own signup form”Your signup form posts to your own server. Your server forwards the lead to Funnel One, so the API key never reaches the browser.
// Node 18+, Express. F1_API_KEY holds a key with leads.manage.import express from 'express';import { randomUUID } from 'node:crypto';
const app = express();app.use(express.json());
app.post('/signup', async (req, res) => { const { email, firstName, lastName, company } = req.body; // One key per signup: a retry of THIS signup is not a second lead. const idempotencyKey = req.get('X-Signup-Id') ?? randomUUID();
const f1 = await fetch('https://app.funnelone.ai/api/v1/leads', { method: 'POST', headers: { Authorization: `Bearer ${process.env.F1_API_KEY}`, 'Content-Type': 'application/json', 'Idempotency-Key': idempotencyKey, }, body: JSON.stringify({ email, first_name: firstName, last_name: lastName, company: { domain: company?.domain, name: company?.name }, utm: { source: req.query.utm_source, medium: req.query.utm_medium, campaign: req.query.utm_campaign }, }), });
// 201: created. 409 duplicate_request: already sent, which is fine on a retry. if (f1.status !== 201 && f1.status !== 409) { console.error('Funnel One lead failed', f1.status, await f1.text()); } res.status(204).end();});Things to know:
- A
429means you hit the key’s per-minute limit. WaitRetry-Afterseconds and send it again with the sameIdempotency-Key. - Do not block your own signup on Funnel One. Log a failure and retry later.
Start a motion from your own systems
Section titled “Start a motion from your own systems”When something happens in your product (a trial starts, an order ships), start
a motion for that company. The motion needs an API call trigger in its
entry settings, and the key needs motions.start.
curl -X POST https://app.funnelone.ai/api/v1/motions/42/start \ -H "Authorization: Bearer $F1_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: trial-started-1234" \ -d '{"companyId": 1234}'A 202 with "status": "queued" means it was accepted; Funnel One decides the
entry with the same checks as every other trigger. Sending the same key again
returns the decision once it is made.
Coming soon
Section titled “Coming soon”These recipes wait for parts of the API that are not live yet:
- Sync your CRM data to a warehouse, with keyset pages of companies, contacts and opportunities.
- A Claude agent that triages inbound through Funnel One, over the MCP server.
- A partner’s agent asking Funnel One for account status, through an external agent channel.