Connect Sarvyam to everything else
A REST API for clients, inquiries, quotes, bookings and payments, and signed webhooks the moment a quote is accepted or a payment lands. Available on Pro and Studio.
Get started in two minutes
- In Sarvyam, open Settings → Developers and create a key. Choose read for reporting, write to create clients, inquiries, quotes or payments.
- Send it as a bearer token. Keys are shown once — store them like passwords.
curl https://api.sarvyam.com/v1/quotes?status=sent \
-H "Authorization: Bearer sk_live_…"- Base URL:
https://api.sarvyam.com/v1· Spec: openapi.json (import into Postman, Insomnia or a code generator) - Money is an integer in minor units of the business currency (cents, paise…). Dates are
YYYY-MM-DDin the business timezone. - Limit: 300 requests per minute per key. Errors return
{ "error": { "code", "message" } }with a stable code. - Keys cannot reach billing, team, other keys or the account — only business data.
Webhooks
Add an endpoint in Settings → Developers → Webhooks and pick events: lead.created, client.created, quote.sent, quote.accepted, quote.declined, booking.created, booking.cancelled, payment.received, gallery.selection_submitted. Each delivery is a JSON POST; respond 2xx within 10 seconds. Failures retry after 1 m, 5 m, 30 m, 2 h, 6 h, 12 h and 24 h. Every delivery is in the log with its response, and you can resend any of them.
Verify the signature (Node.js)
import crypto from 'node:crypto'
// Express: use the raw body, not the parsed JSON.
app.post('/sarvyam-webhook', express.raw({ type: 'application/json' }), (req, res) => {
const header = req.get('Sarvyam-Signature') ?? '' // t=1760000000,v1=ab12…
const { t, v1 } = Object.fromEntries(header.split(',').map((p) => p.split('=')))
const expected = crypto.createHmac('sha256', process.env.SARVYAM_WEBHOOK_SECRET)
.update(`${t}.${req.body}`).digest('hex')
const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300
if (!fresh || !crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))) return res.sendStatus(400)
const event = JSON.parse(req.body) // { id, type, created, data }
// …handle event.type: quote.accepted, payment.received, …
res.sendStatus(200)
})Python
import hmac, hashlib, time
def verify(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
return abs(time.time() - int(parts["t"])) < 300 and hmac.compare_digest(parts["v1"], expected)Using Zapier or Make? Point a “Catch hook” URL at Sarvyam and use the API key for actions. Questions: support@sarvyam.com.
API reference
Sarvyam API
Read and write your Sarvyam data — clients, inquiries, quotes, bookings and payments — and receive webhooks when things happen.
Authentication: create a key in Settings → Developers and send it as Authorization: Bearer sk_live_…. Read keys may only use GET.
Money is always an integer in minor units of the business currency. Dates without time are YYYY-MM-DD in the business timezone.
Limits: 300 requests per minute per key. Errors return { "error": { "code", "message" } } with a stable code.
https://api.sarvyam.com/v1Authorization: Bearer sk_live_…Business
The business this key belongs to
/orgResponses
- 200OK
- 401Error
curl https://api.sarvyam.com/v1/org \
-H "Authorization: Bearer sk_live_…"{
"org": {
"id": "cmvd1x2y3000abc",
"name": "string",
"slug": "string",
"currency": "USD",
"timezone": "America/New_York",
"locale": "en",
"plan": "string"
}
}Download a CSV export
/exports/{name}.csvParameters
namepath · stringrequiredOne ofclientsleadsquotesbookingspayments
Responses
- 200CSV file
curl https://api.sarvyam.com/v1/exports/clients.csv \
-H "Authorization: Bearer sk_live_…"Clients
List clients
/clientsParameters
qquery · stringSearch name, email or phone
archivedquery · stringOne oftruefalse
Responses
- 200OK
- 401Error
curl https://api.sarvyam.com/v1/clients \
-H "Authorization: Bearer sk_live_…"{
"clients": [
{
"id": "cmvd1x2y3000abc",
"name": "string",
"email": "string",
"phone": "string",
"company": "string",
"createdAt": "2026-12-17T15:00:00.000Z"
}
]
}Create a client
/clientsCreate a client. Needs a write key.
Request body
namestringrequiredemailstringphonestringInternational format preferred, e.g. +44 7700 900123
companystringaddressstringnotesstringmarketingConsentbooleanforcebooleanCreate even if a client with the same email/phone exists (otherwise 409 possible_duplicate).
Responses
- 201Created
- 400Error
- 409Error
curl -X POST https://api.sarvyam.com/v1/clients \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"name":"string","email":"string","phone":"string","company":"string","address":"string","notes":"string","marketingConsent":true,"force":true}'{
"client": {
"id": "cmvd1x2y3000abc",
"name": "string",
"email": "string",
"phone": "string",
"company": "string",
"createdAt": "2026-12-17T15:00:00.000Z"
}
}Get a client with their quotes and bookings
/clients/{id}Parameters
idpath · stringrequiredID
Responses
- 200OK
- 404Error
curl https://api.sarvyam.com/v1/clients/<id> \
-H "Authorization: Bearer sk_live_…"Update a client
/clients/{id}Update a client. Needs a write key.
Parameters
idpath · stringrequiredID
Request body
namestringrequiredemailstringphonestringInternational format preferred, e.g. +44 7700 900123
companystringaddressstringnotesstringmarketingConsentbooleanforcebooleanCreate even if a client with the same email/phone exists (otherwise 409 possible_duplicate).
Responses
- 200OK
- 404Error
curl -X PATCH https://api.sarvyam.com/v1/clients/<id> \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"name":"string","email":"string","phone":"string","company":"string","address":"string","notes":"string","marketingConsent":true,"force":true}'{
"client": {
"id": "cmvd1x2y3000abc",
"name": "string",
"email": "string",
"phone": "string",
"company": "string",
"createdAt": "2026-12-17T15:00:00.000Z"
}
}Inquiries
List inquiries
/leadsParameters
stagequery · stringOne ofnewcontactedquotedwonlostarchivedquery · stringOne oftruefalse
Responses
- 200OK
curl https://api.sarvyam.com/v1/leads \
-H "Authorization: Bearer sk_live_…"{
"leads": [
{
"id": "cmvd1x2y3000abc",
"name": "string",
"email": "string",
"phone": "string",
"eventType": "string",
"eventDate": "2026-12-17",
"stage": "string",
"source": "string",
"createdAt": "2026-12-17T15:00:00.000Z"
}
]
}Create an inquiry (e.g. from your own form)
/leadsCreate an inquiry (e.g. from your own form). Needs a write key.
Request body
namestringrequiredemailstringphonestringeventTypestringeventDatestring · datevenuestringguestCountintegerbudgetMinorintegerAmount in minor units (cents, paise…) of the business currency.
messagestringsourcestringOne ofwebsiteinstagramfacebookwhatsappreferralphonewalk_inotherfollowUpAtstring · date-time
Responses
- 201Created
- 400Error
curl -X POST https://api.sarvyam.com/v1/leads \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"name":"string","email":"string","phone":"string","eventType":"string","eventDate":"2026-12-17","venue":"string","guestCount":0,"budgetMinor":0,"message":"string","source":"website","followUpAt":"2026-12-17T15:00:00.000Z"}'{
"lead": {
"id": "cmvd1x2y3000abc",
"name": "string",
"email": "string",
"phone": "string",
"eventType": "string",
"eventDate": "2026-12-17",
"stage": "string",
"source": "string",
"createdAt": "2026-12-17T15:00:00.000Z"
}
}Get an inquiry
/leads/{id}Parameters
idpath · stringrequiredID
Responses
- 200OK
- 404Error
curl https://api.sarvyam.com/v1/leads/<id> \
-H "Authorization: Bearer sk_live_…"Quotes
List quotes
/quotesParameters
statusquery · stringOne ofdraftsentviewedaccepteddeclinedexpiredvoidqquery · stringclientIdquery · string
Responses
- 200OK
curl https://api.sarvyam.com/v1/quotes \
-H "Authorization: Bearer sk_live_…"{
"quotes": [
{
"id": "cmvd1x2y3000abc",
"number": "Q-0042",
"title": "string",
"status": "draft",
"currency": "string",
"totalMinor": 0,
"eventDate": "2026-12-17",
"clientId": "cmvd1x2y3000abc"
}
]
}Create a draft quote from packages
/quotesCreate a draft quote from packages. Needs a write key.
Request body
titlestringrequiredclientIdstringclientobjectCreates or matches a client when clientId is not given.
Fields
namestringemailstringphonestring
leadIdstringeventDatestring · datevenuestringguestCountintegerpackagesobject[]Fields
packageIdstringquantitystring
Responses
- 201Created
- 400Error
- 402Error
curl -X POST https://api.sarvyam.com/v1/quotes \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"title":"string","clientId":"cmvd1x2y3000abc","client":{"name":"string","email":"string","phone":"string"},"leadId":"cmvd1x2y3000abc","eventDate":"2026-12-17","venue":"string","guestCount":0,"packages":[{"packageId":"cmvd1x2y3000abc","quantity":"1"}]}'{
"quote": {
"id": "cmvd1x2y3000abc",
"number": "Q-0042",
"title": "string",
"status": "draft",
"currency": "string",
"totalMinor": 0,
"eventDate": "2026-12-17",
"clientId": "cmvd1x2y3000abc"
}
}Get a quote with its lines and totals
/quotes/{id}Parameters
idpath · stringrequiredID
Responses
- 200OK
- 404Error
curl https://api.sarvyam.com/v1/quotes/<id> \
-H "Authorization: Bearer sk_live_…"Issue the quote (freezes a version) and optionally email the client
/quotes/{id}/sendIssue the quote (freezes a version) and optionally email the client. Needs a write key.
Parameters
idpath · stringrequiredID
Request body
emailbooleanDefaultfalsemessagestring
Responses
- 200OK
- 400Error
- 402Error
curl -X POST https://api.sarvyam.com/v1/quotes/<id>/send \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"email":false,"message":"string"}'Bookings
List bookings
/eventsParameters
fromquery · string · date-timetoquery · string · date-timestatusquery · stringOne oftentativeconfirmedcompletedcancelledclientIdquery · string
Responses
- 200OK
curl https://api.sarvyam.com/v1/events \
-H "Authorization: Bearer sk_live_…"{
"events": [
{
"id": "cmvd1x2y3000abc",
"title": "string",
"status": "tentative",
"startsAt": "2026-12-17T15:00:00.000Z",
"endsAt": "2026-12-17T15:00:00.000Z",
"totalMinor": 0,
"currency": "string",
"clientId": "cmvd1x2y3000abc",
"quoteId": "cmvd1x2y3000abc"
}
]
}Get a booking with payments, schedule and tasks
/events/{id}Parameters
idpath · stringrequiredID
Responses
- 200OK
- 404Error
curl https://api.sarvyam.com/v1/events/<id> \
-H "Authorization: Bearer sk_live_…"Payments
Record a payment or refund on a booking
/events/{id}/paymentsRecord a payment or refund on a booking. Needs a write key.
Parameters
idpath · stringrequiredID
Request body
amountMinorintegerrequiredAmount in minor units (cents, paise…) of the business currency.
methodstringrequiredkindstringOne ofpaymentrefundDefault"payment"receivedAtstring · date-timereferencestringnotestringmilestoneIdstring
Responses
- 201Recorded
- 409Error
curl -X POST https://api.sarvyam.com/v1/events/<id>/payments \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{"amountMinor":0,"method":"bank_transfer","kind":"payment","receivedAt":"2026-12-17T15:00:00.000Z","reference":"string","note":"string","milestoneId":"cmvd1x2y3000abc"}'All payments and refunds (newest first, up to 1000)
/paymentsResponses
- 200OK
curl https://api.sarvyam.com/v1/payments \
-H "Authorization: Bearer sk_live_…"{
"payments": [
{
"id": "cmvd1x2y3000abc",
"eventId": "cmvd1x2y3000abc",
"amountMinor": 0,
"currency": "string",
"kind": "payment",
"method": "string",
"receivedAt": "2026-12-17T15:00:00.000Z",
"reference": "string"
}
]
}Catalog
Catalog items with costs
/catalogResponses
- 200OK
curl https://api.sarvyam.com/v1/catalog \
-H "Authorization: Bearer sk_live_…"Packages with their recipes and prices
/packagesResponses
- 200OK
curl https://api.sarvyam.com/v1/packages \
-H "Authorization: Bearer sk_live_…"Webhooks
lead.created
lead.createdSent as POST with JSON body. Verify the Sarvyam-Signature header: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(your endpoint secret, ${t}.${rawBody}). Reject timestamps older than 5 minutes. Respond 2xx within 10 s; otherwise we retry with backoff (1 m, 5 m, 30 m, 2 h, 6 h, 12 h, 24 h).
Payload
idstringtypestringOne oflead.createdclient.createdquote.sentquote.acceptedquote.declinedbooking.createdbooking.cancelledpayment.receivedgallery.selection_submittedtestcreatedstring · date-timedataobjectDepends on the event type.
Responses
- 200Received
{
"id": "evt_m1abc23",
"type": "lead.created",
"created": "2026-12-17T15:00:00.000Z",
"data": {}
}client.created
client.createdSent as POST with JSON body. Verify the Sarvyam-Signature header: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(your endpoint secret, ${t}.${rawBody}). Reject timestamps older than 5 minutes. Respond 2xx within 10 s; otherwise we retry with backoff (1 m, 5 m, 30 m, 2 h, 6 h, 12 h, 24 h).
Payload
idstringtypestringOne oflead.createdclient.createdquote.sentquote.acceptedquote.declinedbooking.createdbooking.cancelledpayment.receivedgallery.selection_submittedtestcreatedstring · date-timedataobjectDepends on the event type.
Responses
- 200Received
{
"id": "evt_m1abc23",
"type": "lead.created",
"created": "2026-12-17T15:00:00.000Z",
"data": {}
}quote.sent
quote.sentSent as POST with JSON body. Verify the Sarvyam-Signature header: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(your endpoint secret, ${t}.${rawBody}). Reject timestamps older than 5 minutes. Respond 2xx within 10 s; otherwise we retry with backoff (1 m, 5 m, 30 m, 2 h, 6 h, 12 h, 24 h).
Payload
idstringtypestringOne oflead.createdclient.createdquote.sentquote.acceptedquote.declinedbooking.createdbooking.cancelledpayment.receivedgallery.selection_submittedtestcreatedstring · date-timedataobjectDepends on the event type.
Responses
- 200Received
{
"id": "evt_m1abc23",
"type": "lead.created",
"created": "2026-12-17T15:00:00.000Z",
"data": {}
}quote.accepted
quote.acceptedSent as POST with JSON body. Verify the Sarvyam-Signature header: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(your endpoint secret, ${t}.${rawBody}). Reject timestamps older than 5 minutes. Respond 2xx within 10 s; otherwise we retry with backoff (1 m, 5 m, 30 m, 2 h, 6 h, 12 h, 24 h).
Payload
idstringtypestringOne oflead.createdclient.createdquote.sentquote.acceptedquote.declinedbooking.createdbooking.cancelledpayment.receivedgallery.selection_submittedtestcreatedstring · date-timedataobjectDepends on the event type.
Responses
- 200Received
{
"id": "evt_m1abc23",
"type": "lead.created",
"created": "2026-12-17T15:00:00.000Z",
"data": {}
}quote.declined
quote.declinedSent as POST with JSON body. Verify the Sarvyam-Signature header: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(your endpoint secret, ${t}.${rawBody}). Reject timestamps older than 5 minutes. Respond 2xx within 10 s; otherwise we retry with backoff (1 m, 5 m, 30 m, 2 h, 6 h, 12 h, 24 h).
Payload
idstringtypestringOne oflead.createdclient.createdquote.sentquote.acceptedquote.declinedbooking.createdbooking.cancelledpayment.receivedgallery.selection_submittedtestcreatedstring · date-timedataobjectDepends on the event type.
Responses
- 200Received
{
"id": "evt_m1abc23",
"type": "lead.created",
"created": "2026-12-17T15:00:00.000Z",
"data": {}
}booking.created
booking.createdSent as POST with JSON body. Verify the Sarvyam-Signature header: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(your endpoint secret, ${t}.${rawBody}). Reject timestamps older than 5 minutes. Respond 2xx within 10 s; otherwise we retry with backoff (1 m, 5 m, 30 m, 2 h, 6 h, 12 h, 24 h).
Payload
idstringtypestringOne oflead.createdclient.createdquote.sentquote.acceptedquote.declinedbooking.createdbooking.cancelledpayment.receivedgallery.selection_submittedtestcreatedstring · date-timedataobjectDepends on the event type.
Responses
- 200Received
{
"id": "evt_m1abc23",
"type": "lead.created",
"created": "2026-12-17T15:00:00.000Z",
"data": {}
}booking.cancelled
booking.cancelledSent as POST with JSON body. Verify the Sarvyam-Signature header: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(your endpoint secret, ${t}.${rawBody}). Reject timestamps older than 5 minutes. Respond 2xx within 10 s; otherwise we retry with backoff (1 m, 5 m, 30 m, 2 h, 6 h, 12 h, 24 h).
Payload
idstringtypestringOne oflead.createdclient.createdquote.sentquote.acceptedquote.declinedbooking.createdbooking.cancelledpayment.receivedgallery.selection_submittedtestcreatedstring · date-timedataobjectDepends on the event type.
Responses
- 200Received
{
"id": "evt_m1abc23",
"type": "lead.created",
"created": "2026-12-17T15:00:00.000Z",
"data": {}
}payment.received
payment.receivedSent as POST with JSON body. Verify the Sarvyam-Signature header: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(your endpoint secret, ${t}.${rawBody}). Reject timestamps older than 5 minutes. Respond 2xx within 10 s; otherwise we retry with backoff (1 m, 5 m, 30 m, 2 h, 6 h, 12 h, 24 h).
Payload
idstringtypestringOne oflead.createdclient.createdquote.sentquote.acceptedquote.declinedbooking.createdbooking.cancelledpayment.receivedgallery.selection_submittedtestcreatedstring · date-timedataobjectDepends on the event type.
Responses
- 200Received
{
"id": "evt_m1abc23",
"type": "lead.created",
"created": "2026-12-17T15:00:00.000Z",
"data": {}
}gallery.selection_submitted
gallery.selection_submittedSent as POST with JSON body. Verify the Sarvyam-Signature header: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(your endpoint secret, ${t}.${rawBody}). Reject timestamps older than 5 minutes. Respond 2xx within 10 s; otherwise we retry with backoff (1 m, 5 m, 30 m, 2 h, 6 h, 12 h, 24 h).
Payload
idstringtypestringOne oflead.createdclient.createdquote.sentquote.acceptedquote.declinedbooking.createdbooking.cancelledpayment.receivedgallery.selection_submittedtestcreatedstring · date-timedataobjectDepends on the event type.
Responses
- 200Received
{
"id": "evt_m1abc23",
"type": "lead.created",
"created": "2026-12-17T15:00:00.000Z",
"data": {}
}