← Back to home

API Documentation

The public REST API is included on the Agency Pro plan. Run the CRM, reply across every inbox, manage the calendar, send quotes and invoices, text from the workspace number, read forms and tables, work the chatbot queue, act on Agent Ivan's suggestions, publish social posts, post to communities, provision sub-accounts, and subscribe to webhooks — for your agency workspace or any of your client sub-accounts.

Authentication

Create API keys in Sub-accounts → API & webhooks. Every request must include the key as a bearer token. Keys are scoped — grant only the scopes an integration needs — and can be revoked at any time.

curl https://agentivan.ai/api/v1/contacts \
  -H "Authorization: Bearer aiv_..."

By default requests operate on your agency workspace. To act on a client sub-account, pass its id in the X-Tenant-Id header (find ids via GET /api/v1/sub-accounts):

curl https://agentivan.ai/api/v1/contacts \
  -H "Authorization: Bearer aiv_..." \
  -H "X-Tenant-Id: 6f6a7f2e-..."

Rate limit: 120 requests/minute per key (429 with a Retry-After header when exceeded). Errors return { "error": { "code", "message" } }.

Contacts (CRM)

GET/api/v1/contacts

List leads. Query: q (search name/email/phone), stage_id, limit, offset.

POST/api/v1/contacts

Create a lead. Body: name, email, phone, message, stage_id, assigned_to, source (at least one of name/email/phone).

GET/api/v1/contacts/:id

PATCH/api/v1/contacts/:id

Update any of: name, email, phone, message, stage_id, value, address fields. Emits lead.updated, plus lead.stage_changed when the stage moves.

DELETE/api/v1/contacts/:id

GET/api/v1/stages

The pipeline stages, in board order — the ids to use for stage_id.

GET/api/v1/contacts/:id/activities

The contact's timeline (notes, emails, calls, stage changes), newest first.

POST/api/v1/contacts/:id/notes

Log a note. Body: body.

POST/api/v1/contacts/:id/assign

Set the owner. Body: assigned_to (member id, or null to unassign).

Scope: contacts.

Conversations (Unibox)

GET/api/v1/conversations?channel=sms|social|email

List threads for a channel, newest first.

GET/api/v1/conversations/:id?channel=sms|social|email

The full transcript for one thread.

POST/api/v1/conversations/reply

Send a reply. Body: kind (email | sms | social), id (thread/row id from the list endpoint), body. SMS replies debit the workspace's phone usage wallet.

POST/api/v1/conversations/sms

Start a new SMS thread from the workspace's number. Body: to or contact_id, and body. Returns 402 when the usage balance is too low.

Scope: conversations.

Calendar & bookings

GET/api/v1/booking-types

GET/api/v1/booking-types/:id/slots

Bookable slots grouped by day — availability rules, buffers, notice, existing bookings and connected calendars all applied.

GET/api/v1/bookings

Query: from, to (ISO), status.

POST/api/v1/bookings

Body: booking_type_id, name, email, starts_at (ISO), phone, fields. Validated against live availability; 409 when the slot is taken.

GET/api/v1/bookings/:id

POST/api/v1/bookings/:id/cancel

Body: reason (optional). Drops the calendar event and emails the attendee and the owner.

POST/api/v1/bookings/:id/reschedule

Body: starts_at (ISO). Keeps the duration, moves the calendar event, re-sends the invite.

Scope: bookings.

Quotes & invoices

GET/api/v1/quotes

Query: status, lead_id.

GET/api/v1/quotes/:id

Includes line items.

POST/api/v1/quotes

Create a draft. Body: client (contact_id or email plus optional name/phone/address), line_items (name, quantity, unit_price, …), title, discount, tax, valid_until, collect_signature. Totals and the quote number are computed for you.

POST/api/v1/quotes/:id/send

Emails the quote and marks it sent.

POST/api/v1/quotes/:id/convert

Creates a draft invoice from the quote. Returns invoice_id.

GET/api/v1/invoices

Query: status, lead_id.

GET/api/v1/invoices/:id

Includes line items.

POST/api/v1/invoices

Create a draft. Same client and line_items shape as quotes, plus due_date, payment_terms and allow_online_payment.

POST/api/v1/invoices/:id/send

