Keep your stock current from your ERP
Your ERP stays the source of truth. Vitrina keeps a copy of every car and uses it in conversations, on your website and on the portals.
Car dealershipsOnly in car-dealership workspaces.
If your dealership already runs its own ERP, keep it. Your ERP tells Vitrina when a car comes in, changes, gets reserved or gets sold. With that copy, the agent answers from your real stock and your website shows the lot as it is. Publishing to the portals is one click in the app.
It takes five operations:
| When in your ERP… | Call |
|---|---|
| A car comes in | POST /vehicles |
| The price, mileage, photos or description change | PUT /vehicles/{id} |
| It is reserved | PUT /vehicles/{id} with status: "reservado" |
| It is sold | PUT /vehicles/{id} with status: "vendido" |
| It leaves without a sale | PUT /vehicles/{id} with active: false |
The responses on this page come from a run against a sandbox. Your identifiers will differ; the shape is the same.
Trap
Store Vitrina's id in your ERP
POST /vehicles does not take your internal code. It returns an id, and
every later call uses that id. Save it next to the car's record as soon as
you create it.
Before you start
- A key with
tenant:read,marketplace:readandmarketplace:write. You issue it in Authentication. - Build against your sandbox first, with an
sk_test_key. Once the sync works, switch to the live key: the code stays the same.
1. Get your branch id
curl https://api.vitrinadev.com/api/v1/locations \
-H "Authorization: Bearer $VITRINA_KEY"{
"data": [
{ "id": "35cc2d47-8929-4c84-9bfa-9a4835db55cb", "name": "Casa matriz" }
]
}Every car belongs to a branch. With a single branch, that id is the same for the whole lot. Fetch it once and keep it in the sync's configuration.
2. Create each car once
curl -X POST https://api.vitrinadev.com/api/v1/vehicles \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5b0f8c1e-erp-RTKZ45-alta" \
-d '{
"make": "Toyota",
"model": "Yaris",
"version": "XLS 1.5",
"year": 2022,
"price_amount": 11990000,
"price_currency": "CLP",
"odometer_value": 28500,
"odometer_unit": "KM",
"type": "Car",
"listing_type": "Usado",
"fuel_type": "Bencina",
"gear_type": "Manual",
"color": "Gris",
"registration_number": "RTKZ45",
"location_id": "35cc2d47-8929-4c84-9bfa-9a4835db55cb",
"description": "Único dueño, mantenimientos al día.",
"photos": [
{ "url": "https://images.unsplash.com/photo-1623869675781-80aa31012a5a", "order": 0 }
]
}'{
"data": {
"id": "0ea21e09-afb1-4df6-9e55-3e610627cc9e",
"make": "Toyota",
"model": "Yaris",
"registration_number": "RTKZ45",
"plate_normalized": "RTKZ45",
"price_amount": 11990000,
"odometer_value": 28500,
"description": "Único dueño, mantenimientos al día.",
"status": "disponible",
"active": true,
"location_id": "35cc2d47-8929-4c84-9bfa-9a4835db55cb",
"photos": [
{ "url": "https://images.unsplash.com/photo-1623869675781-80aa31012a5a", "order": 0 }
],
"created_at": "2026-10-06T15:03:28.627Z"
}
}201, and the agent can offer the car from that moment on. Photos go in as public URLs, inside the same object.
description is the listing's free text: on Chileautos it shows as «Comentarios del vendedor» (seller comments). Line breaks go in as \n. To change it later, send description in the step 4 PUT.
Trap
No phone numbers or links in the description
Chileautos doesn't allow contact details in a listing. If description contains
a phone number, an email, a link or the word WhatsApp, Vitrina doesn't publish
that car on Chileautos.
If the network drops and your ERP retries with the same Idempotency-Key and the same body, the API returns the same car with the same id and creates no second one.
3. When the car is already there
The same plate against an active car answers 409:
{
"error": {
"code": "CONFLICT",
"message": "Otro vehículo activo ya tiene esta patente (conflicto de patente).",
"details": { "field": "registration_number", "reason": "plate_backstop" },
"requestId": "b465d445-97d6-4a74-950f-37bb906a2266"
}
}That happens on the first load when someone already added cars by hand. Look the car up by plate and store its id:
curl "https://api.vitrinadev.com/api/v1/vehicles?q=RTKZ45" \
-H "Authorization: Bearer $VITRINA_KEY"{
"data": [
{ "id": "0ea21e09-afb1-4df6-9e55-3e610627cc9e", "registration_number": "RTKZ45", "status": "disponible" }
],
"meta": { "total": 1 }
}q is a free-text search, so check that registration_number is the plate you asked for before you store the id.
4. Send only what changed
curl -X PUT https://api.vitrinadev.com/api/v1/vehicles/0ea21e09-afb1-4df6-9e55-3e610627cc9e \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{ "price_amount": 11490000, "odometer_value": 29100 }'{
"data": {
"id": "0ea21e09-afb1-4df6-9e55-3e610627cc9e",
"price_amount": 11490000,
"price_clp": 11490000,
"odometer_value": 29100,
"status": "disponible",
"updated_at": "2026-10-06T15:03:30.483Z"
}
}Fields you leave out stay as they are. If the car is live on a portal, the change reaches the listing too, with no extra call.
5. Reserved
curl -X PUT https://api.vitrinadev.com/api/v1/vehicles/0ea21e09-afb1-4df6-9e55-3e610627cc9e \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "reservado" }'{
"data": {
"id": "0ea21e09-afb1-4df6-9e55-3e610627cc9e",
"status": "reservado",
"reserved_at": "2026-10-06T15:03:31.365Z",
"active": true
}
}A reserved car stays on the lot with its label, and its listings stay up. If the reservation falls through, send status: "disponible" again.
6. Sold
curl -X PUT https://api.vitrinadev.com/api/v1/vehicles/0ea21e09-afb1-4df6-9e55-3e610627cc9e \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "vendido" }'{
"data": {
"id": "0ea21e09-afb1-4df6-9e55-3e610627cc9e",
"status": "vendido",
"reserved_at": "2026-10-06T15:03:31.365Z",
"sold_at": "2026-10-06T15:03:31.771Z",
"active": true
}
}That one call does the rest:
- It closes the car's listings on every connected portal.
- It cancels the car's upcoming test drives.
- The agent stops offering it, and it leaves the public lot:
GET /stock/{id}answers404.
Don't delete a sold car. With vendido, the sale stays in its history and in your metrics.
7. It leaves without a sale
A car that goes back to its owner, or that you pull from sale for a while:
curl -X PUT https://api.vitrinadev.com/api/v1/vehicles/944fd909-5f42-407e-80a4-f9aad09afb92 \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{ "active": false }'{
"data": {
"id": "944fd909-5f42-407e-80a4-f9aad09afb92",
"status": "disponible",
"active": false
}
}It leaves the public lot, and its listings are paused or taken down. active: true brings it back, and paused listings resume.
8. Reconcile once a day
A failed call leaves the two lists out of step. A nightly pass fixes it: walk GET /vehicles in pages of 100 and compare against your ERP.
curl "https://api.vitrinadev.com/api/v1/vehicles?limit=100&offset=0" \
-H "Authorization: Bearer $VITRINA_KEY"{
"data": [
{ "id": "e13dd607-68e9-4777-8a36-c3d99088b1a7", "registration_number": "ZZBB46", "status": "disponible" }
],
"meta": { "total": 64 }
}An active car in Vitrina that is no longer available in your ERP gets step 6 or step 7. A car in your ERP with no Vitrina id gets step 2.
Publish to the portals
Once the stock is in sync, publishing takes no code. Connect your accounts once in the app, under Automotora → Marketplaces. Then, from Stock, select the cars and choose Publicar. Whatever your ERP changes later (price, photos, sold) reaches every listing on its own.
Full walkthrough in Automotora manual → Publish to a portal.
Optional: publish from your ERP
If you'd rather have your ERP decide where each car goes, add publish_to to POST /vehicles or PUT /vehicles/{id}, with the portal name (chileautos, mercadolibre, yapo, linze):
curl -X PUT https://api.vitrinadev.com/api/v1/vehicles/0ea21e09-afb1-4df6-9e55-3e610627cc9e \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{ "publish_to": ["chileautos", "mercadolibre"] }'Retrying is safe: a portal where the car is already live answers already_published and creates no second listing. The details and errors of publish_to are in Load your stock without loading the same car twice.
With the stock current, Publish your stock on your website puts it on your site, and List who's interested in a car tells you who asked about each unit.