{"openapi":"3.1.0","info":{"title":"Repromatronic Workshop API","version":"2026-10-11","description":"API para talleres y revendedores: enviar ficheros ECU, consultar el estado, descargar el fichero modificado y recibir avisos por webhook. / Workshop API: submit ECU files, track status, download the modified file and receive webhooks.","contact":{"name":"Repromatronic","email":"info@repromatronic.es","url":"https://www.repromatronic.es"}},"servers":[{"url":"https://app.repromatronic.es/api/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Account"},{"name":"Catalog"},{"name":"Vehicles"},{"name":"Orders"},{"name":"Webhooks"}],"paths":{"/plans":{"get":{"tags":["Account"],"security":[],"summary":"Planes de la API (público)","responses":{"200":{"description":"OK"}}}},"/me":{"get":{"tags":["Account"],"summary":"Cuenta, saldo, plan y consumo","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"description":"Clave no válida","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Sin plan activo","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/services":{"get":{"tags":["Catalog"],"summary":"Categorías de vehículo, servicios, complementos e incompatibilidades","responses":{"200":{"description":"OK"}}}},"/vehicles/types":{"get":{"tags":["Vehicles"],"summary":"Tipos de vehículo","responses":{"200":{"description":"OK"}}}},"/vehicles/makes":{"get":{"tags":["Vehicles"],"summary":"Marcas de un tipo","parameters":[{"name":"type","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"}}}},"/vehicles/models":{"get":{"tags":["Vehicles"],"summary":"Modelos de una marca","parameters":[{"name":"make","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"}}}},"/vehicles/generations":{"get":{"tags":["Vehicles"],"summary":"Generaciones de un modelo","parameters":[{"name":"model","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"}}}},"/vehicles/engines":{"get":{"tags":["Vehicles"],"summary":"Motores de una generación (potencia, par, etapas, métodos y herramientas de lectura)","parameters":[{"name":"generation","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"}}}},"/vehicles/engines/{id}":{"get":{"tags":["Vehicles"],"summary":"Detalle de un motor","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"},"404":{"description":"No encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/vehicles/search":{"get":{"tags":["Vehicles"],"summary":"Buscar motores por texto","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2}}],"responses":{"200":{"description":"OK"}}}},"/uploads":{"post":{"tags":["Orders"],"summary":"Permiso de subida del fichero original (paso 1)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["filename","size"],"properties":{"filename":{"type":"string"},"size":{"type":"integer","description":"Bytes, máx. 52428800"}}}}}},"responses":{"200":{"description":"upload_url para hacer PUT del binario y file_path para POST /orders","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Upload"}}}},"413":{"description":"Más de 50 MB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders":{"get":{"tags":["Orders"],"summary":"Listar pedidos","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["queued","pending","processing","revision","completed","cancelled","refunded"]}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Solo pedidos actualizados desde esta fecha"},{"name":"plate","in":"query","schema":{"type":"string"}},{"name":"external_ref","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":25,"maximum":100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/Order"}},"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"has_more":{"type":"boolean"}}}}}}}},"post":{"tags":["Orders"],"summary":"Crear un pedido (paso 2)","description":"JSON con `file_path` de /uploads, o multipart/form-data con `file` (máx. 4 MB). Los créditos se descuentan al entregar el fichero. `external_ref` hace la llamada idempotente.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewOrder"}},"multipart/form-data":{"schema":{"allOf":[{"$ref":"#/components/schemas/NewOrder"},{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}]}}}},"responses":{"201":{"description":"Pedido creado","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"$ref":"#/components/schemas/Order"}}}}}},"402":{"description":"Créditos insuficientes o cupo del plan agotado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Campos no válidos (ver error.fields)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/{id}":{"get":{"tags":["Orders"],"summary":"Detalle de un pedido","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"order":{"$ref":"#/components/schemas/Order"},"status_description":{"type":"string"}}}}}},"404":{"description":"No encontrado","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/{id}/file":{"get":{"tags":["Orders"],"summary":"Descargar el fichero modificado (URL firmada 1 h; ?redirect=1 devuelve 302)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"redirect","in":"query","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"{ url, filename, expires_in }"},"409":{"description":"Aún no está listo","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/{id}/original":{"get":{"tags":["Orders"],"summary":"Descargar el fichero original","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"{ url, filename, expires_in }"}}}},"/orders/{id}/messages":{"get":{"tags":["Orders"],"summary":"Conversación con el técnico","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}},"post":{"tags":["Orders"],"summary":"Escribir al técnico","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"properties":{"text":{"type":"string","maxLength":4000}}}}}},"responses":{"201":{"description":"Creado"}}}},"/orders/{id}/revision":{"post":{"tags":["Orders"],"summary":"Pedir revisión de un fichero entregado (gratis, 30 días)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["reason"],"properties":{"reason":{"type":"string"}}}}}},"responses":{"200":{"description":"OK"},"409":{"description":"No completado o fuera de plazo","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/{id}/cancel":{"post":{"tags":["Orders"],"summary":"Cancelar un pedido en cola","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string"}}}}}},"responses":{"200":{"description":"OK"},"409":{"description":"Ya no está en cola","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks":{"get":{"tags":["Webhooks"],"summary":"Listar webhooks","responses":{"200":{"description":"OK"}}},"post":{"tags":["Webhooks"],"summary":"Crear un webhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["order.created","order.processing","order.needs_info","order.completed","order.revision","order.cancelled","order.refunded","order.message"]},"description":"Vacío = todos"}}}}}},"responses":{"201":{"description":"Devuelve el secreto una sola vez"}}}},"/webhooks/{id}":{"patch":{"tags":["Webhooks"],"summary":"Modificar un webhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}},"delete":{"tags":["Webhooks"],"summary":"Borrar un webhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}}},"/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"summary":"Enviar un evento de prueba","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"{ delivered, status }"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Authorization: Bearer rp_live_… (o rp_test_… para pruebas)"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}}}}}},"Upload":{"type":"object","properties":{"file_path":{"type":"string"},"upload_url":{"type":"string"},"method":{"type":"string"},"headers":{"type":"object"},"expires_in":{"type":"integer"},"max_bytes":{"type":"integer"}}},"NewOrder":{"type":"object","required":["file_path","vehicle_category_id","plate","make","model","engine","year","power_hp","km","gearbox","tool","ecu","services"],"properties":{"file_path":{"type":"string","description":"De POST /uploads (no necesario con multipart)"},"vehicle_category_id":{"type":"string","description":"De GET /services"},"plate":{"type":"string"},"make":{"type":"string"},"model":{"type":"string"},"engine":{"type":"string","example":"2.0 TDI 150 CV"},"year":{"type":"integer"},"power_hp":{"type":"integer","description":"Potencia de serie en CV"},"power_kw":{"type":"integer"},"km":{"type":"integer"},"gearbox":{"type":"string","enum":["manual","automatic"]},"tool":{"type":"string","example":"KESS3"},"ecu":{"type":"string","example":"Bosch EDC17C46"},"services":{"type":"array","items":{"type":"string","format":"uuid"}},"addons":{"type":"array","items":{"type":"string","format":"uuid"}},"read_method":{"type":"string","enum":["obd","banco","boot","bdm","jtag"]},"read_type":{"type":"string","enum":["completa","parcial"]},"vin":{"type":"string"},"dtc_codes":{"type":"array","items":{"type":"string"}},"notes":{"type":"string"},"external_ref":{"type":"string","description":"Tu referencia (idempotencia)"}}},"Order":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"reference":{"type":"string"},"status":{"type":"string","enum":["queued","pending","processing","revision","completed","cancelled","refunded"]},"external_ref":{"type":"string","nullable":true},"vehicle":{"type":"object","properties":{"plate":{"type":"string"},"make":{"type":"string"},"model":{"type":"string"},"engine":{"type":"string"},"year":{"type":"integer"},"power_hp":{"type":"integer"},"power_kw":{"type":"integer"},"km":{"type":"integer"},"gearbox":{"type":"string"},"vin":{"type":"string"}}},"ecu":{"type":"string"},"tool":{"type":"string"},"read_method":{"type":"string"},"services":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"credits":{"type":"number"}}}},"addons":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"credits":{"type":"number"}}}},"credits":{"type":"number"},"notes":{"type":"string"},"pending_reason":{"type":"string"},"files":{"type":"object","properties":{"original":{"type":"boolean"},"modified":{"type":"boolean"}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"completed_at":{"type":"string","format":"date-time","nullable":true},"links":{"type":"object","properties":{"self":{"type":"string"},"file":{"type":"string","nullable":true},"original":{"type":"string"},"messages":{"type":"string"}}}}},"Me":{"type":"object","properties":{"workshop":{"type":"object"},"credits":{"type":"object","properties":{"balance":{"type":"number"},"reserved":{"type":"number"},"available":{"type":"number"},"credit_line_available":{"type":"number"}}},"plan":{"type":"object"},"usage":{"type":"object"},"key":{"type":"object"}}},"WebhookEvent":{"type":"object","description":"Cuerpo POST que recibe tu URL. Firma: cabecera X-Repromatronic-Signature: t=<unix>,v1=<hex HMAC-SHA256 del texto `${t}.${body}` con el secreto sin el prefijo rpwh_>.","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["order.created","order.processing","order.needs_info","order.completed","order.revision","order.cancelled","order.refunded","order.message","test.ping"]},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"order":{"$ref":"#/components/schemas/Order"}}}}}}}}