Saltar al contenido principal
Las APIs de Importador cargan datos en lote en Tread. Envía un array de Pedidos, Proyectos, Tickets o Archivos en una sola solicitud en lugar de llamar al REST API registro por registro. Cada endpoint guarda tu payload y lo procesa en el fondo. Usa las APIs de Importador para cargas en lote — sembrando datos históricos, una sincronización nocturna desde tu ERP o sistema de contabilidad, o un feed de datos de alto volumen. Usa los endpoints del REST API en otro lugar de esta referencia cuando estés creando o actualizando un registro individual.
Esta API está en Beta. El comportamiento puede cambiar. Contacta a developers@tread.io con preguntas o comentarios.

URL base y autenticación

Cada endpoint de Importador vive bajo el mismo host que el resto de la API, con un prefijo /ingest.
https://api.tread-horizon.com/ingest
La autenticación usa el mismo token bearer que el resto de la API. Consulta Autenticación para saber cómo obtener uno.
Authorization: Bearer <access_token>
Content-Type depende del endpoint. Pedidos, Proyectos y Tickets toman JSON:
Content-Type: application/json
Archivos toma una carga multipart en su lugar — consulta Archivos. Cada payload JSON puede incluir un objeto metadata opcional para tu propio seguimiento, como un ID de lote o nombre del sistema de origen. Tread lo almacena pero no actúa sobre él.
{
  "orders": [ /* ... */ ],
  "metadata": { "source_system": "ERP", "batch_id": "2025-06-02-001" }
}

El modelo asincrónico

Pedidos, Proyectos y Tickets se procesan asincrónicamente. Una respuesta 202 Accepted significa que Tread guardó tu payload y lo puso en cola para procesamiento. No significa que el registro haya sido creado o actualizado.
202 Accepted no es éxito. Siempre verifica el estado del registro importado después de enviar un payload.
Dos formas de verificar un payload después de enviarlo:
  • Reports > API Integrations en la app Tread. Muestra Imported For, Import Received At, State, Last Error, y el payload sin procesar que enviaste. Por defecto los últimos 7 días, los más recientes primero.
  • Webhooks de error, si has configurado uno. Tread empuja un evento cuando un payload falla al procesarse. Consulta Webhooks.
Cada registro importado termina en uno de estos estados:
EstadoSignificado
createdRecibido. Aún no procesado.
processedÉxito.
failedFalló. Reintentos pendientes.
exhaustedFalló. Todos los reintentos agotados.
skippedUna regla de negocio lo bloqueó — por ejemplo, un payload duplicado.
skipped_updateUna actualización se omitió porque un usuario editó ese campo en la app Tread.
Si un registro está failed o exhausted, lee su campo last_error para la razón, corrige los datos de origen, y reenvía. Tread desduplicará automáticamente, así que reenviar el mismo payload es seguro. El endpoint de Archivos es la única excepción — procesa sincrónicamente. Consulta Archivos.

Pedidos

POST /ingest/orders crea o actualiza Pedidos. La clave raíz es orders — envía un array, incluso para un registro individual.

Campos requeridos

CampoNotas
external_idTu ID del sistema para este pedido (Ext. ID — usado para coincidir en solicitudes futuras).
load_atFecha y hora de carga, ISO 8601. Interpretado en la zona horaria de la empresa.
customer.external_idTu ID del sistema para el cliente que realiza el pedido.

Solicitud de ejemplo

curl -X POST https://api.tread-horizon.com/ingest/orders \
  -H "Authorization: Bearer $TREAD_TOKEN" \
  -H "Content-Type: application/json" \
  -d @payload.json
{
  "orders": [
    {
      "external_id": "ORD-2025-0142",
      "load_at": "2025-06-02T07:30:00",
      "customer": { "external_id": "CUST-441", "name": "Acme Aggregates" },
      "material": { "external_id": "MAT-GRAVEL-34" },
      "sites": [
        { "waypoint": "pickup", "external_id": "SITE-QUARRY-1", "full_address": "4500 Quarry Rd, Denver, CO" },
        { "waypoint": "drop_off", "external_id": "SITE-JOB-19", "full_address": "800 Main St, Denver, CO" }
      ],
      "truck_count": 4,
      "service": "Hired Truck"
    }
  ]
}

Notas de comportamiento

  • La coincidencia es por external_id, limitada a tu empresa. Una coincidencia actualiza los campos raíz del pedido — nombre, cantidades, tarifas, notas, y más.
  • customer, material, equipment_type, y sites son registros anidados. Tread los crea si no existen pero no los actualiza en una coincidencia — consulta coincidencia external_id.
  • foremen y vendors son arrays. Cada payload reemplaza el array completo — no se fusiona con lo que ya está allí. Esto es verdad incluso si omites el campo: omitir foremen no preserva los foremen existentes. Envía el conjunto completo cada vez.
  • Si un pedido se cancela y luego envías un payload con el mismo external_id en un estado no cancelado, Tread renombra el external_id del pedido cancelado a X-{N} y crea un nuevo pedido. Esto es automático — no se necesita limpieza de tu parte.

