Vender una unidad
Los documentos con que una automotora cotiza, reserva y vende.
AutomotorasSolo en los workspaces de automotoras.
POST /quotes emite una cotización y le asigna su folio. POST /reservations bloquea la unidad. POST /sale-notes la vende, y el auto pasa a vendido cuando alguien aprueba esa nota.
Ninguno de los nueve recursos de abajo se edita libremente. Cada uno acepta un conjunto corto de verbos. Anular deja el folio y la razón en el documento; corregir es anular y volver a emitir.
| Recurso | Scope | Qué es |
|---|---|---|
| Publicaciones | marketplace:read / marketplace:write | El estado del auto en cada portal conectado. |
| Cotizaciones | quotes:read / quotes:write / quotes:void | Una oferta de precio congelada. No reserva nada. |
| Reservas | reservations:read / reservations:write / reservations:void / reservations:dispose_abono | Un cupo bloqueado sobre una unidad, con abono opcional. |
| Notas de venta | sale_notes:read / sale_notes:write / sale_notes:void | El documento que vende el auto. |
| Notas de compra | purchase_notes:read / purchase_notes:write / purchase_notes:void | El documento que le da costo a un auto que entra. |
| Pagos de documentos | document_payments:read / document_payments:write | Dinero contra una reserva o una nota de venta. |
| Consignaciones | consignments:read / consignments:write | El contrato bajo el cual se vende el auto de otra persona. |
| Solicitudes de crédito | credit_applications:read / credit_applications:write | El expediente que persigue una carpeta bancaria. |
| Aprobaciones de precio | price_approval:read / price_approval:request / price_approval:approve | La autoridad sobre un precio bajo el de referencia. |
Todos estos POST aceptan Idempotency-Key. Repetir la llamada con el mismo valor devuelve el documento ya emitido y no consume otro folio. Los códigos que puedes recibir están en Errores.
Las respuestas de esta página salen de una corrida contra un workspace de prueba. Los identificadores serán otros; la forma es la misma.
Publicar en portales
curl -X POST https://api.vitrinadev.com/api/v1/vehicles/de7d959a-292f-4491-92ce-2028fa9114f0/publish \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{ "integration_ids": ["e6038419-209e-42e2-80ed-2a8451156a8a"] }'integration_ids nombra los portales a los que quieres publicar. La respuesta trae un veredicto por integración, así que un 200 todavía no significa que el aviso esté arriba:
{
"data": [
{
"integration_id": "e6038419-209e-42e2-80ed-2a8451156a8a",
"provider": "facebook_marketplace",
"status": "pending",
"external_id": "fbm-task:b802ddef-cf01-41e6-9072-2f571c06acfc",
"publication": {
"id": "aed50dde-d45b-47f2-9564-fdcb296b14f3",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"vehicle_id": "de7d959a-292f-4491-92ce-2028fa9114f0",
"marketplace_account_id": "e6038419-209e-42e2-80ed-2a8451156a8a",
"provider": "facebook_marketplace",
"external_id": "fbm-task:b802ddef-cf01-41e6-9072-2f571c06acfc",
"status": "pending",
"origin": "vitrina",
"permalink": null,
"last_synced_at": null,
"last_published_at": "2026-09-23T01:28:12.731Z",
"last_error": null,
"close_retry_count": 0,
"portal_state": null,
"portal_state_at": null,
"raw_provider_payload": {
"taskId": "b802ddef-cf01-41e6-9072-2f571c06acfc"
},
"created_at": "2026-09-23T01:28:12.743Z",
"updated_at": "2026-09-23T01:28:12.743Z"
}
}
]
}Trampa
Facebook Marketplace responde pending porque no hay aviso todavía
La publicación la completa la extensión de Vitrina en el navegador de un
vendedor, a su propio ritmo. Por eso external_id es un identificador
provisorio (fbm-task:…) y permalink viene en null. Si la extensión está
apagada o en pausa, la publicación no avanza. El resultado real llega por
GET /vehicles/{id}/publications o por los eventos de más abajo.
DELETE /vehicles/{id}/publications/{pubId} retira una publicación puntual y POST /vehicles/{id}/close-ads cierra todas las de un auto. La fila nunca desaparece: queda con el estado terminal del portal, así que «¿qué pasó con esa publicación?» siempre tiene respuesta.
{
"data": {
"id": "aed50dde-d45b-47f2-9564-fdcb296b14f3",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"vehicle_id": "de7d959a-292f-4491-92ce-2028fa9114f0",
"marketplace_account_id": "e6038419-209e-42e2-80ed-2a8451156a8a",
"provider": "facebook_marketplace",
"external_id": "fbm-task:b802ddef-cf01-41e6-9072-2f571c06acfc",
"status": "removing",
"origin": "vitrina",
"permalink": null,
"last_synced_at": null,
"last_published_at": "2026-09-23T01:28:12.731Z",
"last_error": null,
"close_retry_count": 0,
"portal_state": null,
"portal_state_at": null,
"raw_provider_payload": {
"taskId": "b802ddef-cf01-41e6-9072-2f571c06acfc"
},
"created_at": "2026-09-23T01:28:12.743Z",
"updated_at": "2026-09-23T01:28:22.295Z"
}
}Cotizar
curl -X POST https://api.vitrinadev.com/api/v1/quotes \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"vehicle_id": "de7d959a-292f-4491-92ce-2028fa9114f0",
"buyer_contact_id": "01a0cbdd-304a-70d8-951f-5e4b481301c9",
"offered_price_clp": 8990000,
"tax_treatment": "afecto",
"expires_on": "2026-09-30"
}'{
"data": {
"id": "982dd531-6b1a-49f1-a947-f8520e7bb648",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"display_id": "Q-7",
"display_seq": 7,
"vehicle_id": "de7d959a-292f-4491-92ce-2028fa9114f0",
"buyer_contact_id": "01a0cbdd-304a-70d8-951f-5e4b481301c9",
"salesperson_id": null,
"list_price_clp": 8990000,
"offered_price_clp": 8990000,
"tax_treatment": "afecto",
"discount_pct": 0,
"unit_make": "Peugeot",
"unit_model": "208",
"unit_version": "Active 1.2",
"unit_year": 2021,
"unit_plate": "KXPW34",
"unit_vin": "VF3CCHMZ6MT012345",
"unit_odometer_value": 38200,
"unit_odometer_unit": "KM",
"unit_color": "Gris",
"discount_hidden": false,
"issued_at": "2026-09-23T01:24:47.318Z",
"expires_on": "2026-09-30",
"state": "vigente",
"voided_at": null,
"void_reason": null,
"voided_by": null,
"extended_at": null,
"extend_reason": null,
"extended_by": null,
"archived_at": null,
"archive_reason": null,
"archived_by": null,
"created_at": "2026-09-23T01:24:47.318Z",
"updated_at": "2026-09-23T01:24:47.318Z"
}
}Los campos unit_* son la identidad del auto congelada al emitir: marca, modelo, versión, año, patente, VIN, kilometraje y color. Repreciar o corregir el auto después no cambia ninguna cotización ya emitida, y por eso esos campos tampoco son parámetros de entrada.
El folio Q-7 sirve en cualquier ruta que acepte {id}. state es derivado (vigente, expirada o nula) y una cotización sigue vigente durante todo el día de expires_on.
Un documento emitido acepta exactamente tres cambios: POST /quotes/{id}/void, POST /quotes/{id}/extend y POST /quotes/{id}/archive. Los tres piden un void_reason, extend_reason o archive_reason visible. Ninguno toma el actor del body: voided_by queda con el principal autenticado.
Trampa
Una cotización nula no se puede volver a anular
Un segundo void es 409 y el primer actor y la primera razón quedan como
están. Para corregir, emite otra cotización.
{
"error": {
"code": "CONFLICT",
"message": "Quote Q-8 is already voided; a void cannot be restated.",
"requestId": "8a40a45a-975d-4fa4-a685-a40deabe4c6e"
}
}Reservar
La reserva es el único documento que bloquea la unidad. Varios clientes pueden tener cotizaciones vigentes sobre el mismo auto; solo una reserva puede estar activa.
curl -X POST https://api.vitrinadev.com/api/v1/reservations \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"vehicle_id": "81e56530-5365-4e4c-a423-2bb043798527",
"holder_contact_id": "01a0cbdd-305f-7312-9345-5818a81e1fd8",
"agreed_price_clp": 10490000,
"hold_expires_on": "2026-09-30"
}'{
"data": {
"id": "55923d26-8109-4d13-85aa-8ae2b9b10454",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"display_id": "R-5",
"display_seq": 5,
"vehicle_id": "81e56530-5365-4e4c-a423-2bb043798527",
"holder_contact_id": "01a0cbdd-305f-7312-9345-5818a81e1fd8",
"salesperson_id": null,
"agreed_price_clp": 10490000,
"abono_expected_clp": 300000,
"taken_at": "2026-09-23T01:25:07.880Z",
"hold_expires_on": "2026-09-30",
"keep_advertised": true,
"status": "activa",
"abono_disposition": null,
"abono_disposition_reason": null,
"abono_disposition_at": null,
"abono_disposition_by": null,
"voided_at": null,
"void_reason": null,
"voided_by": null,
"created_at": "2026-09-23T01:25:07.880Z",
"updated_at": "2026-09-23T01:25:07.880Z"
}
}hold_expires_on es obligatorio y no tiene default. Una reserva bloquea inventario y puede tomar un abono no reembolsable, así que cada una declara su propio plazo. Si omites agreed_price_clp, se copia el precio de publicación vigente del auto. keep_advertised decide si los avisos siguen activos mientras dura el cupo.
Cerrar una reserva con pagos encima obliga a decir qué pasó con el dinero. La ruta es POST /reservations/{id}/abono-disposition, el destino es aplicado, devuelto o perdido, y la misma llamada pide el void_reason porque cierra el cupo:
{
"data": {
"id": "96b5d519-20af-4afb-9d85-d1c5d1134fa6",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"display_id": "R-6",
"display_seq": 6,
"vehicle_id": "c9309769-a5d0-4ec3-a72b-c38463df3bf7",
"holder_contact_id": "01a0cbdd-304a-70d8-951f-5e4b481301c9",
"salesperson_id": null,
"agreed_price_clp": 11290000,
"abono_expected_clp": 300000,
"taken_at": "2026-09-23T01:28:50.056Z",
"hold_expires_on": "2026-09-30",
"keep_advertised": false,
"status": "anulada",
"abono_disposition": "perdido",
"abono_disposition_reason": "Abono no reembolsable según el contrato firmado",
"abono_disposition_at": "2026-09-23T01:29:11.554Z",
"abono_disposition_by": "0eb8e217-8a6f-4cb8-8216-b077194b3df7",
"voided_at": "2026-09-23T01:29:11.554Z",
"void_reason": "El comprador no volvió",
"voided_by": "0eb8e217-8a6f-4cb8-8216-b077194b3df7",
"created_at": "2026-09-23T01:28:50.056Z",
"updated_at": "2026-09-23T01:29:11.554Z"
}
}POST /reservations/{id}/convert produce una nota de venta nueva, hereda el auto y el comprador, y arrastra los pagos al documento resultante. El precio viene de agreed_price_clp y no es un parámetro de esta ruta.
{
"data": {
"reservation": {
"id": "55923d26-8109-4d13-85aa-8ae2b9b10454",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"display_id": "R-5",
"display_seq": 5,
"vehicle_id": "81e56530-5365-4e4c-a423-2bb043798527",
"holder_contact_id": "01a0cbdd-305f-7312-9345-5818a81e1fd8",
"salesperson_id": null,
"agreed_price_clp": 10490000,
"abono_expected_clp": 300000,
"taken_at": "2026-09-23T01:25:07.880Z",
"hold_expires_on": "2026-09-30",
"keep_advertised": true,
"status": "completada",
"abono_disposition": "aplicado",
"abono_disposition_reason": "Abono aplicado a la nota de venta V-2 (BR-237): la reserva R-5 se completó con la venta y el dinero recibido se acreditó en el documento resultante, copiado pago por pago (BR-291).",
"abono_disposition_at": "2026-09-23T01:25:24.288Z",
"abono_disposition_by": "0eb8e217-8a6f-4cb8-8216-b077194b3df7",
"voided_at": null,
"void_reason": null,
"voided_by": null,
"created_at": "2026-09-23T01:25:07.880Z",
"updated_at": "2026-09-23T01:25:24.242Z"
},
"sale_note": {
"id": "32e4f73b-1b37-407a-9442-0c110cd68d08",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"display_id": "V-2",
"display_seq": 2,
"vehicle_id": "81e56530-5365-4e4c-a423-2bb043798527",
"buyer_contact_id": "01a0cbdd-305f-7312-9345-5818a81e1fd8",
"lead_id": null,
"converted_from_reservation_id": "55923d26-8109-4d13-85aa-8ae2b9b10454",
"seller_of_record": "automotora",
"salesperson_id": null,
"net_clp": 10490000,
"tax_clp": null,
"tax_treatment": "afecto",
"status": "issued",
"issued_at": "2026-09-23T01:25:24.242Z",
"approved_by": null,
"approved_at": null,
"voided_at": null,
"void_reason": null,
"voided_by": null,
"created_at": "2026-09-23T01:25:24.242Z",
"updated_at": "2026-09-23T01:25:24.242Z"
},
"carried_payments": [
{
"id": "01a0cbde-13ff-7fba-bc54-a0b8b687bcf1",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"reservation_id": null,
"sale_note_id": "32e4f73b-1b37-407a-9442-0c110cd68d08",
"carried_from_reservation_id": "55923d26-8109-4d13-85aa-8ae2b9b10454",
"instrument": "transferencia",
"amount_clp": 300000,
"paid_on": "2026-09-23",
"bank": "Banco de Chile",
"account_number": null,
"document_number": "8842190",
"note": null,
"card_fee_bps": null,
"card_surcharge_clp": null,
"card_surcharge_source": null,
"created_at": "2026-09-23T01:25:24.095Z",
"updated_at": "2026-09-23T01:25:24.174Z"
}
]
}
}Vender
curl -X POST https://api.vitrinadev.com/api/v1/sale-notes \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"vehicle_id": "de7d959a-292f-4491-92ce-2028fa9114f0",
"buyer_contact_id": "01a0cbdd-304a-70d8-951f-5e4b481301c9",
"seller_of_record": "automotora",
"net_clp": 8990000,
"tax_clp": 1708100,
"tax_treatment": "afecto"
}'Emitir asigna el folio y deja la nota en issued. La venta se cierra con POST /sale-notes/{id}/approve:
{
"data": {
"id": "486de281-2d4a-4e0c-a98c-95617e1b4093",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"display_id": "V-4",
"display_seq": 4,
"vehicle_id": "de7d959a-292f-4491-92ce-2028fa9114f0",
"buyer_contact_id": "01a0cbdd-304a-70d8-951f-5e4b481301c9",
"lead_id": null,
"converted_from_reservation_id": null,
"seller_of_record": "automotora",
"salesperson_id": null,
"net_clp": 8990000,
"tax_clp": 1708100,
"tax_treatment": "afecto",
"status": "approved",
"issued_at": "2026-09-23T01:34:49.722Z",
"approved_by": "0eb8e217-8a6f-4cb8-8216-b077194b3df7",
"approved_at": "2026-09-23T01:34:51.127Z",
"voided_at": null,
"void_reason": null,
"voided_by": null,
"created_at": "2026-09-23T01:34:49.722Z",
"updated_at": "2026-09-23T01:34:51.125Z"
}
}Aprobar marca el auto vendido, un estado terminal, y anula en el mismo acto toda cotización que siguiera vigente sobre esa unidad:
{
"data": {
"id": "982dd531-6b1a-49f1-a947-f8520e7bb648",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"display_id": "Q-7",
"display_seq": 7,
"vehicle_id": "de7d959a-292f-4491-92ce-2028fa9114f0",
"buyer_contact_id": "01a0cbdd-304a-70d8-951f-5e4b481301c9",
"salesperson_id": null,
"list_price_clp": 8990000,
"offered_price_clp": 8990000,
"tax_treatment": "afecto",
"discount_pct": 0,
"unit_make": "Peugeot",
"unit_model": "208",
"unit_version": "Active 1.2",
"unit_year": 2021,
"unit_plate": "KXPW34",
"unit_vin": "VF3CCHMZ6MT012345",
"unit_odometer_value": 38200,
"unit_odometer_unit": "KM",
"unit_color": "Gris",
"discount_hidden": false,
"issued_at": "2026-09-23T01:24:47.318Z",
"expires_on": "2026-09-30",
"state": "nula",
"voided_at": "2026-09-23T01:34:51.156Z",
"void_reason": "Vehículo vendido (BR-215): la validez de una cotización vigente termina en el momento en que se vende la unidad, sin esperar a su fecha de expiración impresa — la validez es la que ocurra primero entre ambas.",
"voided_by": "00000000-0000-0000-0000-000000000000",
"extended_at": null,
"extend_reason": null,
"extended_by": null,
"archived_at": null,
"archive_reason": null,
"archived_by": null,
"created_at": "2026-09-23T01:24:47.318Z",
"updated_at": "2026-09-23T01:34:51.125Z"
}
}Trampa
Un auto admite una sola nota de venta vigente
Emitir una segunda contra la misma unidad es 409, sin folio consumido.
{
"error": {
"code": "CONFLICT",
"message": "Ya existe una nota de venta vigente (V-5) para este vehículo. Anúlala antes de emitir otra: un vehículo se vende una sola vez, y dos notas de venta vigentes sobre la misma unidad significan dos ventas del mismo auto. No se escribió nada y no se consumió ningún folio.",
"requestId": "e41f51cc-48c5-40b8-8d1d-5c185b4ec6c5"
}
}Si net_clp cae bajo el nivel que la organización exige autorizar, approve responde 409. Hace falta una aprobación de precio resuelta a favor sobre ese mismo documento. La sección Autorizar un descuento muestra cómo se pide.
GET /sale-notes/{id} agrega totals y funding, el veredicto sobre si el dinero comprometido cubre el precio. Con las cifras completas y sin pagos registrados, standing es short; si falta tax_clp, el veredicto es not_computable y gaps dice qué falta. Anular pide sale_notes:void, una autoridad distinta de sale_notes:write.
Comprar
curl -X POST https://api.vitrinadev.com/api/v1/purchase-notes \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"seller_contact_id": "01a0cbdd-307a-75af-8566-1f9b09686cb8",
"net_clp": 6200000,
"tax_treatment": "no_gravado",
"lines": [
{ "description": "Compra de vehículo usado Mazda CX-5 2020", "net_clp": 6200000, "tax_treatment": "no_gravado" }
]
}'{
"data": {
"id": "6e84a7d8-ccc0-4ed5-b03e-ec81613308e5",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"display_id": "P-3",
"display_seq": 3,
"seller_contact_id": "01a0cbdd-307a-75af-8566-1f9b09686cb8",
"net_clp": 6200000,
"tax_clp": null,
"tax_treatment": "no_gravado",
"status": "issued",
"issued_at": "2026-09-23T01:34:18.007Z",
"corrected_at": null,
"corrected_by": null,
"voided_at": null,
"void_reason": null,
"voided_by": null,
"created_at": "2026-09-23T01:34:18.007Z",
"updated_at": "2026-09-23T01:34:18.007Z",
"lines": [
{
"id": "e4be40c0-0f87-40be-8698-15feb843bbef",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"purchase_note_id": "6e84a7d8-ccc0-4ed5-b03e-ec81613308e5",
"sale_note_id": null,
"position": 1,
"description": "Compra de vehículo usado Mazda CX-5 2020",
"net_clp": 6200000,
"tax_clp": null,
"tax_treatment": "no_gravado",
"add_on_kind": null,
"add_on_framing": null,
"cost_clp": null,
"beneficiary": null,
"documents_in_customer_name": null,
"fee_kind": null,
"fee_effective_from": null,
"created_at": "2026-09-23T01:34:18.007Z",
"updated_at": "2026-09-23T01:34:18.007Z"
}
],
"acquisition": null,
"retentions": []
}
}La nota de compra le da costo a un auto que entra al lote. Cada línea lleva su propio net_clp y su propio tax_treatment. El vínculo con la unidad se registra aparte, en /vehicle-acquisitions.
PATCH /purchase-notes/{id} corrige un documento vigente sin tocar su folio ni su estado, y deja corrected_at y corrected_by. lines reemplaza el desglose completo cuando lo envías.
Pagar
curl -X POST https://api.vitrinadev.com/api/v1/document-payments \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"reservation_id": "55923d26-8109-4d13-85aa-8ae2b9b10454",
"instrument": "transferencia",
"amount_clp": 300000,
"paid_on": "2026-09-23",
"bank": "Banco de Chile",
"document_number": "8842190"
}'{
"data": {
"id": "01a0cbde-13ff-7fba-bc54-a0b8b687bcf1",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"reservation_id": "55923d26-8109-4d13-85aa-8ae2b9b10454",
"sale_note_id": null,
"carried_from_reservation_id": null,
"instrument": "transferencia",
"amount_clp": 300000,
"paid_on": "2026-09-23",
"bank": "Banco de Chile",
"account_number": null,
"document_number": "8842190",
"note": null,
"card_fee_bps": null,
"card_surcharge_clp": null,
"card_surcharge_source": null,
"created_at": "2026-09-23T01:25:24.095Z",
"updated_at": "2026-09-23T01:25:24.095Z"
}
}Trampa
Una transferencia sin bank es 400
El instrumento decide qué campos se vuelven obligatorios: sin el banco, nadie puede cruzar la línea del estado de cuenta con el documento que pagó.
{
"error": {
"code": "VALIDATION_ERROR",
"message": "A transferencia payment requires bank (BR-261/BR-447): these are the fields that let the cashier match a bank statement line to a document, and without them a returned instrument cannot be traced back to the sale it paid for.",
"requestId": "eb129b92-f686-4f4c-b62c-6cf19e6e57fa"
}
}Esta ruta se mantiene por compatibilidad. Para algo nuevo, la ruta es POST /payments: reparte un pago entre varias obligaciones, deja el sobrante como crédito del contacto y admite reverso.
Consignar
Bajo una consignación, la automotora vende el auto de otra persona. Solo vehicle_id y modalidad son obligatorios.
curl -X POST https://api.vitrinadev.com/api/v1/consignments \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"vehicle_id": "bd4490ca-587e-4396-b0dc-074b4997b8a1",
"modalidad": "en_local"
}'{
"data": {
"id": "1357177d-cad8-49fa-8042-51ce1b1c4452",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"vehicle_id": "bd4490ca-587e-4396-b0dc-074b4997b8a1",
"dueno_contact_id": null,
"modalidad": "en_local",
"contract_structure": "mandato_con_representacion",
"comision_type": null,
"comision_value": null,
"minimo_clp": null,
"vencimiento": null,
"estado": "activo",
"vencimiento_reminded_at": null,
"liquidacion_due_notified_at": null,
"created_at": "2026-09-23T01:25:50.254Z",
"updated_at": "2026-09-23T01:25:50.254Z",
"sale_iva_regime": null,
"not_on_lot": false
}
}Crear el contrato cambia la tenencia del auto a consignacion de inmediato. El dueño, la comisión y el mínimo se completan después con PATCH /consignments/{id}. Mientras falte la comisión, el contrato tampoco se puede vender:
{
"error": {
"code": "CONFLICT",
"message": "Este contrato no tiene comisión registrada, así que no hay reparto que liquidar. Registra comision_type y comision_value en el contrato antes de venderlo.",
"requestId": "7197732b-6386-47e9-9f84-fd1d12b3ac67"
}
}POST /consignments/{id}/sell transiciona el contrato a vendido y produce la liquidación en el mismo acto, con la comisión ya descontada:
{
"data": {
"contract": {
"id": "1357177d-cad8-49fa-8042-51ce1b1c4452",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"vehicle_id": "bd4490ca-587e-4396-b0dc-074b4997b8a1",
"dueno_contact_id": "01a0cbdd-307a-75af-8566-1f9b09686cb8",
"modalidad": "en_local",
"contract_structure": "mandato_con_representacion",
"comision_type": "percentage",
"comision_value": 10,
"minimo_clp": 12000000,
"vencimiento": null,
"estado": "vendido",
"vencimiento_reminded_at": null,
"liquidacion_due_notified_at": null,
"created_at": "2026-09-23T01:25:50.254Z",
"updated_at": "2026-09-23T01:26:12.646Z",
"sale_iva_regime": null,
"not_on_lot": false
},
"liquidacion": {
"id": "765ad258-039c-43e6-b399-36b2e49ac281",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"consignment_contract_id": "1357177d-cad8-49fa-8042-51ce1b1c4452",
"vehicle_id": "bd4490ca-587e-4396-b0dc-074b4997b8a1",
"settlement_mode": "stated_commission",
"amount_venta_clp": 13890000,
"comision_type": "percentage",
"comision_value": 10,
"comision_amount_clp": 1389000,
"monto_owner_clp": 12501000,
"owner_floor_clp": null,
"deducciones_clp": 0,
"retiro_motivo": null,
"retiro_by": null,
"paid_at": "2026-09-23T01:26:12.648Z",
"created_at": "2026-09-23T01:26:12.646Z",
"updated_at": "2026-09-23T01:26:12.646Z"
}
}
}POST /consignments/{id}/return devuelve el auto a su dueño y la tenencia vuelve a propio. Es el único estado terminal que la restaura: un contrato vendido o vencido mantiene consignacion.
{
"data": {
"id": "42331a67-d7a0-45c2-8194-896a538edc42",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"vehicle_id": "a4fb12d7-ef13-4871-b77e-0b80cda38303",
"dueno_contact_id": "01a0cbdd-307a-75af-8566-1f9b09686cb8",
"modalidad": "en_local",
"contract_structure": "mandato_con_representacion",
"comision_type": "percentage",
"comision_value": 8,
"minimo_clp": 7000000,
"vencimiento": null,
"estado": "devuelto",
"vencimiento_reminded_at": null,
"liquidacion_due_notified_at": null,
"created_at": "2026-09-23T01:28:40.901Z",
"updated_at": "2026-09-23T01:28:40.972Z",
"sale_iva_regime": null,
"not_on_lot": false
}
}Financiar
curl -X POST https://api.vitrinadev.com/api/v1/credit-applications \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"vehicle_id": "de7d959a-292f-4491-92ce-2028fa9114f0",
"buyer_contact_id": "01a0cbdd-304a-70d8-951f-5e4b481301c9",
"institution_id": "31512710-2c11-4ae2-b396-a394d7b82c16",
"requested_amount_clp": 6500000,
"term_months": 48
}'{
"data": {
"id": "09071d3d-e586-4415-ab98-03ef0bc681b3",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"display_id": "F-3",
"display_seq": 3,
"vehicle_id": "de7d959a-292f-4491-92ce-2028fa9114f0",
"buyer_contact_id": "01a0cbdd-304a-70d8-951f-5e4b481301c9",
"institution_id": "31512710-2c11-4ae2-b396-a394d7b82c16",
"requested_amount_clp": 6500000,
"vehicle_price_clp": null,
"declared_income_clp": null,
"fee_clp": null,
"term_months": 48,
"financed_total_clp": null,
"submitted_at": null,
"submitted_by": null,
"decided_at": null,
"decided_by": null,
"outcome": null,
"decision_reason": null,
"approved_amount_clp": null,
"withdrawn_at": null,
"withdrawn_by": null,
"withdrawn_reason": null,
"last_contact_at": null,
"last_contact_by": null,
"chased_at": null,
"state": "recorded",
"created_at": "2026-09-23T01:26:19.780Z",
"updated_at": "2026-09-23T01:26:19.780Z",
"taken": false,
"taken_sale_note_id": null,
"taken_sale_note_folio": null,
"institution_name": "Banco Falabella",
"taken_credit_state": null,
"taken_disbursed_at": null,
"vehicle_label": "Peugeot 208 2021",
"vehicle_plate": "KXPW34",
"buyer_name": "Daniela Ortiz",
"buyer_rut": null
}
}El expediente avanza por hechos, cada uno con su propia ruta y ninguno una edición del estado. POST .../submission registra que la carpeta salió al banco, con el submitted_at que le pases. POST .../decision guarda la respuesta de la financiera, y outcome acepta approved o rejected. POST .../withdrawal retira el expediente y es terminal. POST .../contact reinicia el reloj de seguimiento y es el único repetible.
{
"data": {
"id": "09071d3d-e586-4415-ab98-03ef0bc681b3",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"display_id": "F-3",
"display_seq": 3,
"vehicle_id": "de7d959a-292f-4491-92ce-2028fa9114f0",
"buyer_contact_id": "01a0cbdd-304a-70d8-951f-5e4b481301c9",
"institution_id": "31512710-2c11-4ae2-b396-a394d7b82c16",
"requested_amount_clp": 6500000,
"vehicle_price_clp": null,
"declared_income_clp": null,
"fee_clp": null,
"term_months": 48,
"financed_total_clp": null,
"submitted_at": "2026-09-23T14:05:00.000Z",
"submitted_by": "0eb8e217-8a6f-4cb8-8216-b077194b3df7",
"decided_at": "2026-09-23T01:26:38.761Z",
"decided_by": "0eb8e217-8a6f-4cb8-8216-b077194b3df7",
"outcome": "approved",
"decision_reason": null,
"approved_amount_clp": 6000000,
"withdrawn_at": null,
"withdrawn_by": null,
"withdrawn_reason": null,
"last_contact_at": null,
"last_contact_by": null,
"chased_at": null,
"state": "approved",
"created_at": "2026-09-23T01:26:19.780Z",
"updated_at": "2026-09-23T01:26:38.760Z",
"taken": false,
"taken_sale_note_id": null,
"taken_sale_note_folio": null,
"institution_name": "Banco Falabella",
"taken_credit_state": null,
"taken_disbursed_at": null,
"vehicle_label": "Peugeot 208 2021",
"vehicle_plate": "KXPW34",
"buyer_name": "Daniela Ortiz",
"buyer_rut": null
}
}GET /credit-applications/ageing es el tablero de cobranza con el reloj de cada financiera ya resuelto. No toma un parámetro de umbral: el plazo vive en el catálogo de instituciones y cada fila trae el suyo en sla_days.
Autorizar un descuento
curl -X POST https://api.vitrinadev.com/api/v1/price-approvals \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"sale_note_id": "81d9aba3-3901-4ba6-963b-a176f20ae99b",
"requested_price_clp": 7900000
}'{
"data": {
"id": "d0aace9b-bb03-40b1-9c09-1c2c7a08a2ac",
"tenant_id": "00000000-0000-4000-8000-000000000001",
"quote_id": null,
"reservation_id": null,
"sale_note_id": "81d9aba3-3901-4ba6-963b-a176f20ae99b",
"requested_price_clp": 7900000,
"list_price_snapshot_clp": 8990000,
"floor_price_snapshot_clp": 8200000,
"requester_user_id": "0eb8e217-8a6f-4cb8-8216-b077194b3df7",
"status": "pending",
"decider_user_id": null,
"decided_at": null,
"decision_note": null,
"created_at": "2026-09-23T01:26:52.892Z",
"updated_at": "2026-09-23T01:26:52.892Z"
}
}La solicitud nombra exactamente uno de quote_id, reservation_id o sale_note_id, y guarda el precio de lista y el piso tal como estaban. Pedir una autorización que nadie necesita es 400:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "10490000 needs no authorisation on V-2: it is at or above the reference this organisation approves against (tolerance 0 CLP). Sell it. An approval queue full of requests that needed no decision is a queue nobody reads.",
"requestId": "8ec43ba3-0153-4697-9254-bc29ddd601b5"
}
}Trampa
Quien pide y quien decide tienen que ser personas distintas
POST /price-approvals/{id}/decision responde 403 cuando el decisor es el
mismo principal que pidió la autorización.
{
"error": {
"code": "FORBIDDEN",
"message": "You cannot approve or reject your own price request (BR-433/BR-434): the person who asks and the person who grants must differ. A discount authorised by its own beneficiary is not an authorisation. Ask somebody else holding price_approval:approve to decide it.",
"requestId": "7b770694-1e04-481b-a51a-7fe238c967ce"
}
}Una decisión es terminal: no hay PUT, PATCH ni segunda decisión. Un rechazo tiene que traer decision_note; una aprobación puede ir sin comentario.
Eventos
Cada cambio de estado emite su propio evento: vehicle.published, vehicle.unpublished, vehicle.publish_failed, quote.issued, quote.voided, quote.extended, quote.archived, reservation.created, reservation.voided, reservation.abono_disposed, reservation.converted, sale_note.issued, sale_note.approved, sale_note.voided, purchase_note.issued, purchase_note.corrected, purchase_note.voided, payment.recorded, consignment.created, consignment.returned, consignment.sold, credit_application.recorded, credit_application.submitted, credit_application.decided, credit_application.withdrawn, price_approval.requested y price_approval.decided.
El catálogo completo, con el data_schema y una muestra de cada uno, está en Eventos suscribibles. Cómo suscribirte y verificar la firma está en Webhooks.
Referencia
Cada recurso tiene su página de referencia, generada del contrato. Las publicaciones viven dentro de Vehículos.
Cotizaciones · Reservas · Notas de venta · Notas de compra · Pagos de documentos · Consignaciones · Solicitudes de crédito · Aprobaciones de precio.