Developer API

Repromatronic API for workshops and resellers

Submit ECU files, track status, download the modified file and get notified inside your own workshop software. Same queue and same engineers as the panel: every file is modified and verified by a human engineer.

How it works

1. Upload permission

POST /uploads returns a signed URL. Upload the original read with a direct PUT (up to 50 MB).

2. Create the order

POST /orders with vehicle, ECU, tool and services. Credits are charged on delivery, exactly like in the panel.

3. Notification and download

When the engineer delivers, you receive the order.completed webhook and download with GET /orders/{id}/file. If more info is needed, order.needs_info arrives.

Plans

Monthly price excluding VAT. Files are paid with the account's credits at the same price as in the panel. No lock-in: cancel from the panel.

API Taller

Para integrar tu propio programa de gestión con el servicio de ficheros.

€59€/month

  • ✓ Hasta 50 ficheros al mes por API
  • ✓ 1 clave de producción + claves de pruebas
  • ✓ 2 webhooks
  • ✓ 2.000 llamadas al día
  • ✓ Catálogo de vehículos y servicios
  • ✓ Soporte por email
Subscribe

API Pro

Para talleres grandes y revendedores con volumen.

€149€/month

  • ✓ Hasta 250 ficheros al mes por API
  • ✓ 5 claves de producción + claves de pruebas
  • ✓ 10 webhooks
  • ✓ 10.000 llamadas al día
  • ✓ Catálogo de vehículos y servicios
  • ✓ Soporte prioritario
Subscribe

API Empresa

Tarifa a medida para grandes consumos y redes de talleres.

from €349€/month

  • ✓ Ficheros sin límite
  • ✓ Claves y webhooks sin límite
  • ✓ Varias sucursales bajo una cuenta
  • ✓ Acuerdo de nivel de servicio
  • ✓ Integración asistida
  • ✓ Soporte prioritario
Request a quote

Test keys (rp_test_) are included in every plan: they never create orders or spend credits.

Authentication

Every request carries an Authorization: Bearer header with a key created in Panel › API. rp_live_ keys create real orders; rp_test_ keys validate everything but create nothing. Treat the key as a password and revoke it in the panel if it leaks.

Authorization: Bearer rp_live_0123456789abcdef0123456789abcdef

Quick start

# 1) Upload permission / Permiso de subida
curl -X POST https://app.repromatronic.es/api/v1/uploads \
  -H "Authorization: Bearer rp_live_XXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{"filename":"original.bin","size":1048576}'
# → { "file_path": "...", "upload_url": "https://...", "method": "PUT" }

curl -X PUT "<upload_url>" -H "Content-Type: application/octet-stream" \
  -H "x-upsert: false" --data-binary @original.bin

# 2) Create the order / Crear el pedido
curl -X POST https://app.repromatronic.es/api/v1/orders \
  -H "Authorization: Bearer rp_live_XXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
    "file_path": "<file_path>",
    "vehicle_category_id": "<id from /services>",
    "plate": "1234ABC", "make": "Audi", "model": "A4", "engine": "2.0 TDI 150 CV",
    "year": 2019, "power_hp": 150, "km": 85000, "gearbox": "manual",
    "tool": "KESS3", "ecu": "Bosch EDC17C74",
    "services": ["<service_id>"], "external_ref": "OT-2026-0412"
  }'
# → 201 { "order": { "id": "…", "status": "queued", "credits": 2, … } }

# 3) When order.completed arrives / Cuando llega order.completed
curl https://app.repromatronic.es/api/v1/orders/<id>/file \
  -H "Authorization: Bearer rp_live_XXXXXXXX"
# → { "url": "https://…", "filename": "…", "expires_in": 3600 }

Endpoint reference

Base: https://app.repromatronic.es/api/v1 · All responses are JSON · Dates in ISO 8601 (UTC)

MethodPathWhat it does
GET/meAccount, credit balance, plan and monthly usage.
GET/servicesVehicle categories, services with credit cost, add-ons and incompatibilities.
GET/vehicles/types · /makes?type= · /models?make= · /generations?model= · /engines?generation= · /engines/{id} · /search?q=Vehicle catalogue: stock power and torque, stages, read methods and tools.
POST/uploadsSigned upload permission for the original file (step 1).
POST/ordersCreates the order (step 2). JSON with file_path, or multipart with `file` under 4 MB. `external_ref` prevents duplicates.
GET/ordersList with filters: status, since, plate, external_ref; page/limit pagination.
GET/orders/{id}Order detail and status.
GET/orders/{id}/fileModified file: 1-hour signed URL (or 302 with ?redirect=1).
GET/orders/{id}/originalYour original file.
GET · POST/orders/{id}/messagesConversation with the engineer: read and write.
POST/orders/{id}/revisionRequest a revision of a delivered file (free, 30 days).
POST/orders/{id}/cancelCancel an order still in the queue.
GET · POST · PATCH · DELETE/webhooks · /webhooks/{id} · /webhooks/{id}/testManage your webhooks and send a test event.
GET/plans · /openapi.jsonPublic, no key needed.

