Events
Your server tells Aimdoc what happened (POST /api/v1/events). Services
can start a job for that customer, or wake jobs that already exist. You
can also start a job directly from your backend without
emitting an event.
Events are free. Only the service work they cause consumes credits. Authenticate with the same API key as the rest of the External API.
Emit an event
curl -X POST https://api.aimdoc.ai/api/v1/events \
-H "Authorization: Bearer $AIMDOC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "trial.expiring",
"contact": {"external_id": "u_123", "email": "jason@acme.com"},
"account": {"external_id": "acct_9", "domain": "acme.com", "name": "Acme Inc."},
"properties": {"days_left": 3},
"occurred_at": "2026-08-22T14:00:00Z",
"idempotency_key": "trial.expiring:u_123:2026-08-22"
}'
The first time you send a name it appears on Services → Events, where
you can describe it and point a service's event-start list or event
routines at it. Names are yours (trial.expiring). The aimdoc.
namespace is reserved.
Send {"events": [...]} with up to 100 events; the response carries
per-event results.
Subjects
contactis your user (external_idand/oremail).accountis your company or tenant (external_id, optionaldomain/name).- Unknown contacts and accounts are created.
- An event with neither is a broadcast — it is stored, but it cannot start or wake a job that needs a person.
contact.external_id is required for a job to act as that person. Your
API key is the identity authority, the same way a signed
identify is. Email-only contacts stay as
journey records until they carry an external_id. Sending both
contact.external_id and account.external_id on one event also records
that the user belongs to that account.
What happens next
A committed event can create jobs and wake existing ones. The same event can feed any number of each.
Start a job — on the service's Listing tab, under Also start a
job when an event arrives, list the event names (yours or aimdoc.*)
that should create a job. When that event fires for a customer who does
not yet have a job of that service, Aimdoc creates one and runs its setup
wake with the event. Customers who already have a job (on or off) are left
alone — an ended job is never reactivated by an event. An event that names
only an account, with no person, starts nothing.
Wake existing jobs — jobs with an active event routine for that name get a wake. Configure those routines on the service's Setup tab (copied into every job at assignment). Routines answer "what wakes an existing job"; Listing's event list answers "what creates one".
See Services for Listing settings, including shadow mode.
Inputs
When an event starts or wakes a job, put the facts the job needs in
properties. Name them so they line up with the service's setup questions
and instructions. Keep required facts present in the events you emit, or
settle them during the job's setup wake.
Idempotency and dry run
Pass idempotency_key on every write so retries are safe. Choose a key that
encodes the business fact, not the attempt — for example
trial.expiring:${user.id}:${today}. A repeat returns deduplicated: true
and stores nothing.
Add ?dry_run=true while integrating: full validation and subject
resolution, nothing stored, nothing triggered.
const idempotencyKey = `trial.expiring:${user.id}:${today}`
await fetch('https://api.aimdoc.ai/api/v1/events', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.AIMDOC_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'trial.expiring',
contact: { external_id: user.id, email: user.email },
properties: { days_left: daysLeft },
idempotency_key: idempotencyKey,
}),
})
Start a job
Start (or turn back on) a job of a published service for one customer from
your own server — the programmatic counterpart of Assign in the dashboard.
The customer must already exist in your Aimdoc directory (they have
identify'd at least once, or appeared on a
prior event). Unknown external ids return 404; this endpoint never
provisions a new identity (emit an event when you want
Aimdoc to create the contact).
curl -X POST https://api.aimdoc.ai/api/v1/jobs \
-H "Authorization: Bearer $AIMDOC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"service_key": "shipping_go_live",
"customer_external_id": "u_123",
"tenant_external_id": "acct_9",
"mode": "shadow"
}'
service_key— the service's stable key from the dashboard.customer_external_id— the id your SDKidentifycall sent.tenant_external_id— required when a workspace-scoped service's customer belongs to several workspaces.setup_answers— optional answers to the service's setup questions.mode—liveorshadow. Shadow rehearses: the job works as live, but writes to your product and messages to the customer are recorded as "would have" for your team instead of happening. Defaults to the service's New jobs start in setting on Listing.
One job exists per service and customer (or workspace). Calling again
returns the same job and turns it back on if it was off; created in the
response says which.
Related endpoints on the same API key:
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/jobs | List jobs (filter by service_key, customer_external_id, status, mode) |
GET | /api/v1/jobs/{id} | One job with recent events, routines, and messages |
POST | /api/v1/jobs/{id}/steer | Tell the job something in plain words; it wakes and acts |
POST | /api/v1/jobs/{id}/status | Turn the job on or off |
POST | /api/v1/jobs/{id}/mode | Switch shadow ↔ live (going live queues a wake) |
To render the catalog in your app instead of calling from the server, see Services catalog.
Native Aimdoc events
Aimdoc also records what happens inside the product (new session, contact
captured, meeting booked, and the rest of the webhook
catalog). Those names appear on Services → Events with the aimdoc.
prefix. You can list them under Also start a job when an event arrives
or on a job's event routines the same way you use your own names.
You cannot emit names in the aimdoc. namespace from your API key.
Webhooks out
To be notified when things happen inside Aimdoc (a service run completing,
native product events), create webhook subscriptions under
Integrations → Webhooks. Treat deliveries as at-least-once — the event
id is your dedup key.
See the Webhooks guide and the Webhooks reference.