VitrinaAPI

Consignments

The contract under which a dealer sells someone else's car: create, edit, return and sell with its settlement.

Beta
This may change at any time, with a changelog entry and a notice to recent callers — see versioning.

Download the full API pública projection: openapi.json.

Sell a unit explains this resource in prose, with runnable examples.

MethodPathWhat it does
GET/consignmentsList consignment contracts
POST/consignmentsCreate a contract
GET/consignments/{id}Fetch one contract
PATCH/consignments/{id}Update a contract
GET/consignments/{id}/liquidacionFetch the settlement record
POST/consignments/{id}/returnReturn the car to its owner
POST/consignments/{id}/sellSell the car and settle with the owner
GET/consignments/by-vehicle/{vehicleId}The active contract for one vehicle

GET /consignments

List consignment contracts

Filter by vehicle_id and/or estado, with limit / offset. No total is returned — the response carries the rows and nothing else.

ParameterInTypeRequiredConstraints
vehicle_idqueryuuidno
estadoqueryactivo \vendido \devuelto \
limitqueryintegerno≥ 1, ≤ 200
offsetqueryinteger | nullno≥ 0
curl https://api.vitrinadev.com/api/v1/consignments \
  -H "Authorization: Bearer $VITRINA_KEY"

Example response (200)

{
  "data": [
    {
      "id": "d7d7d7d7-0000-4000-8000-000000000001",
      "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
      "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
      "dueno_contact_id": "22222222-0000-4000-8000-000000000004",
      "modalidad": "en_local",
      "contract_structure": "mandato_con_representacion",
      "comision_type": "percentage",
      "comision_value": 10,
      "minimo_clp": 8000000,
      "vencimiento": "2026-12-31",
      "estado": "activo",
      "vencimiento_reminded_at": null,
      "liquidacion_due_notified_at": null,
      "created_at": "2026-08-20T10:00:00.000Z",
      "updated_at": "2026-08-20T10:00:00.000Z",
      "sale_iva_regime": "exento",
      "not_on_lot": false
    }
  ],
  "meta": {
    "total": 1
  }
}

Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429

POST /consignments

Create a contract

Creates it already activo — there is no draft state — and ACTIVATION HAS SIDE EFFECTS on the vehicle: its tenencia becomes consignacion, and minimo_clp, if given, is written through as the vehicle’s floor_price_clp. That floor is load-bearing: the pricing watch clamps every suggestion up to it and refuses to apply below it, so the owner’s minimum is what stops an automated recommendation undercutting them. WITHOUT a minimo_clp the vehicle’s existing floor is left exactly as it was — a contract that names no minimum never clears one the dealer set by hand.

Only vehicle_id and modalidad are required. dueno_contact_id, the comision_type/comision_value pair, minimo_clp and vencimiento are all completable later through PATCH /consignments/\{id\} — this is the contrato mínimo, the shape a dealer can actually produce while classifying stock at the counter. It is a real, active contract and it imposes the tenencia like any other; what is deferred is the terms. Until they are recorded the contract cannot be sold (no commission means no split to settle — 409) and its mandato cannot be printed, and GET /consignments/\{id\}/documentation reports exactly which fields are missing with documentationComplete: false. Completing them clears all three by itself; there is no flag to set.

comision_type and comision_value go together or not at all: a value with no type is unreadable (is 5 five percent or five pesos?).

One active contract per vehicle. A second is a 409, enforced both in the service and by a partial unique index, so the race loses too. The vehicle, and the owner contact when one is given, must belong to the workspace.

comision_type decides how comision_value is read (a percentage or a fixed amount), which is what the Liquidación later subtracts. Answers 201.

Body

FieldTypeRequiredConstraints
vehicle_iduuidyes
dueno_contact_idstring | null—
modalidaden_local \virtualyes
comision_typepercentage \fixed—
comision_valuenumber | null—≥ 0
minimo_clpinteger | null—> 0
minimo_effective_onstring—patrón ^\d{4}-\d{2}-\d{2}$
vencimientostring | null—patrón ^\d{4}-\d{2}-\d{2}$
sale_iva_regimeafecto \exento—
curl -X POST https://api.vitrinadev.com/api/v1/consignments \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
    "dueno_contact_id": "22222222-0000-4000-8000-000000000004",
    "modalidad": "en_local",
    "comision_type": "percentage",
    "comision_value": 10,
    "minimo_clp": 8000000
  }'

Example response (201)

{
  "data": {
    "id": "d7d7d7d7-0000-4000-8000-000000000001",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
    "dueno_contact_id": "22222222-0000-4000-8000-000000000004",
    "modalidad": "en_local",
    "contract_structure": "mandato_con_representacion",
    "comision_type": "percentage",
    "comision_value": 10,
    "minimo_clp": 8000000,
    "vencimiento": "2026-12-31",
    "estado": "activo",
    "vencimiento_reminded_at": null,
    "liquidacion_due_notified_at": null,
    "created_at": "2026-08-20T10:00:00.000Z",
    "updated_at": "2026-08-20T10:00:00.000Z",
    "sale_iva_regime": "exento",
    "not_on_lot": false
  }
}

