Deals

Create, read, update and delete Deals, and move them through pipeline stages.

A Deal is a sales opportunity with an Account. It sits at a stage in a pipeline.

The Deal object#

Field Type Notes
id string UUID.
name string
value number or null In the workspace's currency (see currency on GET /me).
value_period string once_off, monthly, quarterly or yearly. Says whether value is a one-time or recurring amount.
probability integer or null Percent chance of winning, 0 to 100.
expected_close_at string or null ISO 8601 timestamp.
actual_close_at string or null ISO 8601 timestamp. Read-only through the API.
stage_id string The Deal's stage. See Stage IDs.
account_id string The Account the Deal is with.
owner_id string or null User ID of the Deal's owner.
pipeline_id string or null The pipeline the Deal is in. null means the workspace's default pipeline.
created_at string ISO 8601 timestamp.
updated_at string ISO 8601 timestamp.
JSON
{
  "id": "7c2e9f14-3a6b-4d1e-8f5a-9b0c2d4e6f81",
  "name": "Contoso renewal 2027",
  "value": 48500,
  "value_period": "yearly",
  "probability": 60,
  "expected_close_at": "2026-12-15T00:00:00.000Z",
  "actual_close_at": null,
  "stage_id": "rds_proposal",
  "account_id": "3f6c2a1e-8b4d-4c2a-9f1e-2b7d5a9c4e10",
  "owner_id": "5b8d1f3a-7e2c-4a9b-b6d4-1c3e5f7a9b20",
  "pipeline_id": null,
  "created_at": "2026-11-12T09:30:00.000Z",
  "updated_at": "2026-11-12T09:30:00.000Z"
}

Stage IDs#

A Deal's stage_id is a deal stage ID. It is not the id of a stage returned by GET /pipelines: pipeline stages are matched to deal stage IDs by their code (ignoring case).

The stage must belong to the Deal's pipeline, or to the workspace's default pipeline when the Deal has none. Otherwise the request answers 422 INVALID_STAGE.

Deal stage IDs for Signal's standard stage codes:

Pipeline stage code stage_id
qualification rds_qualification
discovery rds_discovery
proposal rds_proposal
negotiation rds_negotiation
closed_won rds_closed_won
closed_lost rds_closed_lost

For any other stage (including stages you created), read stage_id from an existing Deal in that stage.

What a stage means (open, won or lost) comes from the pipeline stage's is_won and is_lost flags.


List Deals#

GET /deals · Scope: deals:read

Returns Deals newest first.

Query parameters#

Parameter Type Required Notes
limit integer No 1 to 100. Default 20.
cursor string No meta.cursor from the previous page.

Example#

curl "https://crm.empiraa.app/api/v1/deals?limit=100" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response 200#

JSON
{
  "data": [
    {
      "id": "7c2e9f14-3a6b-4d1e-8f5a-9b0c2d4e6f81",
      "name": "Contoso renewal 2027",
      "value": 48500,
      "value_period": "yearly",
      "probability": 60,
      "expected_close_at": "2026-12-15T00:00:00.000Z",
      "actual_close_at": null,
      "stage_id": "rds_proposal",
      "account_id": "3f6c2a1e-8b4d-4c2a-9f1e-2b7d5a9c4e10",
      "owner_id": null,
      "pipeline_id": null,
      "created_at": "2026-11-12T09:30:00.000Z",
      "updated_at": "2026-11-12T09:30:00.000Z"
    }
  ],
  "meta": { "cursor": null, "hasMore": false },
  "error": null
}

Create a Deal#

POST /deals · Scope: deals:write · Supports Idempotency-Key

Request body#

Field Type Required Notes
name string Yes
account_id string Yes An Account in this workspace.
stage_id string Yes A deal stage ID in the Deal's pipeline. See Stage IDs.
pipeline_id string or null No A pipeline in this workspace. Leave out for the default pipeline.
value number or null No
value_period string No once_off (default), monthly, quarterly or yearly.
probability integer No 0 to 100. Default 50.
expected_close_at string or null No ISO 8601 date or timestamp.
owner_id string or null No A user ID from GET /users.

Example#

curl -X POST https://crm.empiraa.app/api/v1/deals \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8b0f6c1e-2d4a-4f7b-9c3e-5a1d7e9b2c40" \
  -d '{
    "name": "Contoso renewal 2027",
    "account_id": "3f6c2a1e-8b4d-4c2a-9f1e-2b7d5a9c4e10",
    "stage_id": "rds_proposal",
    "value": 48500,
    "value_period": "yearly",
    "expected_close_at": "2026-12-15"
  }'

Response 201#

The new Deal object in data.

Errors#

Status Code When
400 INVALID_REQUEST name, stage_id or account_id is missing; pipeline_id isn't a string; or expected_close_at isn't a date.
404 NOT_FOUND The Account or pipeline doesn't exist in this workspace, or owner_id isn't an active member of the workspace.
422 INVALID_STAGE stage_id isn't a stage of the Deal's pipeline.

Webhook events: deal.created.


Get a Deal#

GET /deals/{id} · Scope: deals:read

Path parameters#

Parameter Type Notes
id string Deal ID.

Example#

curl https://crm.empiraa.app/api/v1/deals/7c2e9f14-3a6b-4d1e-8f5a-9b0c2d4e6f81 \
  -H "Authorization: Bearer YOUR_API_KEY"

Response 200#

The Deal object in data.

Errors#

Status Code When
404 NOT_FOUND No Deal with that ID in this workspace.

Update a Deal#

PATCH /deals/{id} · Scope: deals:write

Send only the fields you want to change.

Request body#

Field Type Notes
name string
value number or null
probability integer 0 to 100.
stage_id string A deal stage ID in the Deal's pipeline. See Stage IDs.
expected_close_at string or null ISO 8601 date or timestamp.

Other fields, including owner_id, value_period, pipeline_id and account_id, can't be changed through this endpoint and are ignored.

Example: move to a new stage#

curl -X PATCH https://crm.empiraa.app/api/v1/deals/7c2e9f14-3a6b-4d1e-8f5a-9b0c2d4e6f81 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"stage_id": "rds_negotiation", "probability": 80}'

Response 200#

The updated Deal object in data.

Errors#

Status Code When
400 INVALID_REQUEST expected_close_at isn't a date.
404 NOT_FOUND No Deal with that ID in this workspace.
422 INVALID_STAGE stage_id isn't a stage of the Deal's pipeline.

Webhook events: deal.won when this request raises probability to 100 or more from below 100. Changing stage_id alone doesn't send deal.won.


Delete a Deal#

DELETE /deals/{id} · Scope: deals:write

Deletes the Deal permanently. This can't be undone.

Example#

curl -X DELETE https://crm.empiraa.app/api/v1/deals/7c2e9f14-3a6b-4d1e-8f5a-9b0c2d4e6f81 \
  -H "Authorization: Bearer YOUR_API_KEY"

Response 204#

No body.

Errors#

Status Code When
404 NOT_FOUND No Deal with that ID in this workspace.

Webhook events: none.