API reference

One key, one endpoint. Send a visitor message to any of your bots from your own server and get an AI reply, with retrieval and lead capture handled for you.

Quickstart

  1. Create a key in Account → API keys.
  2. Copy your bot's ID from its dashboard page.
  3. Call the endpoint below.
curl https://khushyan.xyz/api/v1/chat \
  -H "Authorization: Bearer sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "bot": "YOUR_BOT_ID",
    "message": "Do you ship to the US?"
  }'

Authentication

Pass your secret key in the Authorization header as a Bearer token. Keys are scoped to your account and can reach any bot you own. Treat them like passwords, never expose them in browser or mobile code. If a key leaks, revoke it from the dashboard and create a new one.

Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxx

Send a message

POST /v1/chat

Request body

FieldTypeDescription
botstringRequired. The bot ID to message.
messagestringRequired. Visitor text, up to 4000 chars.
conversationstringOptional. Continue a thread by passing the ID returned earlier.

Response

{
  "reply": "Yes! We ship to the US in 3–5 business days.",
  "conversation": "conv_9a1f…"
}

Pass conversation back on the next call to keep context across turns.

List leads

Pull the leads your bots have captured. Returns your most recent leads first. This is how you get your data into your own systems, no database access required.

GET /v1/leads

Query params: bot (filter to one bot), limit (1–100, default 50), before (ISO timestamp, for paging).

curl "https://khushyan.xyz/api/v1/leads?limit=20" \
  -H "Authorization: Bearer sk_live_…"
{
  "data": [
    {
      "id": "lead_…",
      "bot_id": "bot_…",
      "name": "Sarah Williams",
      "email": "sarah@example.com",
      "phone": "+1 555 0100",
      "service": "Wedding photography",
      "intent": "high_intent",
      "created_at": "2026-07-28T10:12:00Z"
    }
  ]
}

List conversations

List conversations, or fetch one with its full transcript by passing conversation.

GET /v1/conversations

# one conversation with messages
curl "https://khushyan.xyz/api/v1/conversations?conversation=CONV_ID" \
  -H "Authorization: Bearer sk_live_…"

List bookings

Pull appointment and order requests captured by your booking bots.

GET /v1/bookings

Query params: bot, status (requested · confirmed · packed · shipped · fulfilled · cancelled), payment_status (unpaid · partial · paid · refunded), limit (1–100), before.

curl "https://khushyan.xyz/api/v1/bookings?status=requested" \
  -H "Authorization: Bearer sk_live_…"

Orders include order_total, payment_status, payment_method, location (delivery address) and tracking_number. Line items are in custom_fields.items as [{ name, quantity, unit_price }] — totals are computed server-side from your catalogue, never from the model.

PATCH /v1/bookings

Advance an order from your own UI. Body: id (required), status, payment_status, tracking_number. Returns the updated record.

curl -X PATCH "https://khushyan.xyz/api/v1/bookings" \
  -H "Authorization: Bearer sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{"id":"<booking_id>","status":"shipped","tracking_number":"BLR123456"}'

Webhooks

Add a webhook under Connections and we POST every new lead and booking to your endpoint. Failed deliveries retry up to 3 times with backoff (network errors, 429 and 5xx); a 4xx is treated as a permanent rejection.

{
  "id": "9f1c…",            // idempotency key — safe to dedupe on
  "event": "booking",       // "lead" | "booking"
  "type": "webhook",
  "data": { "name": "Asha", "email": "…", "order_total": 2097 },
  "sent_at": "2026-07-28T10:15:00.000Z"
}

Verifying the signature

Every request carries X-Khushyaan-Signature: t=<unix>,v1=<hex>. Compute HMAC-SHA256 over `${t}.${rawBody}` with your connection secret and compare in constant time. Reject requests whose t is more than a few minutes old to prevent replay.

import crypto from "crypto";

function verify(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(
    header.split(",").map((p) => p.split("=")),
  );
  // Reject stale timestamps (replay protection)
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rawBody}`)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(v1),
  );
}

Verify against the raw request body, before any JSON parsing — re-serialising changes the bytes and breaks the signature.

GET /v1/webhooks

Recent delivery attempts, for debugging your endpoint. Params: status (success · failed · pending), event, limit (1–100).

curl "https://khushyan.xyz/api/v1/webhooks?status=failed" \
  -H "Authorization: Bearer sk_live_…"

Errors

StatusMeaning
400Missing or invalid body.
401Missing, invalid, or revoked API key.
404Bot not found or not owned by this key.

Ready to build?

Create your first API key and send a message in under a minute.

Get your API key