Answers: 201 · 400 · 401 · 403 · 404 · 409 · 429

GET /consignments/{id}

Fetch one contract

The contract as stored, whatever its state.

ParameterInTypeRequiredConstraints
idpathuuidyes
curl https://api.vitrinadev.com/api/v1/consignments/<id> \
  -H "Authorization: Bearer $VITRINA_KEY"

Example response (200)

{
  "data": {
    "id": "d7d7d7d7-0000-4000-8000-000000000001",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
    "dueno_contact_id": "22222222-0000-4000-8000-000000000004",
    "modalidad": "en_local",
    "contract_structure": "mandato_con_representacion",
    "comision_type": "percentage",
    "comision_value": 10,
    "minimo_clp": 8000000,
    "vencimiento": "2026-12-31",
    "estado": "activo",
    "vencimiento_reminded_at": null,
    "liquidacion_due_notified_at": null,
    "created_at": "2026-08-20T10:00:00.000Z",
    "updated_at": "2026-08-20T10:00:00.000Z",
    "sale_iva_regime": "exento",
    "not_on_lot": false
  }
}

Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429

PATCH /consignments/{id}

Update a contract

Edits the terms, and can move estado — except to vendido, which is a 409 directing you to the sell action, so a sale can never be recorded without producing its Liquidación. Other transitions are checked against the state machine and an illegal one is also a 409.

Moving vencimiento RE-ARMS the expiry reminder: the "already reminded" stamp is cleared, so a pushed-out date produces a fresh nudge rather than staying silent.

Supplying minimo_clp RENEGOTIATES the mínimo rather than editing a column: it appends an immutable revision to the contract’s terms history (GET /consignments/\{id\}/terms), dated minimo_effective_on or today. The new value must DIFFER from the one currently governing — repeating it is a 409, as is a second revision on a date already taken.

A raised minimo_clp writes through to the vehicle’s floor while the contract is active — but clearing it never clears the floor, and neither does the contract ending. The vehicle has one floor column with no record of who set it, so removing it here could silently wipe a floor the dealer set by hand. Clear the vehicle’s floor deliberately if that is what you want.

ParameterInTypeRequiredConstraints
idpathuuidyes

Body

FieldTypeRequiredConstraints
dueno_contact_iduuid—
modalidaden_local \virtual—
comision_typepercentage \fixed—
comision_valuenumber—≥ 0
minimo_clpinteger | null—> 0
minimo_effective_onstring—patrón ^\d{4}-\d{2}-\d{2}$
vencimientostring | null—patrón ^\d{4}-\d{2}-\d{2}$
estadoactivo \vendido \devuelto \
sale_iva_regimeafecto \exento—
curl -X PATCH https://api.vitrinadev.com/api/v1/consignments/<id> \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "minimo_clp": 8300000
  }'

Example response (200)

{
  "data": {
    "id": "d7d7d7d7-0000-4000-8000-000000000001",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
    "dueno_contact_id": "22222222-0000-4000-8000-000000000004",
    "modalidad": "en_local",
    "contract_structure": "mandato_con_representacion",
    "comision_type": "percentage",
    "comision_value": 10,
    "minimo_clp": 8300000,
    "vencimiento": "2026-12-31",
    "estado": "activo",
    "vencimiento_reminded_at": null,
    "liquidacion_due_notified_at": null,
    "created_at": "2026-08-20T10:00:00.000Z",
    "updated_at": "2026-08-20T10:00:00.000Z",
    "sale_iva_regime": "exento",
    "not_on_lot": false
  }
}

Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429

GET /consignments/{id}/liquidacion

Fetch the settlement record

The persisted Liquidación for a contract. It only exists once the contract has been sold — this is a read of a record, not a projection computed on demand, so the figures are what was agreed at settlement even if the terms changed afterwards.

ParameterInTypeRequiredConstraints
idpathuuidyes
curl https://api.vitrinadev.com/api/v1/consignments/<id>/liquidacion \
  -H "Authorization: Bearer $VITRINA_KEY"

Example response (200)

{
  "data": {
    "id": "d8d8d8d8-0000-4000-8000-000000000001",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "consignment_contract_id": "d7d7d7d7-0000-4000-8000-000000000001",
    "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
    "settlement_mode": "stated_commission",
    "amount_venta_clp": 8900000,
    "comision_type": "percentage",
    "comision_value": 10,
    "comision_amount_clp": 890000,
    "monto_owner_clp": 8010000,
    "owner_floor_clp": null,
    "deducciones_clp": 0,
    "retiro_motivo": null,
    "retiro_by": null,
    "paid_at": "2026-09-18T15:00:00.000Z",
    "created_at": "2026-09-18T15:00:05.000Z",
    "updated_at": "2026-09-18T15:00:05.000Z"
  }
}

Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429

POST /consignments/{id}/return

Return the car to its owner

Moves the contract to devuelto and flips the vehicle’s tenencia back to propio. Exactly equivalent to PATCH \{ estado: "devuelto" \} — it exists so the intent reads as a verb rather than a state assignment.

