Skip to content
v1
Get an API key

Cookbook

Complete examples you can adapt. Each one calls only endpoints that are live today.

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 429 means you hit the key’s per-minute limit. Wait Retry-After seconds and send it again with the same Idempotency-Key.
  • Do not block your own signup on Funnel One. Log a failure and retry later.

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.

Terminal window
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.

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.