Emails the invoice (with its payment link) and marks it sent.

Scope: invoices.

Phone & SMS

GET/api/v1/phone/numbers

The workspace's provisioned numbers, primary first.

POST/api/v1/phone/sms

Send a text. Body: to or contact_id, and body. Matches (or creates) the contact and lands in the same thread the Unibox shows.

Scope: phone.

Forms

GET/api/v1/forms

GET/api/v1/forms/:id/submissions

Completed submissions, newest first. Pass partial=true to include abandoned saves.

Scope: forms. Every completed submission also fires the form.submitted webhook.

Tables

GET/api/v1/tables

GET/api/v1/tables/:id/rows

Paged rows plus the column definitions. Query: q, limit, offset.

POST/api/v1/tables/:id/rows

Add a row. Body: fields (keys may be column ids, names or slugs) and an optional dedupe_key — posting the same key twice updates instead of duplicating. Row automations fire exactly as they do for a form entry.

Scope: tables.

Chatbot & tickets

GET/api/v1/chatbot/conversations

Widget chats. Query: status, source.

GET/api/v1/chatbot/conversations/:id

The conversation with its full message history.

GET/api/v1/chatbot/tickets

Escalated chats waiting on a human. Query: status.

POST/api/v1/chatbot/tickets/:id/reply

Reply as staff. Body: body. Takes the conversation over from the bot and reopens it if it was closed.

Scope: chatbot.

Agent Ivan

GET/api/v1/ivan/suggestions

Ivan's queue, highest confidence first. Query: status (defaults to suggested; pass all for everything), action_type.

POST/api/v1/ivan/suggestions/:id/approve

Apply an internal suggestion — stage change, deal value, reminder and the like. Suggestions that send a message to a customer still need a human in the dashboard and return 400 here.

POST/api/v1/ivan/suggestions/:id/dismiss

Decline it. Recorded as a learning signal so Ivan surfaces fewer like it.

Scope: ivan.

Social posting

GET/api/v1/social/posts

Query: group_id, limit.

POST/api/v1/social/posts

Body: group_id, content, image_url, scheduled_at (ISO; publishes automatically when due) or publish: true (publish immediately). The content fans out to every account connected to the group.

Scope: social.

Communities

GET/api/v1/communities

Communities with their channels.

GET/api/v1/communities/messages?channel_id=

POST/api/v1/communities/messages

Body: channel_id, body. Posts as the community owner.

Scope: communities.

Sub-account provisioning

GET/api/v1/sub-accounts

POST/api/v1/sub-accounts

Body: name, template_tenant_id (clone structure from one of your template workspaces). Quota-gated by your plan.

GET/api/v1/sub-accounts/:id

DELETE/api/v1/sub-accounts/:id

Archives the account (data retained, access revoked). Fails while it still has active connections.

Scope: sub_accounts.

Usage & billing reads

GET/api/v1/usage

Plan, subscription status, lead-credit balance, and phone usage balance for the target tenant.

Scope: usage.

Webhooks

Register HTTPS endpoints (in the dashboard or via the API) to receive events for your agency and all of its sub-accounts. Deliveries are signed and retried with exponential backoff for up to 8 attempts.

GET/api/v1/webhooks

POST/api/v1/webhooks

Body: url (https), events (omit for all). Returns the signing secret once.

DELETE/api/v1/webhooks/:id

Events: lead.created, lead.updated, lead.stage_changed, message.inbound, booking.created, booking.cancelled, booking.rescheduled, quote.sent, quote.approved, invoice.sent, invoice.paid, form.submitted, ivan.suggestion.created, sub_account.created, sub_account.archived.

Verify deliveries by recomputing the HMAC over the raw request body:

// X-Agency-Event:     lead.created
// X-Agency-Signature: sha256=<hex>
import { createHmac, timingSafeEqual } from "node:crypto";

function verify(secret: string, rawBody: string, signature: string): boolean {
  const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
  return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}

Payload shape: { "event", "tenant_id", "agency_tenant_id", "created_at", "data" }

Scope (for managing endpoints via API): webhooks.

Support

Questions or need a higher rate limit? Email hello@agentivan.ai.

API Documentation — Agent Ivan