Vehicle attachments
Documents and files hanging off one unit.
Download the full API pública projection: openapi.json.
Keep and read the vehicle file explains this resource in prose, with runnable examples.
| Method | Path | What it does |
|---|---|---|
GET | /vehicle-attachments | List the car's papers |
POST | /vehicle-attachments | File one of the car's papers (multipart/form-data) |
DELETE | /vehicle-attachments/{id} | Delete one of the car's papers |
PATCH | /vehicle-attachments/{id} | Rename a paper or set its «Vence» day |
GET | /vehicle-attachments/{id}/content | Download the stored bytes of one attachment |
GET /vehicle-attachments
List the car's papers
vehicle_id is required; there is no tenant-wide list of documents. Newest first. Each paper carries its kind, its label (an otro paper) and its expires_on («Vence»), when recorded.
expiring_within_days (ADR 0114 §7) narrows to the papers «Vencido» or due within that many days, soonest first, each with expiry_state; without vehicle_id it covers every car in stock and never returns a cédula or a paper naming a person. The same papers raise the vehicle_papers_expiring dealer alert and fill the Stock counts papers_expired / papers_expiring on GET /vehicles/stats.
| Parameter | In | Type | Required | Constraints |
|---|---|---|---|---|
vehicle_id | query | uuid | no | |
kind | query | padron \ | cedula \ | contrato \ |
expiring_within_days | query | integer | no |
curl https://api.vitrinadev.com/api/v1/vehicle-attachments \
-H "Authorization: Bearer $VITRINA_KEY"Example response (200)
{
"data": [
{
"id": "f1f1f1f1-0000-4000-8000-000000000001",
"tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
"vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
"kind": "padron",
"storage_bucket": "vitrina-registry",
"storage_path": "a1a1a1a1-0000-4000-8000-000000000001/e1e1e1e1-0000-4000-8000-000000000001/padron.png",
"filename": "padron.png",
"mime_type": "image/png",
"byte_size": 812004,
"subject_contact_id": null,
"uploaded_by": "11111111-0000-4000-8000-000000000001",
"uploaded_at": "2026-09-15T18:47:01.784Z",
"created_at": "2026-09-15T18:47:01.784Z",
"signed_document_type": null,
"signed_document_id": null,
"label": null,
"expires_on": null
},
{
"id": "f1f1f1f1-0000-4000-8000-000000000002",
"tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
"vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
"kind": "cedula",
"storage_bucket": "vitrina-registry",
"storage_path": "a1a1a1a1-0000-4000-8000-000000000001/e1e1e1e1-0000-4000-8000-000000000001/cedula-consignante.png",
"filename": "cedula-consignante.png",
"mime_type": "image/png",
"byte_size": 812004,
"subject_contact_id": "22222222-0000-4000-8000-000000000001",
"uploaded_by": "11111111-0000-4000-8000-000000000001",
"uploaded_at": "2026-09-15T18:47:01.784Z",
"created_at": "2026-09-15T18:47:01.784Z",
"signed_document_type": null,
"signed_document_id": null,
"label": null,
"expires_on": null
},
{
"id": "f1f1f1f1-0000-4000-8000-000000000003",
"tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
"vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
"kind": "contrato",
"storage_bucket": "vitrina-registry",
"storage_path": "a1a1a1a1-0000-4000-8000-000000000001/e1e1e1e1-0000-4000-8000-000000000001/compraventa-firmada.pdf",
"filename": "compraventa-firmada.pdf",
"mime_type": "application/pdf",
"byte_size": 812004,
"subject_contact_id": null,
"uploaded_by": "11111111-0000-4000-8000-000000000001",
"uploaded_at": "2026-09-15T18:47:01.784Z",
"created_at": "2026-09-15T18:47:01.784Z",
"signed_document_type": "compraventa",
"signed_document_id": "d4d4d4d4-0000-4000-8000-000000000001",
"label": null,
"expires_on": null
},
{
"id": "f1f1f1f1-0000-4000-8000-000000000004",
"tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
"vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
"kind": "soap",
"storage_bucket": "vitrina-registry",
"storage_path": "a1a1a1a1-0000-4000-8000-000000000001/e1e1e1e1-0000-4000-8000-000000000001/soap-2027.jpg",
"filename": "soap-2027.jpg",
"mime_type": "image/jpeg",
"byte_size": 812004,
"subject_contact_id": null,
"uploaded_by": "11111111-0000-4000-8000-000000000001",
"uploaded_at": "2026-09-15T18:47:01.784Z",
"created_at": "2026-09-15T18:47:01.784Z",
"signed_document_type": null,
"signed_document_id": null,
"label": null,
"expires_on": "2027-03-31"
},
{
"id": "f1f1f1f1-0000-4000-8000-000000000005",
"tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
"vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
"kind": "otro",
"storage_bucket": "vitrina-registry",
"storage_path": "a1a1a1a1-0000-4000-8000-000000000001/e1e1e1e1-0000-4000-8000-000000000001/informe.pdf",
"filename": "informe.pdf",
"mime_type": "application/pdf",
"byte_size": 812004,
"subject_contact_id": null,
"uploaded_by": "11111111-0000-4000-8000-000000000001",
"uploaded_at": "2026-09-15T18:47:01.784Z",
"created_at": "2026-09-15T18:47:01.784Z",
"signed_document_type": null,
"signed_document_id": null,
"label": "Informe mecánico",
"expires_on": null
}
]
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
POST /vehicle-attachments
File one of the car's papers (multipart/form-data)
Capped at the configured max size; the file part is required. PDF or an image (JPEG, PNG, WebP, HEIC, TIFF — a phone photo of a paper is fine).
THE CAR’S PAPERS (ADR 0114 §7): kind names the paper — permiso_circulacion, revision_tecnica, soap, padron, certificado_anotaciones (CAV), factura, contrato, cedula. Any other paper is otro with a label that names it («Factura de compra», «Informe mecánico»); a label with no kind files it as otro. expires_on records the day the paper stops being valid («Vence»). replaces_id supersedes a filed paper of the same kind: the old one is erased once the new one is filed.
A SIGNED COPY of one of the car’s documents (ADR 0114 §7) is filed with signed_document_type (purchase_note, sale_note, compraventa, consignment_contract, liquidacion) and signed_document_id (the nota de venta’s id for a compraventa, the consignación’s id for a liquidación). The document must be this car’s, and a compraventa must have been printed; kind may then be omitted — it is contrato for the compraventa and the mandato, otro for the rest — and a contradicting kind is refused (400). GET /vehicles/\{id\}/documents shows the copy on its document.
Or a JSON body (application/json) — what an MCP connector sends through call_operation, which cannot build multipart: \{ filename, content, content_encoding?, content_type? \} plus the operation's own form fields. content is UTF-8 text by default, or base64 when content_encoding is "base64" (images, PDF, audio, video). The same byte cap applies to the decoded bytes (413 above it); invalid base64 is a 400; the content type defaults from the filename extension.
Body
| Field | Type | Required | Constraints |
|---|---|---|---|
filename | string | yes | mín. 1, máx. 255 |
content | string | yes | mín. 1, máx. 35000000 |
content_encoding | utf8 \ | base64 | — |
content_type | string | — | máx. 200 |
vehicle_id | uuid | yes | |
kind | padron \ | cedula \ | contrato \ |
subject_contact_id | uuid | — | |
signed_document_type | purchase_note \ | sale_note \ | compraventa \ |
signed_document_id | uuid | — | |
label | string | — | máx. 120 |
expires_on | any | — | |
replaces_id | uuid | — |
curl -X POST https://api.vitrinadev.com/api/v1/vehicle-attachments \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
"kind": "soap",
"expires_on": "2027-03-31",
"file": "(binary file part)"
}'Example response (201)
{
"data": {
"id": "f1f1f1f1-0000-4000-8000-000000000001",
"tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
"vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
"kind": "padron",
"storage_bucket": "vitrina-registry",
"storage_path": "a1a1a1a1-0000-4000-8000-000000000001/e1e1e1e1-0000-4000-8000-000000000001/padron.png",
"filename": "padron.png",
"mime_type": "image/png",
"byte_size": 812004,
"subject_contact_id": null,
"uploaded_by": "11111111-0000-4000-8000-000000000001",
"uploaded_at": "2026-09-15T18:47:01.784Z",
"created_at": "2026-09-15T18:47:01.784Z",
"signed_document_type": null,
"signed_document_id": null,
"label": null,
"expires_on": null
}
}Answers: 201 · 400 · 401 · 403 · 404 · 409 · 429
DELETE /vehicle-attachments/{id}
Delete one of the car's papers
Erases the storage object first, then the row. A paper still cited by a transferencia or a document discrepancy is refused (409) before anything is touched. Recorded in the car’s Historial.
| Parameter | In | Type | Required | Constraints |
|---|---|---|---|---|
id | path | uuid | yes |
curl -X DELETE https://api.vitrinadev.com/api/v1/vehicle-attachments/<id> \
-H "Authorization: Bearer $VITRINA_KEY"Answers: 204 · 400 · 401 · 403 · 404 · 409 · 429
PATCH /vehicle-attachments/{id}
Rename a paper or set its «Vence» day
ADR 0114 §7 — corrects a filed paper without touching its file: label renames a paper filed as otro (a named kind — SOAP, padrón… — is named by its kind and refuses a label, 400); expires_on sets the day the paper stops being valid, null clears it. A new file is a replace (POST with replaces_id), not this. Recorded in the car’s Historial.
| Parameter | In | Type | Required | Constraints |
|---|---|---|---|---|
id | path | uuid | yes |
Body
| Field | Type | Required | Constraints |
|---|---|---|---|
label | string | null | — | máx. 120 |
expires_on | string | null | — |
curl -X PATCH https://api.vitrinadev.com/api/v1/vehicle-attachments/<id> \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"expires_on": "2027-03-31"
}'Example response (200)
{
"data": {
"id": "f1f1f1f1-0000-4000-8000-000000000001",
"tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
"vehicle_id": "e1e1e1e1-0000-4000-8000-000000000001",
"kind": "soap",
"storage_bucket": "vitrina-registry",
"storage_path": "a1a1a1a1-0000-4000-8000-000000000001/e1e1e1e1-0000-4000-8000-000000000001/padron.png",
"filename": "padron.png",
"mime_type": "image/png",
"byte_size": 812004,
"subject_contact_id": null,
"uploaded_by": "11111111-0000-4000-8000-000000000001",
"uploaded_at": "2026-09-15T18:47:01.784Z",
"created_at": "2026-09-15T18:47:01.784Z",
"signed_document_type": null,
"signed_document_id": null,
"label": null,
"expires_on": "2027-03-31"
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
GET /vehicle-attachments/{id}/content
Download the stored bytes of one attachment
Streams the raw file (not a JSON envelope) with Cache-Control: private, no-store and a locked-down CSP. Audited on every read.
| Parameter | In | Type | Required | Constraints |
|---|---|---|---|---|
id | path | uuid | yes |
curl https://api.vitrinadev.com/api/v1/vehicle-attachments/<id>/content \
-H "Authorization: Bearer $VITRINA_KEY"Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429