Comprobar y ensayar sin escribir
Referencia de check-request, que dice si una petición pasaría sin ejecutarla, y de la prueba activa, que lee con cada permiso sin devolver datos.
Actualizado el . 6 min de lectura
Incluido en todos los planes. Ver precios
Dos rutas para probar sin escribir datos: check-request razona sobre una petición sin llamar a la ruta, y la prueba activa (run) lee de verdad con cada permiso, sin devolver nada. Las dos se llaman con la clave de la aplicación en X-Api-Key y sin permisos de la API. El resto del diagnóstico está en Rutas del diagnóstico.
Dos formas de probar sin escribir
Razona
check-request
Prueba
Prueba activa
Comprobar una petición sin ejecutarla
check-request responde a «¿pasaría esta petición?» sin llamar a la ruta: no lee ni escribe nada, y el cuerpo no se guarda ni se registra. Dice cada fallo con el mismo errorCode que daría la llamada real. Un ejemplo con los SDK está en Probar tu integración.
/api/external/v1/diagnostics/check-requestDice si una petición a la API pública pasaría y, si no, por qué, sin llamar a la ruta. Siempre 200 con el resultado; 400 solo con una entrada mal formada. Sin permisos de la API.
- methodstringobligatorio
- GET, POST, PUT, PATCH o DELETE.
- pathstringobligatorio
- La ruta concreta (/external/v1/invoices/abc) o su plantilla (/external/v1/invoices/:id), con o sin /api delante y con o sin el dominio. Hasta 2.048 caracteres. Si lleva ?consulta, se comprueba junto a query.
- queryobjeto
- Los parámetros de la consulta, como los mandaría tu programa. Hasta 100 parámetros y 16 KB.
- bodyJSON
- El cuerpo, tal cual lo mandaría tu programa. Hasta 256 KB y 32 niveles de anidamiento. No se guarda ni se registra.
Fuera de esos topes la respuesta es 400 VALIDATION_ERROR, y también si la petición entera a check-request pasa de 300 KB: se corta antes de leerla. En los SDK, checkRequest({ method, path, query?, body? }) y check_request(method, path, query=..., body=...).
Qué comprueba
checks trae una comprobación por cada cosa que mira la llamada real: route (la ruta existe en la API pública), app, responsible, plan, capability (también «Próximamente»), scope, billing, query y body. Cada una sale pass, fail, warn o skip, con su mensaje y, si falla, su errorCode. Se evalúan todas, aunque la llamada real se pararía en la primera que falla, para que veas de una vez lo que falta.
scopesalewarnsi el permiso que falta está en transición y la llamada real todavía pasaría con un aviso. Los permisos críticos, de datos personales y financieros, no tienen transición: si falta uno, salefail.appsalefailconDIAGNOSTICS_NOT_AVAILABLE_FOR_PUBLISHABLE_KEYsi compruebas, con una clave publicada en una web, una de las cuatro rutas de diagnóstico que esa clave no puede llamar.scopesalefailconSCOPE_NOT_ALLOWED_FROM_BROWSERsi la ruta exige un permiso que no se usa desde una página y la llamada se rechazaría: porque la comprobación llega desde un navegador o porque UTILIA OS ya lo exige también desde los servidores. Con una clave publicada que hoy solo se rechazaría desde el navegador, salewarncon el mismo código. Ver Claves dentro de una página web.
Dónde se pararía
nextStep no propone la primera de la lista, sino la primera en la que se pararía la llamada real. Ese orden no es el de checks: el plan va antes que el permiso, y la consulta y el cuerpo también, así que un cuerpo que no valida da 400 antes que el 403 de un permiso que falta.
Dónde se pararía la llamada real
La clave y la aplicación
app y responsible y, con una clave publicada en una web, el permiso que no se usa desde una página.Si no: 401 o 403 de la clave, la aplicación o su responsable.
El plan
plan y capability.Si no: 403 MODULE_NOT_ENABLED, CAPABILITY_NOT_ENABLED o FEATURE_COMING_SOON.
La cuenta de la organización
Solo en las rutas que crean o cambian datos.Si no: 403 TENANT_SUSPENDED o TENANT_CANCELLED.
La consulta y el cuerpo
query y body, contra la definición real de la ruta.Si no: 400 VALIDATION_ERROR, antes que cualquier permiso.
El permiso de la API
scope. Aquí se paran también las pruebas que una clave publicada en una web no puede lanzar.Si no: 403 INSUFFICIENT_SCOPE, con el permiso en missing.
La facturación y el responsable
billing y, en las rutas que lo miran, el permiso de la persona responsable.Si no: 403 BILLING_NOT_ENABLED o APP_RESPONSIBLE_PERMISSION_DENIED.
El ejemplo, recortado, es una factura con un permiso que falta, una línea sin taxType y un campo mal escrito. Fallan el permiso y el cuerpo, y nextStep propone el cuerpo, porque la llamada real respondería 400 antes de mirar el permiso:
{
"matched": true,
"route": {
"id": "POST /external/v1/invoices",
"method": "POST",
"path": "/external/v1/invoices",
"resource": "invoices",
"summary": "Crear y emitir una factura",
"sideEffect": "irreversible"
},
"wouldPass": false,
"checks": [
{ "key": "route", "status": "pass", "message": "Ruta pública: Crear y emitir una factura" },
{ "key": "scope", "status": "fail", "errorCode": "INSUFFICIENT_SCOPE", "message": "A la aplicación le falta el permiso de la API «Emitir facturas» (crm:invoices:issue). Lo concede un administrador de la organización en UTILIA OS, en la ficha de la aplicación, Configuración › Ajustes › Permisos.", "missing": ["crm:invoices:issue"] },
{ "key": "body", "status": "fail", "errorCode": "VALIDATION_ERROR", "message": "Falta el campo obligatorio `lines[0].taxType`.", "missing": ["lines[0].taxType"] }
],
"validation": {
"errors": [{ "path": "lines[0].taxType", "message": "Falta este campo obligatorio.", "constraint": "isDefined" }],
"ignoredFields": ["lines[0].precio"],
"missingRequired": ["lines[0].taxType"]
},
"nextStep": {
"text": "Arregla primero esto: falta el campo obligatorio `lines[0].taxType`.",
"docsUrl": "https://os.utilia.ai/docs/developers/getting-started/errors-and-retries#validation_error"
}
}Campos ignorados y rutas que no existen
ignoredFields son los campos que la llamada real descartaría sin error: casi siempre un nombre mal escrito, como precio en vez de unitPrice. Es lo mismo que te diría después la cabecera X-Utilia-Ignored-Fields, pero antes de enviar nada. Si el cuerpo no tiene otros errores, body sale warn y los nombra en su mensaje. Cuando todo pasa, nextStep propone el ensayo en seco de la ruta si lo tiene (en una factura, POST /external/v1/invoices/validate) o avisa de que la llamada tiene efectos.
Una ruta que no es de la API pública, también si existe en UTILIA OS, responde matched: false igual que una que no existe, con hasta tres rutas públicas parecidas en suggestions. Para saber todo lo que puedes llamar, pide el contrato de tu clave.
Prueba activa de solo lectura
/api/external/v1/diagnostics/runPor cada permiso de lectura concedido, hace la lectura mínima de su ruta y dice si funciona, sin devolver datos. Si la aplicación factura, valida en seco una factura de ejemplo. Hasta 6 por minuto. Sin permisos de la API.
Donde check-request razona, run prueba: llama de verdad a cada ruta de lectura, como tu aplicación y dentro de tu organización, y devuelve solo pass, fail (con el errorCode que daría la ruta) o skip (con el motivo: fuera de plan, sin ruta de lectura sin identificador...). Nunca devuelve el contenido. Cada lectura espera 10 segundos como mucho.
{
"runAt": "2026-10-21T10:00:00.000Z",
"durationMs": 840,
"summary": { "passed": 2, "failed": 0, "skipped": 1 },
"probes": [
{ "id": "invoices.list", "resource": "invoices", "label": "Leer facturas", "scope": "crm:invoices:read", "route": "GET /external/v1/invoices", "status": "pass", "message": "La lectura funciona con este permiso.", "durationMs": 210 }
],
"invoiceDryRun": {
"status": "fail",
"message": "La factura de ejemplo no se podría emitir ahora mismo: revisa los bloqueos.",
"blockers": [{ "code": "BILLING_NOT_ENABLED", "message": "La facturación de esta aplicación está desactivada, así que todavía no puede emitir facturas. La activa un Super Administrador de la organización en UTILIA OS, en la ficha de la aplicación, Dinero › Facturación («Activar la facturación»)." }],
"warnings": []
},
"writeScopesNotProbed": [
"Emitir facturas (crm:invoices:issue): no se prueba escribiendo. Compruébalo sin efectos con POST /external/v1/invoices/validate."
]
}- Las escrituras no se prueban escribiendo:
writeScopesNotProbeddice cómo comprobar cada una sin efectos. - Una factura:
runya valida una de ejemplo, pero con tu cuerpo real es como sabrás si la tuya pasa. Las tres rutas que calculan sin emitir (POST /external/v1/invoices/validate,POST /external/v1/invoices/validate/pdfyPOST /external/v1/invoices/:id/rectifications/validate) están en Probar la facturación sin emitir facturas. - El resultado se reutiliza 60 segundos, salvo que cambie la configuración de la aplicación: un permiso concedido o la facturación activada dan un resultado nuevo en el acto.
- No cuenta como llamadas de tu aplicación: las lecturas quedan en el registro de acceso a datos de la organización como hechas por tu aplicación, pero no aparecen en las llamadas rechazadas, no cambian su salud ni marcan pasos del recorrido.
- Con la organización suspendida o de baja sigue respondiendo, porque no escribe nada. Si el contador de su cupo no responde,
503 DIAGNOSTICS_UNAVAILABLE. Con una clave publicada en una web,403 DIAGNOSTICS_NOT_AVAILABLE_FOR_PUBLISHABLE_KEYantes de gastar ningún cupo: lánzala desde la pestaña Pruebas.
Si algo falla
400 VALIDATION_ERRORencheck-request: la entrada está mal formada, pasa de los topes de la tabla de campos o la petición entera pasa de 300 KB. Si lo que no valida es la petición que compruebas, la respuesta es200, con el fallo dentro.matched: false: la ruta no es de la API pública. Mirasuggestionso el contrato de tu clave.429 DIAGNOSTICS_RATE_LIMITEDen la prueba activa: pasaste de 6 al minuto. Espera lo que digaRetry-After.503 DIAGNOSTICS_UNAVAILABLEen la prueba activa: el contador de su cupo no responde y no se lanza sin contarla. Repite en unos minutos.403 DIAGNOSTICS_NOT_AVAILABLE_FOR_PUBLISHABLE_KEYen la prueba activa: la clave está publicada en una web. Lánzala desde la pestaña Pruebas del panel;check-requestsí funciona con esa clave.