Integra tus reportes de campo con tu ERP
Una API REST para que tu sistema consuma los reportes de tu organización: búscalos, descárgalos en PDF, etiquétalos con tu referencia y recibe avisos automáticos cuando se crean. Server-to-server, en cualquier lenguaje.
# Trae el reporte de una orden y baja su PDF curl -H "Authorization: Bearer $SR_API_KEY" \ "https://api.servireports.com/api/v1/reports?query=OT-2026-00184" # Respuesta { "reports": [{ "folio": "OYS2609-001", "referenceId": "OT-2026-00184" }], "count": 1 }
Automatiza: el reporte foliado por tu técnico aparece solo en tu ERP.
Concilia sin doble captura: cada reporte ligado a tu orden por Referencia ID.
Menos llamadas, más automatización: webhooks + cache de tu lado.
Documentación para desarrolladores
Todo lo que necesitas para integrar, con ejemplos en 5 lenguajes.
Límites del servicio
Tomados de la configuración actual del servicio, no escritos a mano.
Por organización. Solo las descargas consumen cuota.
Búsqueda, uso, Referencia ID e índice no consumen cuota.
Introducción
Conecta los reportes de campo de tu organización con tu ERP u otros sistemas.
ServiReports Connect es una API REST sobre HTTPS que responde en JSON. Con ella tu sistema puede buscar los reportes de tu organización, descargar su PDF, etiquetarlos con tu propio identificador y recibir avisos automáticos cuando ocurren eventos.
Al ser HTTP estándar, es compatible con cualquier lenguaje — JavaScript/Node, Python, PHP, Java, C#, Go, Ruby — o simplemente curl. No hay que instalar ningún SDK: usas el cliente HTTP que ya trae tu lenguaje.
Importante: la API es servidor-a-servidor (server-to-server)
Debes llamar la API desde el backend de tu sistema (tu servidor), NO desde el navegador ni desde el frontend de una página web. Dos razones:
- Tu
API_KEYes secreta. Si la pones en JavaScript de navegador, cualquiera que abra el inspector la puede robar. - Por seguridad, las llamadas desde un navegador de otro dominio son rechazadas (CORS / origen no permitido). Solo funcionan desde servidor, donde no hay navegador de por medio.
En corto: guarda la llave en una variable de entorno de tu servidor y haz las llamadas desde ahí. Todos los ejemplos de esta guía asumen eso.
Propósito. Automatizar tu operación: que un reporte foliado por tu técnico aparezca solo en tu ERP, ligado a tu orden de trabajo o factura, y obtener su PDF cuando lo necesites — sin que nadie entre al portal a copiar datos a mano.
Suscripción. El uso en producción requiere la suscripción de la API (una por organización). Puedes desarrollar y probar gratis en modo sandbox antes de activarla.
Anatomía de una llamada
De qué se compone cada petición — para que sepas exactamente qué mandar.
Toda llamada a la API se arma con cuatro piezas. Tomemos como ejemplo “buscar reportes”:
GETLa acción HTTP: GET (leer), POST (crear), PATCH (actualizar), DELETE (borrar).
https://api.servireports.com/api/v1/reports?query=bomba&limit=20La URL base + la ruta del recurso + parámetros opcionales después del signo ?.
Authorization: Bearer TU_API_KEYTu llave. En POST/PATCH agrega también Content-Type: application/json.
{ "referenceId": "OT-2026-00184" }Solo en POST/PATCH: los datos en JSON. GET y DELETE no llevan cuerpo.
Así se ve completa, con las cuatro piezas juntas (misma llamada en 5 lenguajes):
curl -H "Authorization: Bearer TU_API_KEY" \ "https://api.servireports.com/api/v1/reports?query=bomba&limit=20"
La API siempre responde con un código HTTP (200 = todo bien) y un cuerpo JSON. Mira la pestaña Respuesta arriba para ver exactamente qué te devuelve. En la sección Respuestas y diagnóstico explicamos cada código.
Modo Sandbox
Prueba la integración gratis, sin suscripción.
Las llaves que empiezan con dev_ son de sandbox. Funcionan gratis sobre los datos reales de tu organización, para que desarrolles y valides tu integración sin costo.
En sandbox, la descarga de PDF devuelve un PDF de prueba (con la leyenda “Prueba de descarga PDF”) y no consume cuota. Todo lo demás — búsqueda, referencia, registro de webhooks — se comporta igual que en producción, así tu código no cambia al pasar a vivo: solo cambias la llave.
Modo Producción
Tus reportes reales y sus PDF definitivos.
Las llaves que empiezan con sr_live_ son de producción: entregan tus reportes reales y el PDF definitivo de cada uno. Requieren la suscripción de la API activa.
Si llamas con una llave de producción sin suscripción activa, la API responde 403 API_SUBSCRIPTION_REQUIRED. Actívala o renuévala desde la gestión de la suscripción.
API Keys
Cómo generarlas, usarlas y revocarlas.
Generar. En la pestaña Claves generas una llave sandbox o de producción. La llave completa se muestra una sola vez al crearla — guárdala en un lugar seguro (variable de entorno o gestor de secretos). Solo guardamos una huella; no podemos volver a mostrártela.
Usar. Envíala en el encabezado Authorization: Bearer TU_API_KEY en cada solicitud. Tu organización se identifica a partir de la propia llave — nunca la envías tú.
curl -H "Authorization: Bearer TU_API_KEY" "https://api.servireports.com/api/v1/usage"
¿Puedo tener varias? Sí. Crea las que necesites (por sistema, por ambiente). Todas comparten la misma cuota diaria de descargas de tu organización.
Eliminar. Revoca una llave desde la pestaña Claves; deja de funcionar de inmediato. Si sospechas que se filtró, revócala y genera otra.
Uso justo (rate-limit)
Sin cobro por uso. Solo las descargas de PDF tienen cuota.
- Las consultas son gratis y sin límite: buscar reportes, consultar uso, actualizar la referencia, gestionar webhooks.
- Solo las descargas de PDF consumen una cuota diaria por organización, compartida entre todas tus llaves.
- Al agotar la cuota del día, la descarga responde
429 API_RATE_LIMITEDcon el encabezadoRetry-After(segundos hasta el reinicio). Respeta ese valor y reintenta. - Consulta cuánto te queda cuando quieras con
GET /usage.
Respuestas y diagnóstico
Cómo saber si tu llamada salió bien — o qué pasó si no.
Cada respuesta trae un código HTTP. Con él diagnosticas todo: si empieza en 2xx salió bien; 4xx es un problema de tu petición; 5xx es un error temporal del servidor.
| Código | Significa | Cuándo |
|---|---|---|
| 200 OK | Todo correcto. | Búsqueda, PDF, referencia, usage, listar/eliminar webhooks. |
| 201 Created | Recurso creado. | Al registrar un webhook (POST /webhooks). |
| 4xx | Error de tu petición. | Llave inválida, sin suscripción, cuota agotada, folio inexistente… (ver Códigos de error). |
| 5xx | Error del servidor. | Temporal. Reintenta con backoff; si persiste, contacta a soporte. |
- Los éxitos (2xx) devuelven el JSON del recurso (revisa la pestaña Respuesta en cada función).
- Los errores devuelven
{ "code": "...", "error": "..." }. Programa contracode(estable), no contra el texto. - Toda respuesta trae el encabezado
X-ServiReports-Mode: sandbox | production, para confirmar contra qué entorno hablas.
Actividad
Evalúa el uso y gestiona tus recursos.
En la pestaña Actividad ves el uso por cada API key (última vez utilizada), para saber qué llaves están activas, detectar integraciones que dejaron de usarse y decidir cuáles conservar o revocar.
Para el estado de la cuota del día (límite, usado, restante) usa GET /usage desde tu integración — así tu propio sistema se monitorea y previene antes de una carga grande.
Reportes
Qué son y cómo se entregan.
Un reporte es el documento de campo que tu técnico generó y folió desde la app: datos generales, secciones de contenido, fotos y firmas. Una vez foliado es definitivo (no cambia). Cada reporte tiene un folio único (ej. OYS2609-001) — es su identificador.
- Metadata (JSON) al buscarlo: folio, título, cliente, empresa, departamento, tipo de usuario, quién lo creó, fechas y tu referencia.
- Documento en PDF cuando lo descargas: el reporte completo, listo para archivar o imprimir. Para verlo, cualquier visor de PDF estándar.
La API no entrega las fotos/firmas sueltas; entrega el PDF final, que ya las incluye.
Índice
El catálogo de reportes de tu organización.
El índice es la lista de todos los reportes foliados de tu organización con su metadata. Es lo que consultas con GET /reports, con filtros y paginación.
Se entrega como JSON paginado: cada respuesta trae un arreglo reports, un count y un nextCursor. La primera vez (para llenar tu ERP con el histórico) recorres todo el índice pidiendo páginas con ?cursor=<nextCursor> hasta que nextCursor venga vacío — o, más simple, pides ?limit=-1 y te devolvemos todo de una vez. Después ya no re-lees todo: te mantienes al día con el webhook report.created.
Volcado completo (backfill inicial), en 5 lenguajes:
# El volcado completo se hace en bucle (pagina por pagina). # Se implementa en tu lenguaje; el patron es: pedir 100, guardar, # tomar nextCursor, repetir hasta que venga vacio. Ver otras pestanas.
Funciones
Cada operación de la API, con ejemplos en 5 lenguajes y su respuesta.
/catalogCatálogo de departamentos, tipos de usuario y prefijos
Qué hace: devuelve el catálogo de departamentos, tipos de usuario y prefijos (el prefijo del folio, definido por cada plantilla) de tu organización. Cada elemento trae su ID, su nombre, a qué departamento pertenece cada tipo, y si está activo o fue eliminado.
deptId y userTypeId (IDs, no nombres) y su folio empieza con un prefijo. Con este catálogo tu ERP resuelve cada ID a su nombre, mapea el prefijo a su plantilla/tipo de reporte, y para filtrar en GET /reports por departamento o tipo usas el ID que sale de aquí.- Activos: los que existen hoy en tu organización (
status: "active"). - Eliminados: los que ya se borraron pero que aún aparecen en reportes viejos (
status: "deleted") — así puedes seguir resolviendo esos IDs históricos. - Cada tipo de usuario trae su
deptId+deptName(el departamento al que pertenece). - Cada prefijo trae
folioPrefix,name(nombre de la plantilla),reportTypey sutemplateId. - Agrega
?includeDeleted=falsesi solo quieres los activos (respuesta más rápida).
curl -H "Authorization: Bearer TU_API_KEY" \ "https://api.servireports.com/api/v1/catalog"
Uso eficiente: cachea el catálogo de tu lado y refréscalo de vez en cuando (cambia poco). Úsalo para poblar los filtros por departamento/tipo de tu ERP con los IDs correctos.
/reportsBuscar reportes
Devuelve reportes del índice de tu organización. Parámetros (todos opcionales y combinables, van en la URL después del ?):
query— texto libre; busca en título, cliente, empresa, folio, departamento, tipo y tu referenceId.deptId/userTypeId— filtra por departamento o tipo de usuario. Ojo: son IDs, no nombres. Obtén esos IDs conGET /catalog.from/to— rango de fechas sobrecreatedAt(ambos inclusive). Acepta fechaYYYY-MM-DDo fecha-hora ISO. Puedes mandar solo uno.limit— cuántos traer, de1a1000(numeración libre, no hay valores fijos; default 50). Usalimit=-1para traer TODOS los reportes que cumplan el filtro de una sola vez.cursor— para pedir la siguiente página (se ignora conlimit=-1).
Ejemplo completo usando todos los filtros a la vez (en 5 lenguajes):
# deptId y userTypeId son IDs (no nombres). Los obtienes de GET /catalog. # from/to aceptan fecha (YYYY-MM-DD) o fecha-hora ISO. limit hasta 1000. curl -H "Authorization: Bearer TU_API_KEY" \ "https://api.servireports.com/api/v1/reports?query=bomba\ &deptId=8f3a1c20-...&userTypeId=b7d0e9a1-...\ &from=2026-09-01&to=2026-09-30&limit=100"
- Uso eficiente: filtra con
querypor tureferenceIdpara encontrar al instante el reporte de una orden o factura. - Volcado histórico: usa
limit=-1(o pagina concursor) para llenar tu ERP la primera vez; luego mantente al día con el webhookreport.created. - Cortes por periodo: combina
from/topara traer, por ejemplo, solo los reportes de un mes.
/reports/{folio}/pdfDescargar PDF
Reemplaza {folio} por el folio del reporte (ej. /reports/OYS2609-001/pdf). No devuelve el archivo directo, sino un JSON con una URL de descarga temporal (válida 30 min); descargas el PDF desde ese downloadUrl.
# 1) pide la URL de descarga curl -H "Authorization: Bearer TU_API_KEY" \ "https://api.servireports.com/api/v1/reports/OYS2609-001/pdf" # 2) descarga el PDF desde el downloadUrl que te devolvio curl -o reporte.pdf "URL_DEVUELTA"
Uso eficiente: solo esto consume cuota. Si vas a mostrar el mismo reporte varias veces, guárdalo de tu lado y reutilízalo. El campo downloads.remaining de la respuesta te dice cuánta cuota te queda.
/reports/{folio}Actualizar la Referencia ID
Qué hace: le escribe (o cambia) a un reporte tu Referencia ID — tu identificador externo. En la URL va el {folio} (qué reporte quieres actualizar) y en el cuerpo va el valor nuevo: { "referenceId": "OT-2026-00184" }. Es decir: “a este reporte, ponle esta referencia”.
¿Qué es la Referencia ID y por qué te conviene? (léelo, vale oro para tu ERP)
Cada reporte ya viene clasificado por departamento y tipo de usuario — eso te dice de dónde salió y quién lo hizo. La Referencia ID es un dato extra tuyo para clasificarlo aún mejor, ligándolo a algo de tu mundo: el número de tu orden de trabajo, el folio de tu ERP, un proyecto o una factura.
Con eso, un reporte de campo deja de ser un documento suelto y se convierte en parte de tu flujo: puedes decir “dame el reporte de la orden OT-2026-00184” y encontrarlo al instante (GET /reports?query=OT-2026-00184). Ese puente entre el reporte del técnico y tu proceso de negocio es exactamente lo que hace que Connect API valga la pena para un ERP: automatizas la clasificación y la conciliación sin que nadie copie folios a mano.
Es texto libre (hasta 120 caracteres). No cambia ni se imprime en el PDF; es solo para clasificar e integrar.
¿De dónde sale y cómo se actualiza?
- Al crear el reporte: el técnico la captura en la app al foliar (si la plantilla la pide). Ese es el camino normal.
- Desde el Portal ServiReports: un admin la puede editar en el detalle del reporte.
- Por la API (esta función): tu ERP la escribe o corrige automáticamente — ideal si necesitas re-clasificar reportes en lote o asignar la referencia desde tu sistema sin intervención humana.
curl -X PATCH \ -H "Authorization: Bearer TU_API_KEY" \ -H "Content-Type: application/json" \ -d '{"referenceId":"OT-2026-00184"}' \ "https://api.servireports.com/api/v1/reports/OYS2609-001"
Para quitar la referencia, envía { "referenceId": "" } o null.
/usageConsultar uso
Te dice el modo (sandbox/producción), si tu suscripción está activa y cuánta cuota de descargas te queda hoy. Úsalo para prevenir antes de una carga grande y reaccionar a lowRemaining.
curl -H "Authorization: Bearer TU_API_KEY" "https://api.servireports.com/api/v1/usage"
Webhooks
Recibe avisos automáticos en tu servidor, en vez de consultar en bucle.
Un webhook es al revés de una llamada normal: en vez de que tú preguntes, nosotros avisamos a tu servidor cuando pasa algo. Tú registras una URL https tuya y te mandamos un POST firmado cada vez que ocurre el evento.
Paso 1 — registrar tu URL y a qué eventos suscribirte:
curl -X POST \ -H "Authorization: Bearer TU_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url":"https://tu-sistema.com/sr-hook","events":["report.created"]}' \ "https://api.servireports.com/api/v1/webhooks"
Guarda el secret que te devuelve: lo necesitas para verificar que el aviso realmente vino de nosotros. Cada envío llega a tu URL con estos encabezados:
X-ServiReports-Delivery: <uuid> (id único por envío)
X-ServiReports-Signature: sha256=<hmac>
Paso 2 — verifica la firma antes de confiar en el aviso. Calculas el HMAC-SHA256 del cuerpo crudo (sin parsear) con tu secret y lo comparas con X-ServiReports-Signature:
# La verificacion de firma se hace en TU servidor (no con curl). # Formula: sha256=HMAC_SHA256(cuerpo_crudo, tu_secret) # Compara ese valor con el header X-ServiReports-Signature. # Ver ejemplos en Node / Python / PHP / Java en las otras pestanas.
report.createdEvento: report.created
Se dispara cuando un técnico folía (crea) un reporte. Es el evento estrella para automatizar: el reporte llega solo a tu sistema, con su referenceId incluido, listo para ligarlo a tu orden. Abajo, un receptor completo (verifica firma + procesa) en 5 lenguajes, y en la pestaña Respuesta exactamente lo que te enviamos:
# Un receptor de webhook es un endpoint HTTP en TU servidor. # No se implementa con curl. Elige tu lenguaje en las otras pestanas: # el patron es SIEMPRE: (1) leer cuerpo crudo, (2) verificar firma, # (3) responder 2xx rapido, (4) procesar de forma idempotente.
Responde 2xx para confirmar. Si tu endpoint falla, reintentamos; tras varios fallos seguidos el webhook se pausa solo (lo reactivas volviéndolo a registrar). Usa X-ServiReports-Delivery para no procesar dos veces el mismo aviso (idempotencia).
usage.thresholdEvento: usage.threshold
Se dispara cuando tu cuota diaria de descargas baja de 10%, para que tu sistema se prepare antes de quedarse sin descargas. El cuerpo trae { limit, used, remaining, window, resetsInSec }. Se verifica con la misma firma HMAC de arriba.
Códigos de error
Todos los errores, qué significan y qué hacer.
Los errores llegan con el código HTTP + un cuerpo { code, error }. Programa tu integración contra code (estable), no contra el texto (que puede cambiar).
| HTTP | code | Qué significa / qué hacer |
|---|---|---|
| 401 | API_KEY_INVALID | La llave falta, está mal formada o fue revocada. Revisa el header Authorization: Bearer. |
| 403 | API_SUBSCRIPTION_REQUIRED | Llave de producción sin suscripción activa. Activa o renueva la suscripción. |
| 429 | API_RATE_LIMITED | Cuota diaria de descargas agotada. Espera el Retry-After (segundos) y reintenta. |
| 404 | REPORT_NOT_FOUND | El folio no existe en tu organización. Verifica el folio. |
| 400 | VALIDATION_BAD_JSON | El cuerpo no es JSON válido (en PATCH o POST). Corrige el body. |
| 400 | VALIDATION_INVALID_URL | La url del webhook no es https o excede el largo permitido. |
| 400 | VALIDATION_INVALID_EVENT | Evento de webhook no soportado. Usa report.created o usage.threshold. |
| 409 | WEBHOOK_LIMIT_REACHED | Alcanzaste el máximo de webhooks por organización (10). Elimina alguno. |
| 404 | WEBHOOK_NOT_FOUND | El webhookId no existe o no es de tu organización. |
| 500 | INTERNAL_ERROR | Error temporal del servidor. Reintenta con backoff; si persiste, contacta a soporte. |
Eficiencia de uso
Ideas para que aproveches la API al máximo en tu servidor — menos llamadas, menos cuota, más automatización.
Esta sección no son reglas, son ideas de implementación: cómo montar la API del lado de tu servidor para que rinda al máximo. Combínalas todas y tu integración prácticamente se auto-mantiene.
Idea 1 · Recibe con webhooks, no consultes en bucle
En vez de preguntar cada rato “¿hay reportes nuevos?”, deja que nosotros te avisemos. Registras el webhook report.created UNA vez y cada reporte nuevo llega solo a tu servidor. Cero polling, cero cuota (los webhooks no cuestan).
Idea 2 · Mantén tu propio índice (espejo del nuestro)
Guarda en tu base de datos una copia de cada reporte que llega (por webhook) o del volcado inicial (con cursor). Así tienes tu propio índice, siempre actualizado, y no dependes de llamarnos para listar o filtrar.
# El volcado completo se hace en bucle (pagina por pagina). # Se implementa en tu lenguaje; el patron es: pedir 100, guardar, # tomar nextCursor, repetir hasta que venga vacio. Ver otras pestanas.
Idea 3 · Guarda los PDF en tu servidor (ahorra cuota)
La descarga de PDF es lo único que consume cuota. Cuando bajes un PDF, guárdalo en tu almacenamiento. Como un reporte foliado nunca cambia, ese PDF te sirve para siempre — no vuelvas a pedirlo.
Idea 4 · Consulta primero tu servidor (local-first)
Si ya implementaste tu índice local (idea 2) y tu cache de PDF (idea 3), haz que tu app consulte primero tu servidor y solo caiga a la API cuando falte algo. Con el tiempo, casi todo lo resuelves sin llamarnos: máxima velocidad, mínima cuota.
# Patron conceptual (se implementa en tu servidor, no con curl): # 1. Busca el reporte en TU base local. # 2. Si esta -> lo devuelves (0 llamadas, 0 cuota). # 3. Si NO esta -> lo pides a la API, lo guardas en tu base, y lo devuelves. # Con el tiempo casi todo lo resuelves localmente.
Idea 5 · El flujo completo (todo junto)
Uniendo las ideas anteriores: el webhook llena tu índice, ligas cada reporte por referenceId a tu orden, y el PDF se baja una sola vez bajo demanda y queda cacheado.
# Flujo recomendado (pseudo-pasos, cada paso en tu lenguaje): # 1. Registras UNA vez el webhook report.created. # 2. Cada reporte nuevo llega solo a tu /sr-hook -> lo guardas en tu ERP. # 3. Cuando un usuario abre la orden, bajas el PDF UNA vez y lo archivas. # Asi no consultas en bucle y solo gastas cuota cuando de verdad ves el PDF.
Recordatorios rápidos:
- Respeta
Retry-Afteren un429(espera creciente / backoff exponencial). - Revisa
/usageantes de una carga grande y actúa ante el webhookusage.threshold. - Verifica siempre la firma del webhook y procesa idempotente con
X-ServiReports-Delivery.
referenceId lista, y solo gastas cuota cuando alguien realmente necesita ver un PDF que aún no tienes. Mínimas llamadas, máxima automatización.