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

  • contact is your user (external_id and/or email).
  • account is your company or tenant (external_id, optional domain / 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 SDK identify call 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 — live or shadow. 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:

MethodPathPurpose
GET/api/v1/jobsList 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}/steerTell the job something in plain words; it wakes and acts
POST/api/v1/jobs/{id}/statusTurn the job on or off
POST/api/v1/jobs/{id}/modeSwitch 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.

Was this page helpful?