---
title: "Create a deal"
method: POST
path: "/api/v1/rest/crm/deals"
tags: ["CRM"]
---

# Create a deal

`POST /api/v1/rest/crm/deals`

## Request

- Base URL: `https://api.custodo.ai`
- URL: `https://api.custodo.ai/api/v1/rest/crm/deals`
- Auth: HTTP bearer

Opens a trattativa on an existing customer: a title, the anagrafica, a figure and the date it is expected to close — both `party_id` and `expected_close_date` are required, because an opportunity without either is one the forecast cannot add up. It refuses to file an unqualified enquiry (that is crm_create_lead) and it cannot move or close the deal it creates (that is crm_advance_deal). It appears in the pipeline immediately, so confirm the details with the user first.

## Headers

- `X-Tenant-Id` string, uuid

## Request body

- object
  - `title` string, required: What the trattativa is about, as it should read in the pipeline.
  - `party_id` string, uuid, required: The customer. Required — an opportunity always hangs off an anagrafica. From anagrafiche_search_parties, or anagrafiche_create_party when the customer is new. A deleted anagrafica is refused.
  - `contact_id` string, uuid: The person at that customer — an anagrafica of kind `person`, from anagrafiche_search_parties.
  - `pipeline_id` string, uuid: Which pipeline. Omit for the organisation’s default one.
  - `stage_id` string, uuid: Where it starts. Omit for the pipeline’s first non-terminal stage; the ids come from crm_list_lookups or crm_deals_board.
  - `amount` number: Expected value in `currency`. 0 when nobody has said a figure yet.
  - `currency` string: ISO-4217, three uppercase letters — EUR, USD, CHF.
  - `probability` number: 0–100, never 0–1. Omit to inherit the landing stage’s own default.
  - `expected_close_date` string, required: When it is expected to close, YYYY-MM-DD. Required: an open opportunity with no date is one the forecast cannot add up.
  - `owner_user_id` string, uuid: Whose deal it is. Omit and it becomes yours.
  - `source` string: Where it came from — «sito», «passaparola», «fiera». Free text.

## Response `200`

Done. `data` is the tool’s own answer.

- RestResult
  - `ok` true, required
  - `data` unknown, required

## Other responses

- `400`: The arguments did not validate: `error.message` names the field, what it expects and what arrived.
- `401`: No API key, or one that is malformed, unknown, revoked or expired.
- `403`: The call never ran: the module is off for this organisation, the credential lacks the permission or the module, the tier does not cover it, or the tool is destructive and the key was not minted for that.
- `409`: The record is in a state that does not allow it — under legal hold, already sent, already closed. `error.code` says which.
- `422`: The tool ran and refused, in a sentence of its own (`TOOL_REFUSED`): the message says what to change. Retrying the same call will not help.
- `429`: The API key has spent its minute, or its day. Every request a key makes counts. See `Retry-After`.

---

[API](https://skmtc.dev/custodo/apis/custodo-integrazioni.md) · [All operations](https://skmtc.dev/custodo/apis/custodo-integrazioni/llms.txt) · [OpenAPI document](https://skmtc.dev/custodo/apis/custodo-integrazioni/revisions/16d336d3ec2a?raw)