POST /orders fields

file_pathPath returned by /uploads (required unless you send `file` as multipart).
vehicle_category_idCategory id from GET /services (car, truck, agricultural…).
plate, make, model, engine, yearRegistration plate, make, model, engine (e.g. “2.0 TDI 150 hp”) and year.
power_hp, power_kw, km, gearboxStock power in hp (kW optional), mileage and gearbox: manual or automatic.
tool, ecuRead tool (KESS3, Flex, Autotuner, bFlash…) and ECU (e.g. “Bosch EDC17C46”).
services[], addons[]Ids from GET /services. At least one service; add-ons go with their service.
read_method, read_type, vin, dtc_codes[], notesOptional: obd/banco/boot/bdm/jtag, completa/parcial (full/partial), VIN, fault codes and notes for the engineer.
external_refYour reference (work order). Repeating it never creates a second order.

Order states

queuedQueued: received, waiting for an engineer.
pendingNeeds info: the engineer needs something from you (pending_reason).
processingIn progress.
completedCompleted: the modified file is available.
revisionUnder revision at the workshop's request.
cancelled / refundedCancelled / refunded (credits returned).

Webhooks

Register an https URL and the events you want (or none to receive all). Every delivery is a signed JSON POST. Reply 2xx within 8 seconds; otherwise we retry up to 7 times with growing delays (1 min → 12 h).

Events

order.createdOrder received.
order.processingAn engineer started working on it.
order.needs_infoThe engineer needs something (data.reason).
order.completedModified file ready: download it with /orders/{id}/file.
order.revisionRevision accepted.
order.messageMessage from the engineer (data.message).
order.cancelled · order.refundedCancelled or refunded.

Verifying the signature

Header X-Repromatronic-Signature: t=<unix>,v1=<hex>. v1 is the HMAC-SHA256 of the string `${t}.${body}` using the webhook secret without the rpwh_ prefix. Reject signatures older than 5 minutes.

// Node.js
const crypto = require("crypto");
function verify(secret, header, rawBody) {
  const m = /t=(\d+),v1=([0-9a-f]+)/.exec(header || "");
  if (!m) return false;
  if (Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
  const expected = crypto.createHmac("sha256", secret.replace(/^rpwh_/, ""))
    .update(`${m[1]}.${rawBody}`).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(m[2], "hex"));
}
<?php // PHP
function verify(string $secret, string $header, string $rawBody): bool {
  if (!preg_match('/t=(\d+),v1=([0-9a-f]+)/', $header, $m)) return false;
  if (abs(time() - (int)$m[1]) > 300) return false;
  $expected = hash_hmac('sha256', $m[1] . '.' . $rawBody, preg_replace('/^rpwh_/', '', $secret));
  return hash_equals($expected, $m[2]);
}
{
  "id": "evt_9f2c…",
  "type": "order.completed",
  "created_at": "2026-10-11T16:20:00.000Z",
  "data": { "order": { "id": "…", "reference": "A1B2C3D4", "status": "completed", "external_ref": "OT-2026-0412", "links": { "file": "/api/v1/orders/…/file" } } }
}

Errors and limits

Errors return { error: { code, message, fields? } }. Limits: 120 calls per minute per key, plus the plan's daily calls and monthly files. Exceeding them returns 429 (with retry_after) or 402 (plan quota or insufficient credits).

401 unauthorizedMissing, invalid or revoked key.
402 subscription_required · plan_quota_exceeded · insufficient_credits_reservedNo plan, monthly quota used up, or not enough credits.
409 not_ready · not_cancellable · window_expiredThe action does not apply in the current state.
422 validation_errorInvalid fields: see error.fields.
429 rate_limited · daily_limitToo many calls.

Test mode

With an rp_test_ key every read works on your real data, and writes (orders, messages, revisions, cancellations) are validated and return the same shape as production without creating anything or spending credits. To test webhook delivery use POST /webhooks/{id}/test.

FAQ

How much does each file cost via the API?

The same as in the panel: it is deducted from your credits on delivery. The plan only covers API access.

Does my software need to be special?

No. Anything that can make HTTPS requests (PHP, .NET, Node, Python, Java…) works. If you use commercial software, hand this page to its vendor.

Can I resell the service under my brand?

Yes: the Enterprise plan supports several branches under one account, and the tuning certificate carries your brand if you enable it in the panel.

What are the hours?

The API answers 24/7. Files are processed during the engineering team's hours, every day 8:00–22:00 CET.

Where do I get help?

Email info@repromatronic.es with the time of the call and the path, or open a ticket in the panel.