The customer record.
Every organisation on AI3 has one: the people it has dealt with, what happened with each (the timeline), and what is still to do for them (open items). Every worker AI3 sells writes to it, the receptionist first, so a caller who booked on Monday is known by name on Friday, whichever agent picks up. A business with a CRM of its own keeps it: the record is mirrored to HubSpot or to a webhook, and the AI3 copy stays the one the agents read.
Three verbs
- Upsert a customer. Found by phone number (the last nine digits, so formatting does not matter) or by email; made when new. A field already known is kept unless the new one is fuller, and a placeholder like “Caller” never overwrites a real name. One person is one record.
- Add to the timeline. A dated line saying who did what: an agent (named), the owner, the customer, or the system. Kinds: call, booking, message, enquiry, note, reply, order, invoice, quote, visit, email.
- Open an item. A callback, a booking, a quote, a job, a follow-up or an invoice, with a due time, closed as done or cancelled by whoever did it.
Over HTTP
An owner’s session, or a personal token from Settings as Authorization: Bearer ai3t_…. The token acts only on organisations that account owns.
GET https://ai3.co/api/o/<slug>/customers?q=ortiz the people, and the summary
POST https://ai3.co/api/o/<slug>/customers {"name","phone","email","company","tags","notes","note","kind"} → 201 new, 200 found
GET https://ai3.co/api/o/<slug>/customers/lookup?phone=+17185550142 → {known, customer, history[]}
GET https://ai3.co/api/o/<slug>/customers/cu_… one person: record, timeline, open items
PATCH https://ai3.co/api/o/<slug>/customers/cu_… {"name","phone","email","company","tags","notes"}
POST https://ai3.co/api/o/<slug>/customers/cu_…/notes {"text","kind","agent"}
POST https://ai3.co/api/o/<slug>/customers/cu_…/items {"kind","title","due"}
POST https://ai3.co/api/o/<slug>/customers/items/oi_… {"status":"done"|"cancelled"}
A write answers with mirrored: the connector it went to and whether that succeeded. The AI3 write has already happened either way.
Over MCP
The same record through the AI3 MCP server: list_customers, get_customer (by id, phone or email; says what happened last and what is open), upsert_customer, add_customer_note (with an optional item to open), list_open_items, close_open_item. Writes need confirm: true; without it they say what they would do.
The connector
Set under Customers, or under Phone → Plugged into your systems when the receptionist is hired. AI3 (the default) keeps the record here and needs nothing. HubSpot takes a private app token (Settings → Integrations → Private apps; scopes crm.objects.contacts.read and write): each person becomes a contact, matched on email then phone, and each timeline line a note on it; the HubSpot id is kept on the customer. A webhook gets one signed POST per write:
POST <your url> x-ai3-signature: sha256=<hmac of the body with your secret>
{"action":"contact"|"booking"|"message","business":"…",
"contact":{"id":"cu_…","name","phone","email","company","source"},
"activity":{"kind","text","by":{"kind","name"},"ref":{…},"at"},
"note":"…","message":"…"}
A mirror that fails is noted on the connector (the console shows the last result) and never fails the write that caused it.
What the receptionist writes
Before a call it looks the number up and greets a known caller by name with what happened last and what is open. A booking becomes a customer, a timeline line and an open booking due at the time; a message becomes a customer, a line and an open callback; every finished call adds a line with the outcome and the summary. The owner’s notes on a customer are read back to the receptionist when they call.