POST /v1/deals/{id}/stage
Move a deal to another stage
Move a deal to another stage
Applies the transition through the deal state machine (required fields, automatic tasks, client notifications and the stage_changed event for webhooks). A blocked transition is 409 transition_blocked with missing[]. With dry_run=true nothing is changed and the response says what is missing and shows the client message preview. Supports Idempotency-Key. The key acts with the manager role: stages reserved for other roles (e.g. accountant, logistics) are blocked. Requires scope write:deals.
- Автентифікація: заголовок
Authorization: Bearer rv_live_...(API-ключі та scopes) - Потрібний scope:
write:deals
openapi.json) і подається англійською, як у самому API.Параметри
| Поле | Де | Тип | Обов’язк. | Опис |
|---|---|---|---|---|
id | path | string (uuid) | так | Resource id (UUID). |
dry_run | query | "true" | "false" | ні | true: do not change anything, return what is missing and the client message preview (always 200). |
idempotency-key | header | string | ні | Makes a retry of this POST safe for 24 hours: the same key and body returns the stored response (Idempotent-Replay: true). |
Тіло запиту
| Поле | Тип | Обов’язк. | Опис |
|---|---|---|---|
note | string | null | ні | |
fields | object | ні | |
fields.vehicle | object | ні | |
fields.vehicle.vin | string | null | ні | |
fields.vehicle.make | string | null | ні | |
fields.vehicle.model | string | null | ні | |
fields.vehicle.trim | string | null | ні | |
fields.vehicle.year | integer | null | ні | |
fields.vehicle.body | "sedan" | "hatchback" | "wagon" | "suv" | "crossover" | "coupe" | "convertible" | "minivan" | "van" | "pickup" | "truck" | "motorcycle" | "other" | null | ні | |
fields.vehicle.fuel | "petrol" | "diesel" | "hybrid" | "phev" | "ev" | "lpg" | "cng" | "hydrogen" | "other" | null | ні | |
fields.vehicle.engine | string | null | ні | |
fields.vehicle.engineCc | integer | null | ні | |
fields.vehicle.powerKw | integer | null | ні | |
fields.vehicle.gearbox | "manual" | "automatic" | "cvt" | "robot" | "other" | null | ні | |
fields.vehicle.mileageKm | integer | null | ні | |
fields.vehicle.color | string | null | ні | |
fields.vehicle.source | string | ні | |
fields.vehicle.sourceUrl | string | null (uri) | ні | |
fields.vehicle.lotId | string | null | ні | |
fields.vehicle.titleStatus | "clean" | "salvage" | "rebuilt" | "flood" | "junk" | "parts_only" | "certificate" | "unknown" | null | ні | |
fields.items | object[] | ні | |
fields.items[].id | string (uuid) | ні | |
fields.items[].kind | "lot_price" | "auction_fee" | "broker_fee" | "inland_us" | "ocean" | "port" | "inland_eu" | "customs_duty" | "excise" | "vat" | "broker_customs" | "certification" | "pension_fund" | "registration" | "repair" | "detailing" | "insurance" | "our_fee" | "other" | ні | |
fields.items[].label | string | null | ні | |
fields.items[].planned | number | string | null | ні | |
fields.items[].actual | number | string | null | ні | |
fields.items[].currency | "UAH" | "USD" | "EUR" | "PLN" | "GEL" | ні | |
fields.items[].paidBy | "client" | "company" | ні | |
fields.items[].paidAt | string | null (date-time) | ні | |
fields.items[].documentId | string | null (uuid) | ні | |
fields.items[].note | string | null | ні | |
fields.items[].sort | integer | ні | |
fields.shipment | object | ні | |
fields.shipment.mode | "container" | "roro" | "truck" | ні | |
fields.shipment.carrier | string | null | ні | |
fields.shipment.containerNo | string | null | ні | |
fields.shipment.billOfLading | string | null | ні | |
fields.shipment.bookingNo | string | null | ні | |
fields.shipment.vessel | string | null | ні | |
fields.shipment.voyage | string | null | ні | |
fields.shipment.portFrom | string | null | ні | |
fields.shipment.portTo | string | null | ні | |
fields.shipment.warehouse | string | null | ні | |
fields.shipment.etd | string | null (date-time) | ні | |
fields.shipment.eta | string | null (date-time) | ні | |
fields.shipment.atd | string | null (date-time) | ні | |
fields.shipment.ata | string | null (date-time) | ні | |
fields.shipment.pickupAt | string | null (date-time) | ні | |
fields.shipment.deliveredAt | string | null (date-time) | ні | |
fields.shipment.status | "planned" | "booked" | "loaded" | "in_transit" | "at_port" | "discharged" | "released" | "delivered" | ні | |
fields.customs | object | ні | |
fields.customs.status | "draft" | "documents_sent" | "declared" | "paid" | "cleared" | "rejected" | ні | |
fields.customs.declarant | string | null | ні | |
fields.customs.declarationNo | string | null | ні | |
fields.customs.duty | number | string | null | ні | |
fields.customs.excise | number | string | null | ні | |
fields.customs.vat | number | string | null | ні | |
fields.customs.pensionFund | number | string | null | ні | |
fields.customs.currency | "UAH" | "USD" | "EUR" | "PLN" | "GEL" | ні | |
fields.customs.paidAt | string | null (date-time) | ні | |
fields.customs.clearedAt | string | null (date-time) | ні | |
fields.customs.notes | string | null | ні | |
fields.etaDelivery | string | null (date-time) | ні | |
fields.route | "sea" | "land" | ні | |
fields.destinationCountry | string | null | ні | |
fields.destinationCity | string | null | ні | |
fields.lostReason | string | null | ні | |
attachments | string (uuid)[] | ні | |
notifyClient | boolean | ні | |
messageOverride | string | null | ні | |
channel | "telegram" | "viber" | "email" | "sms" | "webhook" | "in_app" | ні | |
to | "lead" | "consult" | "contract_signed" | "deposit_paid" | "searching" | "bid_approved" | "won" | "paid_to_auction" | "pickup_scheduled" | "at_us_warehouse" | "loaded" | "in_transit_sea" | "at_eu_port" | "inland_to_border" | "customs_clearing" | "customs_cleared" | "certification" | "registration" | "ready_for_handover" | "handed_over" | "closed" | "lost" | "cancelled" | "on_hold" | "dispute" | так | Target stage. |
Відповіді
200
The transition was applied (or previewed with dry_run).
application/json · Схема: StageResult
| Поле | Тип | Обов’язк. | Опис |
|---|---|---|---|
dryRun | boolean | так | |
applied | boolean | так | true: the deal was moved. false only for dry_run. |
from | "lead" | "consult" | "contract_signed" | "deposit_paid" | "searching" | "bid_approved" | "won" | "paid_to_auction" | "pickup_scheduled" | "at_us_warehouse" | "loaded" | "in_transit_sea" | "at_eu_port" | "inland_to_border" | "customs_clearing" | "customs_cleared" | "certification" | "registration" | "ready_for_handover" | "handed_over" | "closed" | "lost" | "cancelled" | "on_hold" | "dispute" | так | |
to | "lead" | "consult" | "contract_signed" | "deposit_paid" | "searching" | "bid_approved" | "won" | "paid_to_auction" | "pickup_scheduled" | "at_us_warehouse" | "loaded" | "in_transit_sea" | "at_eu_port" | "inland_to_border" | "customs_clearing" | "customs_cleared" | "certification" | "registration" | "ready_for_handover" | "handed_over" | "closed" | "lost" | "cancelled" | "on_hold" | "dispute" | так | |
ok | boolean | так | The transition is possible (always true when applied). |
kind | string | null | так | |
skipped | "lead" | "consult" | "contract_signed" | "deposit_paid" | "searching" | "bid_approved" | "won" | "paid_to_auction" | "pickup_scheduled" | "at_us_warehouse" | "loaded" | "in_transit_sea" | "at_eu_port" | "inland_to_border" | "customs_clearing" | "customs_cleared" | "certification" | "registration" | "ready_for_handover" | "handed_over" | "closed" | "lost" | "cancelled" | "on_hold" | "dispute"[] | так | Stages skipped on the way (e.g. sea stages for a land route). |
missing | string[] | так | |
reasonKey | string | null | так | |
reasonRequired | boolean | так | |
notifications | object[] | так | |
notifications[].event | string | ні | |
notifications[].to | string | ні | |
taskIds | string (uuid)[] | так | |
clientMessage | object | так | Preview of the message the client gets (dry_run only). |
clientMessage.channel | string | так | |
clientMessage.locale | string | так | |
clientMessage.title | string | null | так | |
clientMessage.text | string | так | |
clientMessage.warnings | string[] | так | |
deal | object | так | The updated deal (null for dry_run). |
deal.id | string (uuid) | так | |
deal.number | string | так | |
deal.status | "lead" | "consult" | "contract_signed" | "deposit_paid" | "searching" | "bid_approved" | "won" | "paid_to_auction" | "pickup_scheduled" | "at_us_warehouse" | "loaded" | "in_transit_sea" | "at_eu_port" | "inland_to_border" | "customs_clearing" | "customs_cleared" | "certification" | "registration" | "ready_for_handover" | "handed_over" | "closed" | "lost" | "cancelled" | "on_hold" | "dispute" | так | |
deal.pausedFrom | "lead" | "consult" | "contract_signed" | "deposit_paid" | "searching" | "bid_approved" | "won" | "paid_to_auction" | "pickup_scheduled" | "at_us_warehouse" | "loaded" | "in_transit_sea" | "at_eu_port" | "inland_to_border" | "customs_clearing" | "customs_cleared" | "certification" | "registration" | "ready_for_handover" | "handed_over" | "closed" | "lost" | "cancelled" | "on_hold" | "dispute" | null | так | |
deal.type | "full_service" | "auction_only" | "logistics_only" | "resale" | так | |
deal.route | "sea" | "land" | так | |
deal.currency | "UAH" | "USD" | "EUR" | "PLN" | "GEL" | так | |
deal.contactId | string (uuid) | так | |
deal.managerId | string | null (uuid) | так | |
deal.vehicleId | string | null (uuid) | так | |
deal.destinationCountry | string | null | так | |
deal.destinationCity | string | null | так | |
deal.etaDelivery | string | null | так | ISO 8601 date-time (UTC). |
deal.stageDates | object | так | stage -> time of entering it. |
deal.trackingToken | string (uuid) | так | Token of the public tracking page (Track). |
deal.trackingEnabled | boolean | так | |
deal.lostReason | string | null | так | |
deal.closedAt | string | null | так | ISO 8601 date-time (UTC). |
deal.createdAt | string | так | ISO 8601 date-time (UTC). |
deal.updatedAt | string | так | ISO 8601 date-time (UTC). |
400
Invalid request parameters or body (code validation_error).
application/problem+json · Схема: Problem
401
Missing, malformed, unknown, revoked or expired API key (code unauthorized).
application/problem+json · Схема: Problem
403
The API key lacks the scope required by this endpoint (code insufficient_scope).
application/problem+json · Схема: Problem
404
No such deal in this tenant.
application/problem+json · Схема: Problem
409
Conflict: duplicate contact (duplicate_ids), a request with this Idempotency-Key is still being processed, or the stage transition is blocked (missing[]).
application/problem+json · Схема: Problem
422
Well-formed but not acceptable data (unprocessable_input), or Idempotency-Key reused with a different request.
application/problem+json · Схема: Problem
429
Rate limit exceeded for the tenant plan (code rate_limited). Wait Retry-After seconds.
application/problem+json · Схема: Problem