Skip to main content
POST
RecordLeadNextActionAPI records a person's hold or close on one lead. It

Authorizations

Authorization
string
header
required

An Erdo API key (erdo_api_...) or scoped token (erdo_token_...).

Path Parameters

datasetSlug
string
required
leadRef
string
required

Body

application/json
kind
string
required
decided_by_external_ref
string
note
string
until
string<date-time>

Response

Success response

accompanying_email
AccompanyingEmailState is what a surface needs to render the email that went · object

out beside a gated decision: whether it went, when, in what words, and why it did not if it did not.

It joins the row's own columns (the authoritative state) with the draft stored in action_input, so a caller does not have to read two things and work out which one is true.

action_input
object
action_kind
string
approval_request_id
string
canonical_lead_id
string
created_by
string
dataset_id
string
decided_at
string<date-time>
decided_by
string
decided_by_external_ref
string

handles for the person who decided this action and the person who took that decision back — opaque strings Erdo stores verbatim and never interprets.

They exist because an application built on `/v1` authenticates a whole team with ONE organization API key, so DecidedBy — the Erdo account that key belongs to — is the same person for every decision anybody there makes. The caller is the only party that can say which of its users acted, so it says, and it resolves these back to names on its own side.

ATTRIBUTION, NEVER AUTHENTICATION. Anything holding the organization's key can write any value here; Erdo does not verify it, must never branch on it, authorize by it, or resolve it against an Erdo identity. It is fine for "Approved by Ana" on a card and must never be presented as proof of who acted. Empty means the caller offered no name, which is every decision made before this existed.

due_at
string<date-time>
error
string
evaluated_at
string<date-time>
executed_at
string<date-time>
execution_ref
string
facts
LeadFacts is what the evaluation understood about the lead. A nil field · object

means the lead has not told us.

handoff_alert
HandoffAlertState is what a surface needs to render the alert that told the · object

desk a handoff is waiting: whether it went, when, the message to open, and why it did not go if it did not.

The alert IS a handoff's delivery. Nothing else happens when a handoff is carried out — deliverHandoff records the literal string "accepted" and sends nothing — so a surface that wants to say what a handoff DID has to read this and not the row's execution ref. It is also why these facts are exposed at all: a sent alert is a real, openable message, and the timeline used to show a handoff as an unopenable line that mentioned no email whatever.

It reads only the row's own columns, unlike AccompanyingEmailState, because the alert's words are not drafted onto the decision — they are composed at send time from the card by buildHandoffAlert. The message itself is read back from the email service by ExecutionRef, which is the only copy of it there is.

id
string
lead_reference
string
mode
string
model
string
playbook_revision
integer<int64>
policy_digest
string

is what says whether the decision is stale — not the revision number. The revision bumps on every save, so a decision at revision 9 may have been decided under exactly the rules revision 10 carries; comparing it with LeadPlaybook.PolicyDigest answers the question the revision only hints at. Empty on every decision written before digests existed and on one a person recorded by hand. See policy.go for the two halves it is made of.

priority
string
priority_reason
string
rationale
string
revisit_at
string<date-time>
rule
string
source
string
stage
string
status
string
undone_by_external_ref
string