Proyectos

POST /ingest/projects crea o actualiza Proyectos. La clave raíz es projects.

Campos requeridos

CampoNotas
external_idTu ID del sistema para este proyecto.
customer.external_idTu ID del sistema para el cliente.

Solicitud de ejemplo

curl -X POST https://api.tread-horizon.com/ingest/projects \
  -H "Authorization: Bearer $TREAD_TOKEN" \
  -H "Content-Type: application/json" \
  -d @payload.json
{
  "projects": [
    {
      "external_id": "PRJ-2025-014",
      "name": "Highway 401 Resurfacing",
      "effective_at": "2025-05-01T00:00:00",
      "customer": { "external_id": "CUST-441", "name": "Acme Aggregates" },
      "phases": [
        { "name": "Mobilization", "code": "PH-01" },
        { "name": "Paving", "code": "PH-02" }
      ],
      "materials": [
        { "external_id": "MAT-ASPHALT-12", "total_quantity": 2500, "unit_of_measure": "Ton" }
      ]
    }
  ]
}
effective_at debe ser estrictamente antes de expires_at. Si tus datos de origen los tienen iguales — común para proyectos de un día — omite expires_at completamente. No lo configures para el final del día; simplemente déjalo fuera.

Notas de comportamiento

  • La coincidencia es por external_id. Una coincidencia actualiza campos raíz — nombre, fechas, notas, tarifas.
  • La sincronización de fases es destructiva. Cada payload reemplaza la lista de fases completa. Una fase omitida del payload se elimina. Siempre envía el conjunto completo, no solo lo que cambió.
  • La sincronización de materiales es igual. Un material omitido del payload se elimina del proyecto.
  • Los sitios necesitan una dirección. Cada sitio necesita full_address o lat/lon. Si tus datos de origen solo tienen un nombre de sitio, establece full_address en ese nombre — Tread lo geocodifica automáticamente. Sin uno de estos, el sitio falla la validación y se descarta silenciosamente: el proyecto aún reporta éxito, pero ese recogida o entrega falta y no aparece error.
  • foremen reemplazan en la actualización, igual que en Pedidos.
  • Si el nombre de un proyecto colisiona con el nombre de otro proyecto diferente, Tread le añade -{external_id} para mantener ambos.

Tickets

POST /ingest/tickets crea Tickets — el registro de prueba de carga para una Carga. La clave raíz es tickets.

Campos requeridos

CampoNotas
ticket_numberÚnico por empresa.
service_dateISO 8601.
quantityCantidad numérica.
unit_of_measureValor enum exacto — consulta referencia de enums.
truck_idIdentifica el camión.

Solicitud de ejemplo

curl -X POST https://api.tread-horizon.com/ingest/tickets \
  -H "Authorization: Bearer $TREAD_TOKEN" \
  -H "Content-Type: application/json" \
  -d @payload.json
{
  "tickets": [
    {
      "ticket_number": "T-88213",
      "service_date": "2025-06-02T14:10:00Z",
      "quantity": 22.4,
      "unit_of_measure": "Ton",
      "truck_id": "T-101",
      "dispatch_number": "DISP-2025-0142",
      "material": { "external_id": "MAT-GRAVEL-34" },
      "customer": { "external_id": "CUST-441" }
    }
  ]
}

Notas de comportamiento

  • Tread vincula un ticket a un pedido de dos formas: tread_order_id (directo, preferido) o dispatch_number más una fecha de inicio de trabajo coincidente (alternativa). Envía tread_order_id cuando lo tengas.
  • La normalización de unit_of_measure es insensible a mayúsculas pero los valores exactos son más seguros. "tons" se convierte en "Ton", pero una cadena que el sistema no reconoce puede caer silenciosamente a la predeterminada (Ton) en lugar de error. Usa el valor enum exacto.
  • site es un objeto individual en Tickets — a diferencia de Pedidos y Proyectos, donde sites es un array.

Archivos

POST /ingest/files adjunta un archivo a un Pedido existente (o próximo a existir). Usa multipart/form-data, no JSON — todos los demás endpoints de Importador usan JSON.

Campos requeridos

CampoNotas
fileCarga binaria de archivo. Una cadena de URL se rechaza.
external_idEl external_id del Pedido objetivo.
file_attachable_typeActualmente solo Order es soportado.
Opcional: category (Inspection Report, Site Map, Scale Ticket (External), Scale Ticket (Internal), Timesheet, o Other) y description. El tamaño máximo de archivo es 10 MB. Tipos aceptados: JPEG, PNG, WebP, GIF, y PDF.

Solicitud de ejemplo

curl -X POST https://api.tread-horizon.com/ingest/files \
  -H "Authorization: Bearer $TREAD_TOKEN" \
  -F "file=@/path/to/scale-ticket.jpg" \
  -F "external_id=ORD-2025-0142" \
  -F "file_attachable_type=Order" \
  -F "category=Scale Ticket (External)"

