API & webhooks

Developer reference · API v1

The Automate Admits REST API lets you push leads from your own web forms and landing pages straight into your inbox, and pull contacts, conversations, and calls into your BI tools. Outbound webhooks fire signed events to your URL so you can wire Automate Admits into your stack without us building anything custom.

The API and webhooks are available on the Growth plan and above. Create keys and register webhook endpoints in the app under Channels & integrations → Developer API & webhooks.

Authentication

Every request authenticates with an API key sent as a bearer token. Create a key in Channels & integrations → Developer API & webhooks → API keys. The full key is shown only once at creation — store it securely. Keys look like aa_<prefix>_<secret>.

Authorization: Bearer aa_live_xxxxxxxxxxxxxxxxxxxxxxxx

Requests without a valid key return 401. Keys on a plan below Growth return 403. Treat keys like passwords: never expose them in client-side code or a browser. POST leads from your server, not from a public web page.

Base URL & format

All endpoints live under:

https://automateadmits.com/api/v1

Requests and responses are JSON (Content-Type: application/json). List endpoints return { "data": [...], "next_cursor": ... }. Single-object endpoints return { "data": {...} }. Errors return { "error": "message" } with an appropriate HTTP status.

Probe a key

get/api/v1/me

Returns the org, plan, API version, and the list of event types you can subscribe to. Useful for verifying a key works.

curl https://automateadmits.com/api/v1/me \
  -H "Authorization: Bearer $AA_KEY"

{ "org_id": "org_...", "org_name": "Acme Recovery", "plan": "growth",
  "version": "1", "events": ["message_received","lead_created", ...] }

Pagination

List endpoints are cursor-paginated, newest first. Pass limit (default 50, max 100). When more results exist, the response includes a next_cursor — pass it back as ?cursor= to fetch the next page. When next_cursor is null, you've reached the end.

GET /api/v1/contacts?limit=100
GET /api/v1/contacts?limit=100&cursor=1718900000000

Creating leads — the #1 use case

POST a lead from your own form or landing page and it lands in your inbox immediately, ready for a human (this endpoint never triggers an AI auto-reply). It creates a contact and a conversation, and optionally an initial inbound message. This fires the lead_created webhook.

post/api/v1/leads (alias: POST /api/v1/contacts)

At least one of name, phone, or email is required.

FieldTypeNotes
namestringLead's full name.
phonestringPhone number.
emailstringEmail address.
messagestringOptional first message from the lead (shown as an inbound message).
sourcestringWhere the lead came from (e.g. Landing page). Defaults to API.
insurancestringOptional.
locationstringOptional.
statusstringOptional initial stage. One of new, hot, ready, sched, followup, intake, admitted, cold, closed. Defaults to new.
curl -X POST https://automateadmits.com/api/v1/leads \
  -H "Authorization: Bearer $AA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jordan Lee",
    "phone": "+15551234567",
    "email": "jordan@example.com",
    "message": "Saw your ad — do you take Aetna?",
    "source": "Google Ads landing page"
  }'

HTTP/1.1 201 Created
{ "data": { "contact_id": "ct_...", "conversation_id": "cv_...",
            "status": "new", "created_at": 1718900000000 } }

Contacts

get/api/v1/contacts

List contacts, newest first. Optional q filters by name, phone, or email. Supports limit and cursor.

get/api/v1/contacts/:id

Fetch a single contact.

Conversations & messages

get/api/v1/conversations

List conversations, newest activity first. Optional status filter. Supports limit and cursor (on last activity).

get/api/v1/conversations/:id

Full conversation snapshot (contact, stage, AI summary, and details).

get/api/v1/conversations/:id/messages

List messages in a conversation, newest first. Supports limit and cursor.

post/api/v1/conversations/:id/messages

Send an outbound reply on the conversation's channel. Body: { "text": "..." }. Delivery and metering behave exactly like sending from the in-app inbox.

curl -X POST https://automateadmits.com/api/v1/conversations/cv_123/messages \
  -H "Authorization: Bearer $AA_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "text": "Hi Jordan — yes, we accept Aetna. When works for a quick call?" }'

Calls

get/api/v1/calls

List calls, newest first. Optional direction = inbound or outbound. Supports limit and cursor. Includes status, duration, numbers, and the linked contact/conversation.

Webhooks

Register a URL under Channels & integrations → Developer API & webhooks → Webhooks and subscribe to the events you care about (subscribe to none to receive all events, including ones we add later). When an event fires, we POST a JSON payload to your URL.

Each delivery carries these headers:

HeaderValue
X-AA-EventThe event type, e.g. lead_created.
X-AA-DeliveryA unique delivery id.
X-AA-Signaturesha256=<hex> — HMAC-SHA256 of the raw request body, keyed by your endpoint's signing secret.
User-AgentAutomateAdmits-Webhooks/1

Respond with any 2xx status to acknowledge. Non-2xx responses are counted as failures and surfaced in the app. Use the Send test button to POST a signed ping payload and confirm your receiver works.

Event types

EventFires when
lead_createdA new lead / conversation is created (including via the API).
lead_hotA lead moves into the hot stage.
call_scheduledAn appointment / call is booked.
call_missedAn inbound call goes unanswered.
human_handoffA conversation is handed off from the AI to a human.
message_receivedA new inbound message arrives from a lead.
stage_changedA conversation's stage changes.
lead_assignedA lead is assigned to a team member.

Verifying signatures

Always verify the X-AA-Signature before trusting a payload. Compute the HMAC-SHA256 of the raw request body (not a re-serialized copy) using your endpoint's signing secret, then compare it to the hex after sha256= using a constant-time comparison.

// Node.js (Express) example
const crypto = require("crypto");

function verify(req) {
  const secret = process.env.AA_WEBHOOK_SECRET;      // your endpoint's signing secret
  const sig = req.get("X-AA-Signature") || "";        // "sha256=<hex>"
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(req.rawBody)                               // the exact bytes we sent
    .digest("hex");
  return sig.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

If you rotate a secret in the app, older payloads signed with the previous secret will no longer verify — roll the secret when you're ready to update your receiver.