Assert Deal
PUT /deals/assert
Create or update a deal. Matches by name + company_id.
Deliberately NOT wired into the closed-stage gates or the completeness rule: assert is the sync-shaped surface (external systems pushing state, no human to answer a 400), the same category the internal router excludes for POST /v1/deals/webhook/sync and the CRM pull worker (#15530 “Out of scope”). Only input hygiene applies here: ids must exist and close_date must parse.
#16060: a stage move made here now emits deal.stage_changed and writes
cb_deal_stage_history, like every other stage writer. background_tasks
is injected (not a body field, so the request schema is unchanged) and the
publish is queued only after the session context has exited — a rolled-back
assert publishes nothing. Because assert is the sync-shaped surface, the
SAME stage arrives on every tick of the caller’s poll loop: the event fires
only on an actual transition, never on a re-assert of the current stage.
Authorizations
Parameters
Header Parameters
Request Body required
object
Deal name (match key)
Responses
200
Successful Response
object
object
‘created’ or ‘updated’
object
Whether there are more pages
Items per page
Current page number (1-indexed)
Total number of items
422
Validation Error