Public REST API - keys, scopes and endpoints
Mint an API key, call the /api/v1 endpoints, understand rate limits and the audit log.
Jeanus ships a JSON REST API at /api/v1. Use it to push leads in from a landing page or webhook, pull customer / order / product data into Zapier, Make, n8n, or your own scripts, and build integrations we haven't written yet.
1. Mint an API key
Go to Settings > API keys. Click Create key, pick a name ("Zapier production", "My reporting script"), and choose a scope:
- Read - list customers, leads, orders, products.
- Write - all of read, plus create new leads.
The full key is shown to you once. Copy it immediately - we only store the SHA-256 hash. If you lose it, revoke it and mint a new one.
2. Send requests
Pass the key in the Authorization header. Every response is JSON.
curl https://jeanus.app/api/v1/customers \
-H "Authorization: Bearer jns_live_YOUR_KEY_HERE"3. Endpoints
| Method + path | Scope | What it returns |
|---|---|---|
GET /api/v1/leads | read | Paginated list of pipeline leads. |
POST /api/v1/leads | write | Create a lead from an external source (form, Zap, script). |
GET /api/v1/customers | read | Paginated list of your customers. |
GET /api/v1/orders | read | Paginated list of orders across customers. |
GET /api/v1/products | read | Paginated list of catalogue products. |
Every response has the same shape: { data: [...], next_cursor: string | null }. Pass ?cursor=abc and ?limit=50 (max 200) to page.
4. Rate limits
Each key is limited independently. Current limits: 60 requests per minute per key. Every response includes X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers so you can back off cleanly. Exceeded requests return 429.
5. Audit log
Every call (successful or rejected) writes a row to your workspace's audit log with the timestamp, method, path, response status, IP and user-agent. You can view it under Settings > API keys. Useful for spotting unexpected use, and required by most compliance frameworks.
6. Rotating and revoking keys
There's no expiry. To rotate, mint a new key, switch your integration over, then hit Revokeon the old one in the settings page. Revocation is immediate across every future request.
7. Webhooks (push, not pull)
Don't want to poll? Add a webhook endpoint at Settings > Webhooks. We POST to your URL with a JSON body the moment an event fires. Currently supported:
lead.created— public API, homepage capture, portal contact form.lead.won/lead.lost— lead cycle transitioned into a Won/Placed or Lost stage.quote.sent— first send (not resends) via the quote-send flow.quote.accepted/quote.rejected— recipient clicked accept or decline on the public quote page.order.placed— customer placed an order through the portal.customer.created— a rep or the system created a new customer record.
Each POST carries an X-Jeanus-Signatureheader — the HMAC-SHA256 of the raw body signed with your endpoint's secret. Verify by recomputing and comparing:
// Node.js example
const expected = require('crypto')
.createHmac('sha256', WEBHOOK_SECRET)
.update(req.rawBody)
.digest('hex')
if (expected !== req.headers['x-jeanus-signature']) {
return res.status(401).send('Bad signature')
}Payload shape: { event, tenant_id, occurred_at, data }. First attempt is a synchronous POST with a 5-second timeout. On non-2xx or timeout we enqueue and retry on a 30s / 2m / 10m / 1h / 6h backoff (5 attempts total, ~7.5 hours before the delivery is marked dead). Every retry sends byte-identical body + signature so your HMAC check keeps working. Retries carry an X-Jeanus-Retry-Attempt header if you want to log or dedupe on it.
Consumers should be idempotent— de-dupe on the payload's stable fields (e.g. data.lead.id) so a re-delivered event doesn't create a duplicate record on your side.
Expand any endpoint in Settings > Webhooksto see recent failed deliveries — event, attempt count, last HTTP status, when it's next scheduled to retry. Happy-path deliveries aren't logged, so an empty list is the healthy state.