For AI agents: markdown of this page — /docs-content-en/entities/deals/move.md documentation index — /llms.txt

Move deal to another stage

POST /v1/deals/:id/move

Moves a deal to another stage of its pipeline. The same call can also move the deal to a different pipeline.

Parameters

Parameter Type Required Description
Parameterid (path) Typenumber Requiredyes DescriptionDeal ID. List: GET /v1/deals

Request fields (body)

Field Type Description
FieldstageId Typestring DescriptionIdentifier of the target stage. Stages of the main pipeline — GET /v1/statuses?filter[entityId]=DEAL_STAGE, stages of the pipeline whose categoryId equals {N} — GET /v1/statuses?filter[entityId]=DEAL_STAGE_{N}
FieldcategoryId Typenumber DescriptionID of the target pipeline. Pass it together with a stageId from that same pipeline when the deal moves between pipelines. List: GET /v1/deal-categories

Fields not listed in the table are ignored.

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/deals/741/move" \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "stageId": "C1:PREPARATION"
  }'

curl — OAuth application

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/deals/741/move" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "stageId": "C1:PREPARATION"
  }'

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/deals/741/move', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    stageId: 'C1:PREPARATION',
  }),
})

const { success, data } = await res.json()

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/deals/741/move', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    stageId: 'C1:PREPARATION',
  }),
})

const { success, data } = await res.json()

Moving to another pipeline

The request body contains a stage of the target pipeline and that pipeline's categoryId:

JSON
{
  "stageId": "C11:NEW",
  "categoryId": 11
}

Response fields

Field Type Description
Fieldsuccess Typeboolean Descriptiontrue on a successful call
Fielddata Typeobject DescriptionThe deal after the call, all fields — see Deal fields
Fielddata.stageId Typestring DescriptionThe stage the deal is on after the call
Fielddata.previousStageId Typestring DescriptionThe stage the deal was on before the call
Fielddata.categoryId Typenumber DescriptionThe pipeline the deal belongs to after the call
Fielddata.movedTime Typestring DescriptionTimestamp of the last stage change, ISO 8601

Response example

The main fields are shown.

JSON
{
  "success": true,
  "data": {
    "id": 741,
    "title": "Equipment delivery",
    "categoryId": 1,
    "stageId": "C1:PREPARATION",
    "previousStageId": "C1:NEW",
    "stageSemanticId": "P",
    "assignedById": 1,
    "movedBy": 1,
    "movedTime": "2026-08-25T10:47:14.000Z",
    "updatedAt": "2026-08-25T10:47:14.000Z"
  }
}

Error response example

404 — no deal with that id:

JSON
{
  "success": false,
  "error": {
    "code": "ENTITY_NOT_FOUND",
    "message": "Item not found"
  }
}

422 — the stage/pipeline that was sent was not applied (for example, a stageId that is not in the dictionary). By that point Bitrix24 has already accepted the write and the deal has been re-read, so the error response contains the re-read deal in data, and error.details lists the unapplied fields with their current values:

JSON
{
  "success": false,
  "error": {
    "code": "STAGE_NOT_APPLIED",
    "message": "Bitrix24 accepted the write but did not apply it: stageId requested \"C1:BOGUS\", still \"C1:NEW\" after re-read. The value is likely not a valid id for this deal — check GET /v1/statuses?filter[entityId]=... (or GET /v1/deal-categories for a pipeline id) for the valid set before retrying. The record was already written and re-read: any OTHER field in the same request may have been applied, so correct the value and send only what still needs changing rather than repeating the whole body.",
    "details": {
      "unappliedFields": ["stageId"],
      "currentValues": {
        "stageId": "C1:NEW"
      }
    }
  },
  "data": {
    "id": 741,
    "title": "Equipment delivery",
    "categoryId": 1,
    "stageId": "C1:NEW"
  }
}

Errors

HTTP Code Description
HTTP404 CodeENTITY_NOT_FOUND DescriptionNo deal with the given id
HTTP422 CodeSTAGE_NOT_APPLIED DescriptionThe stageId/categoryId that was sent was not applied — after the call the value was still the old one (this usually means the stage or pipeline does not exist). Such a call used to return 200 with no warning; now it is an explicit error: details in error.message and error.details, the re-read deal in data
HTTP422 CodeBITRIX_ERROR DescriptionBitrix24 rejected the call itself (not the stage value specifically) — a malformed field, for example. The reason is returned in error.message, and the machine-readable Bitrix24 code in error.b24Code
HTTP403 CodeBITRIX_ACCESS_DENIED DescriptionBitrix24 denied access to the deal
HTTP403 CodeSCOPE_DENIED DescriptionThe key lacks the crm scope
HTTP403 CodeWRITE_BLOCKED_READONLY_KEY DescriptionA key in read-only mode called a write method
HTTP401 CodeTOKEN_MISSING DescriptionThe API key has no configured tokens
HTTP429 CodeRATE_LIMITED DescriptionRequest limit exceeded. The response includes a Retry-After header with the recommended delay

Full list of common API errors — Errors.

Known specifics

  • An empty body is not an error. A call with no stageId/categoryId in the body returns 200, and the deal stays on its previous stage: there is nothing to compare, so this is not STAGE_NOT_APPLIED — the platform only verifies the fields that were actually sent.

See also