devuelto is the only terminal state that restores propio: a sold or expired contract KEEPS tenencia: consignacion, because the car was sold on consignment and the history should say so.

ParameterInTypeRequiredConstraints
idpathuuidyes
curl -X POST https://api.vitrinadev.com/api/v1/consignments/<id>/return \
  -H "Authorization: Bearer $VITRINA_KEY"

Example response (200)

{
  "data": {
    "id": "d7d7d7d7-0000-4000-8000-000000000001",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
    "dueno_contact_id": "22222222-0000-4000-8000-000000000004",
    "modalidad": "en_local",
    "contract_structure": "mandato_con_representacion",
    "comision_type": "percentage",
    "comision_value": 10,
    "minimo_clp": 8000000,
    "vencimiento": "2026-12-31",
    "estado": "devuelto",
    "vencimiento_reminded_at": null,
    "liquidacion_due_notified_at": null,
    "created_at": "2026-08-20T10:00:00.000Z",
    "updated_at": "2026-09-15T09:00:00.000Z",
    "sale_iva_regime": "exento",
    "not_on_lot": false
  }
}

Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429

POST /consignments/{id}/sell

Sell the car and settle with the owner

One atomic action doing two things: moves the contract to vendido, and produces the Liquidación — sale price minus commission equals the amount owed to the owner, plus the payment record. Requires amount_venta_clp; paid_at records when the owner was actually paid.

Legal only from activo; anything else is a 409. Answers 201 with the contract and the Liquidación.

It does NOT close the vehicle’s side — the estadía close belongs to the vehicle lifecycle, so mark the vehicle sold separately.

ParameterInTypeRequiredConstraints
idpathuuidyes

Body

FieldTypeRequiredConstraints
amount_venta_clpintegeryes> 0
paid_atstring—date-time
curl -X POST https://api.vitrinadev.com/api/v1/consignments/<id>/sell \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount_venta_clp": 8900000,
    "paid_at": "2026-09-18T15:00:00.000Z"
  }'

Example response (201)

{
  "data": {
    "contract": {
      "id": "d7d7d7d7-0000-4000-8000-000000000001",
      "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
      "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
      "dueno_contact_id": "22222222-0000-4000-8000-000000000004",
      "modalidad": "en_local",
      "contract_structure": "mandato_con_representacion",
      "comision_type": "percentage",
      "comision_value": 10,
      "minimo_clp": 8000000,
      "vencimiento": "2026-12-31",
      "estado": "vendido",
      "vencimiento_reminded_at": null,
      "liquidacion_due_notified_at": null,
      "created_at": "2026-08-20T10:00:00.000Z",
      "updated_at": "2026-08-20T10:00:00.000Z",
      "sale_iva_regime": "exento",
      "not_on_lot": false
    },
    "liquidacion": {
      "id": "d8d8d8d8-0000-4000-8000-000000000001",
      "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
      "consignment_contract_id": "d7d7d7d7-0000-4000-8000-000000000001",
      "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
      "settlement_mode": "stated_commission",
      "amount_venta_clp": 8900000,
      "comision_type": "percentage",
      "comision_value": 10,
      "comision_amount_clp": 890000,
      "monto_owner_clp": 8010000,
      "owner_floor_clp": null,
      "deducciones_clp": 0,
      "retiro_motivo": null,
      "retiro_by": null,
      "paid_at": "2026-09-18T15:00:00.000Z",
      "created_at": "2026-09-18T15:00:05.000Z",
      "updated_at": "2026-09-18T15:00:05.000Z"
    }
  }
}

Answers: 201 · 400 · 401 · 403 · 404 · 409 · 429

GET /consignments/by-vehicle/{vehicleId}

The active contract for one vehicle

Answers the question the agent and the test-drive flow actually ask: is this car ours to hand over? Returns the ACTIVE contract (or null) plus a not_on_lot flag.

Use this rather than filtering the list by vehicle_id: a vehicle can have several historical contracts and only ever one active, and this endpoint is the one that resolves that.

ParameterInTypeRequiredConstraints
vehicleIdpathuuidyes
curl https://api.vitrinadev.com/api/v1/consignments/by-vehicle/<id> \
  -H "Authorization: Bearer $VITRINA_KEY"

Example response (200)

{
  "data": {
    "contract": {
      "id": "d7d7d7d7-0000-4000-8000-000000000001",
      "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
      "vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
      "dueno_contact_id": "22222222-0000-4000-8000-000000000004",
      "modalidad": "en_local",
      "contract_structure": "mandato_con_representacion",
      "comision_type": "percentage",
      "comision_value": 10,
      "minimo_clp": 8000000,
      "vencimiento": "2026-12-31",
      "estado": "activo",
      "vencimiento_reminded_at": null,
      "liquidacion_due_notified_at": null,
      "created_at": "2026-08-20T10:00:00.000Z",
      "updated_at": "2026-08-20T10:00:00.000Z",
      "sale_iva_regime": "exento",
      "not_on_lot": false
    },
    "not_on_lot": false
  }
}

Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429

On this page