Update Deal
PATCH /deals/{deal_id}
Update a deal (partial update).
Contact operations run in a fixed order within the single transaction:
remove_contact_ids -> add_contact_ids -> contact_roles. That
order is what makes the useful combinations work:
- a contact linked by
add_contact_idsin THIS request can be given a role bycontact_rolesin the same call (roles run last); - an id in both
remove_contact_idsandadd_contact_idsends up linked (add runs after remove), so a role for it still applies; - an id in
remove_contact_idsandcontact_rolesbut NOT inadd_contact_idsis unlinked by the time roles run, so it is a 422 naming that id rather than a role written to a row that no longer exists.
A contact_roles entry for a contact that is neither already linked nor
being added is a 422; the whole transaction rolls back, so a partially
applied batch is not a state this endpoint can produce.
background_tasks carries the deal.stage_changed fan-out only. It is
injected, not a body field, so it does not appear in the OpenAPI schema and
the request contract is unchanged (pinned by
developer_api/tests/test_deal_stage_events.py). Publishing there rather
than inline keeps the Redis round trip off the caller’s latency budget and
makes “strictly after the commit” structural: the task is queued only after
the session context has exited, and FastAPI attaches background tasks to the
SUCCESS response, so a raise anywhere above publishes nothing.
Authorizations
Parameters
Path Parameters
Deal ID (UUID)
Deal ID (UUID)
Header Parameters
Request Body required
object
Mashup_contact_ids to add to the deal (must match the deal’s company; idempotent)
Mashup_contact_ids to remove from the deal (idempotent — unlinked skipped)
Responses
200
Successful Response
object
object
Lightweight contact summary embedded in deal responses.
id is the canonical mashup_contact_id (BigInt), matching how contacts
are addressed everywhere else in the public API (g8_search_contacts,
g8_lookup_person, etc.). role is the contact’s role within THIS deal
(champion / decision_maker / influencer / blocker / coach / end_user) and
is null when no role was set.
Lightweight contact summary embedded in deal responses.
id is the canonical mashup_contact_id (BigInt), matching how contacts
are addressed everywhere else in the public API (g8_search_contacts,
g8_lookup_person, etc.). role is the contact’s role within THIS deal
(champion / decision_maker / influencer / blocker / coach / end_user) and
is null when no role was set.
422
Validation Error