prospecting

Permanently delete an archived deal (Archived deals page only — plan 2026-09-04-archived-deal-delete.md). Live deals must be archived first; deals with linked business records (invoices, proposals, expenses, recurring invoices, time entries, or leads merged into this deal) refuse with a structured 409 naming them. A lead id (still pending/dismissed/merged in prospecting_leads) must never reach this far — resolve_deal_or_lead_by_id is dual-table, so we require source == "deals" and 404 otherwise; only a promoted lead's real prospecting_deals row (or a deal that was never a lead) qualifies.

Ordering: prospecting_deals is the only delete that can fail (5 RESTRICT FKs — invoices/proposals/expenses/recurring_invoices/ timetracking — plus the prospecting_leads.merged_into_deal_id NO ACTION reference, all precleared above, but the DB is the final authority) — delete it FIRST. deal_identities has no FK to prospecting_deals (see plan Grounding) so cascade behavior is identical whichever order we delete in; deleting it second means a failure there leaves at worst an orphaned identity row, never a half-gutted live deal. Deleting prospecting_deals CASCADEs pipeline_deal_messages, pipeline_operator_questions, deal_private_latest_activity, deal_members, deal_delivery, member_rates, member_cost_rates (FKs against deal_identities(id) with ON DELETE CASCADE still fire off the identity row, which we delete right after); pipeline_stage_history, contact_recent_google_context_requests SET NULL. No event is emitted — there is nothing left for a timeline entry to attach to once the row is gone.

After the deal row is gone we also sweep the two cross-entity link tables so nothing dangles: entity_links rows where this deal is the subject (entity_type='prospecting_deal', entity_id=deal_id — see services/deal_link_service.py) and event_links rows where this deal is a subject/related entity (entity_type='deal', entity_id=deal_id, a text column — see routes/prospecting_routes.py::_fetch_event_links_chunked usage). Both deletes are org-scoped and best-effort in spirit but run unconditionally as part of the delete transaction's follow-through.

delete/api/prospecting/deals/{deal_id}

Request

  • Base URL: https://api.every.ai (the document declares no server; this is the origin it was published from)
  • URL: https://api.every.ai/api/prospecting/deals/{deal_id}
  • Auth: none declared

Query parameters

user_idstring nullable
org_idstring nullable

Response

Successful Response

unknown required

Changes