Notas de comportamiento

Los archivos se procesan sincrónicamente — la única excepción entre las APIs de Importador.
  • 201 Created — el Pedido ya existe. Tread adjunta el archivo inmediatamente.
  • 202 Accepted — el Pedido aún no existe. Tread almacena el archivo y lo adjunta automáticamente una vez que llega un Pedido coincidente — los archivos y pedidos pueden llegar en cualquier orden. No se necesita llamada extra.
  • 422 — el archivo falló la validación (tipo incorrecto o más de 10 MB).

Coincidencia external_id y comportamiento de upsert

Cada endpoint de Importador usa external_id — tu identificador del sistema — para decidir si crear un nuevo registro o actualizar uno existente. Está limitado por empresa y es sensible a mayúsculas. Registros raíz (Pedido, Proyecto, Ticket) funcionan como era de esperar: encontrado por external_id → actualizar; no encontrado → crear. Registros anidados (cliente, material, tipo de equipo, sitios, foremen) funcionan diferente. Tread los crea si no existen, pero generalmente no actualiza sus campos una vez coincidentes. Enviar un name diferente para un cliente que ya existe no lo renombra.
Registro anidadoCoincidencia por
ClienteNombre, luego external_id
MaterialNombre, luego external_id
SitioNombre y external_id juntos, luego cualquiera
Tipo de equipoNombre o external_id
ForemanCorreo electrónico, luego teléfono, luego external_id
Para renombrar un cliente, material, u otro registro de datos maestros, usa los endpoints del REST API en otro lugar de esta referencia — no las APIs de Importador. Los arrays siguen uno de tres patrones en actualización:
ArrayComportamiento
foremen, vendors, collaborators, salespeopleReemplazar — el array completo se intercambia
phases, materials (solo Proyectos)Sincronizar — los elementos faltantes del payload se eliminan
sitesUpsert — coincidencia por tipo de waypoint; el ID del registro se preserva

Referencia de enums

Valores exactos de cadena que Tread espera. Un valor fuera de esta lista se normaliza (unidad de medida) o se rechaza. Unidad de medidaLoad, Tonne, Ton, Yard, Meter, Foot, Liter, Hour, Bushel, Gallon, CubicMeter, Mile, Kilometer, Barrel, Bag, Pallet. Predeterminado: Ton. Tipo de tarifaRatePerHour (predeterminado), RatePerDay, RatePerLoad, RatePerTon, RatePerTonne, RatePerYard, RatePerBushel, RateCommission, RateFlatCommission, RateFlatRate. Waypoint del sitiopickup, staging, drop_off, weigh_point. Tipo de sitioPlant, Quarry, JobSite, Depot, EquipmentHomeBase, Daily, Other (predeterminado).

Trampa comunes

  • 202 no significa que funcionó. Verifica el estado del registro importado antes de tratar un payload como completo.
  • Los registros anidados no se actualizan en la coincidencia. Renombrar un cliente o material en tu payload no tiene efecto una vez que ese registro ya existe. Usa el REST API para renombrarlo.
  • Los sitios sin dirección se descartan, silenciosamente. Sin full_address o lat/lon en un sitio significa que Tread lo descarta — y el Proyecto u Orden aún reporta éxito.
  • Los números de teléfono inválidos se descartan, silenciosamente. Un teléfono que no se normaliza a E.164 se elimina del contacto. Sin error, sin entrada de last_error.
  • Los payloads duplicados se omiten, no se reprocesa. Enviar el mismo payload exacto dos veces marca el segundo como skipped. Esto es esperado, no un bug.
  • La sincronización de fases elimina lo que dejas fuera. Cada payload de Proyecto reemplaza la lista de fases completa, no solo las fases que estés cambiando.
  • Los foremen y vendors reemplazan, no se fusionan. Cada payload con un array foremen o vendors intercambia el todo, incluso si omites el campo.
  • La unidad de medida es exigente. "tons" se normaliza a "Ton", pero una cadena que el sistema no reconoce cae silenciosamente al predeterminado (Ton) en lugar de error. Usa valores enum exactos.

Gestión de registros individuales

¿Necesitas crear, actualizar o eliminar un registro a la vez en lugar de carga en lote? Usa los endpoints del REST API en otro lugar de esta referencia. Son sincrónicos — un 201 o 200 significa que está listo — y soportan actualizaciones de campo completas en registros anidados, incluyendo renombrar un cliente o material. Las APIs de Importador son solo para cargas en lote.

Continuar

Autenticación

Obtén un token bearer para estos endpoints.

Webhooks

Recibe notificaciones cuando un payload importado falla al procesarse.

Pedidos y Proyectos

Cómo se ajusta la jerarquía de despacho.

Tickets y Partes de horas

Qué registra un Ticket, y cómo se convierte en una Liquidación.