Developers
Your business, from your own systems.
Read your leads, bookings, invoices and calendar. Add leads from a voice assistant, a website form or anything that can send a request. Hear about every new lead, reply and payment the moment it happens.
Keys
Make a key in the portal under Team, then API keys. It's shown once; keep it like a password. Every request carries it as a bearer token.
A key acts as the person who made it. It sees exactly what they see in the portal, narrowed to the scopes you tick, and it stops working if they leave your team or you revoke it. Nothing in the API messages a client on its own: replies go out through your scheduled sends, where you can see and cancel them. Every call is logged on the same screen.
Pro makes read-only keys. Studio adds leads, notes, replies and webhooks.
curl https://www.theveilwedding.com/api/v1/me \
-H "Authorization: Bearer veil_live_api_…"Routes
JSON in and out. Money is in cents with a currency; times are ISO 8601. Lists page with next_cursor, 50 at a time by default and 200 at most.
| Method | Path | What it does |
|---|---|---|
| GET | /me | The business, the member the key acts as, and the key |
| GET | /leads | Leads, newest first |
| POST | /leads | Add a lead |
| GET | /leads/{id} | A lead with its notes, messages and scheduled replies |
| PATCH | /leads/{id} | Assign, tag or close a lead |
| POST | /leads/{id}/notes | Add a note |
| POST | /leads/{id}/replies | Schedule a reply to the client |
| GET | /bookings | Booked events in a window |
| GET | /bookings/{id} | One booking |
| GET | /invoices | Invoices |
| GET | /payments | Payments through The Veil, with fees and net |
| GET | /calendar | Booked days, holds, tours and tastings, and blocked days |
| GET | /clients/{id} | A lead's client and their page link |
| GET | /team | Members and roles |
| GET | /webhooks | Webhook endpoints |
| POST | /webhooks | Add a webhook endpoint |
| DELETE | /webhooks/{id} | Delete a webhook endpoint |
Adding leads from a voice assistant or a form
An answering service, a voice AI on your phone line or your own website form can hand a caller straight to your inbox. The lead lands like any other: your team is notified, it's routed by your rules, and your webhooks fire. The same email or phone to the same business within the hour comes back as the existing lead, so a caller who rings twice is one lead.
curl -X POST https://www.theveilwedding.com/api/v1/leads \
-H "Authorization: Bearer veil_live_api_…" \
-H "Content-Type: application/json" \
-d '{
"contact": { "name": "Ava Bennett", "phone": "+17175550123", "email": "ava@example.com" },
"name": "Ava & Noah",
"event": { "date": "2027-06-12", "type": "wedding", "guests": "120", "budget": "$20k-$30k" },
"message": "Called after hours. Wants a Saturday in June and a tour next week.",
"source": "Phone line"
}'Answers 201 with the lead (or 200 and "duplicate": true). Then add what the call covered as a note with POST /leads/{id}/notes.
Webhooks
Add an endpoint on Team, under Webhooks, or with POST /webhooks. Events: lead.created, lead.replied, lead.assigned, quote.sent, quote.accepted, booking.confirmed, payment.received and client.details_sent. Failed deliveries retry with backoff, and you can send any of them again from the log.
Each request is signed. Check it before trusting the body: the HMAC-SHA256 of the timestamp, a dot and the raw body, with your endpoint's secret, must equal the hex after v1=.
// Node
import crypto from "node:crypto";
function fromTheVeil(rawBody, headers, secret) {
const ts = headers["veil-timestamp"];
const sig = (headers["veil-signature"] || "").replace(/^v1=/, "");
const want = crypto.createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
return fresh && sig.length === want.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(want));
}Zapier
Our Zapier app is on its way to Zapier's directory. Until it's listed, use Zapier's own Webhooks step: add its catch hook address as a webhook here to start a Zap on any event, and call the API from a Zap to add leads and notes. Facebook and Instagram lead ads come in the same way: their New Lead trigger, then Create Lead here, with the form's answers mapped to the date, guests and budget.
Claude and other AI assistants
The Veil is an MCP server, so an assistant you already use can work your business with you: “which leads have waited more than a day?”, “what's owed this month?”, “put a note on Maya and Jordan”. Make a key of the kind Claude or another AI on Team, then API keys.
It reads what the key's person can read and adds notes and leads. It never messages a client: a reply it writes waits on the lead until someone on your team approves the exact words, and a lead it adds gets no automatic email. Give an assistant this kind of key, never a plain API key, which isn't held for approval.
claude mcp add --transport http the-veil https://www.theveilwedding.com/api/mcp \
--header "Authorization: Bearer veil_live_mcp_…"Limits and errors
600 requests a minute per key, 20 of them writes, and 2,000 a minute across a business's keys. Over that, you get 429 with Retry-After. If you need more, write to us.
Errors look like this, with a code you can switch on and a message you can show:
{ "error": { "code": "scope_missing", "scope": "invoices:read",
"message": "This key can't do that. Add invoices:read to a key on Team → API." } }v1 is stable: new fields and routes arrive without notice; anything removed or renamed goes to v2, with v1 kept for twelve months.
Building something for venues and wedding pros? Tell us about it.