---
title: "events.ingest"
method: POST
path: "/v1/events/ingest"
tags: ["events"]
---

# events.ingest

`POST /v1/events/ingest`

## Request

- Base URL: `https://api.selda.ai`
- URL: `https://api.selda.ai/v1/events/ingest`
- Auth: HTTP bearer

Report that something happened outside Selda (a form, an analysis, an ad response). Creates the lead if new, recognises it if known, records it on the timeline, and can put it on a campaign's review list. Pass autoAdvance to have Selda write the reply from the Brain straight away and leave it in the Sales Inbox, draft.ready is published when it is there. It never sends.

Dispatched to `events.ingest` on `POST /mcp/mutate`. This route is a different URL for the same call: the request is answered by the same dispatcher, with the same authentication, the same scope check, the same organisation scoping and the same refusals.

- Scope: `write`
- A free sandbox key may call it
- Needs the `inboundIntake` entitlement on top of the scope
- MCP tools that wrap the same function: `selda_ingest_event`
- Filled in from your API key, never sent by you: `orgId`

## Request body

- object
  - `projectId` string, required
  - `type` string, required: Caller-defined: "form_submitted", "analysis_completed", "contract_signed", anything.
  - `identity` object, required
    - `email` string
    - `domain` string
    - `linkedinUrl` string
    - `name` string
    - `firstName` string
    - `lastName` string
    - `company` string
    - `jobTitle` string
    - `phone` string
  - `payload` unknown
  - `source` string: Which system reported it, e.g. "evexcreative.com". Stored as `discoverySource`.
  - `occurredAt` union: ISO string or epoch ms. An unusable or out-of-range value falls back to now, and says so.
    - string
    - number
  - `idempotencyKey` string: Replay protection, unique per org. A repeat returns the first result unchanged.
  - `attachToRunId` string: Put the lead on this campaign run's review list as well. The run's own tone, signature, follow-up rhythm and safety rules already exist and are already approved; an inbound lead joining them beats it inventing a process of its own. It joins at the review stage with no message written, exactly like every other lead on that run. A Convex document id in the `campaignRuns` table.
  - `analysis` string: Research the caller already did, used by engineV3 as authoritative grounding.
  - `mediaImageUrl` string: A PICTURE FOR THIS PERSON'S MESSAGE, when the event came with one (15.9.2026). The case this is for: a system finishes an analysis of a company, renders a gif of what it found, and reports the whole thing here in one call. Same four fields and the same rules as `addLead`: public https, placed into this person's draft when it is composed, beaten by nothing except a picture already on their own row. Fresh research is taken as an update on a matched lead and so is a fresh picture, it is what the next message will carry.
  - `mediaLinkUrl` string
  - `mediaAlt` string
  - `mediaWidth` number
  - `tags` string[]
  - `autoAdvance` boolean: Write the reply now, from the Brain, and leave it in the Sales Inbox for a person. Off by default because it spends. It never sends: the draft waits for the same approval as every other draft, and `draft.ready` is published so nobody has to poll to find it. When drafting cannot be done the lead is untouched and `draft.failed` says why.

## Response `200`

The call succeeded.

- object
  - `value` unknown, required
  - `request_id` string, required: Echoed in the `X-Request-Id` header.

## Other responses

- `400`: Unknown route, or arguments the validator refused.
- `401`: Missing, expired or revoked key.
- `403`: The key lacks the scope, the plan entitlement, or is a sandbox key on a live-only function.
- `429`: Rate limited. Wait for the next minute window and retry.
- `500`: The function threw. The message says what, without leaking internals.

---

[API](https://skmtc.dev/selda/apis/selda-api.md) · [All operations](https://skmtc.dev/selda/apis/selda-api/llms.txt) · [OpenAPI document](https://skmtc.dev/selda/apis/selda-api/revisions/f0b115a94c0f?raw)
