Preflight & Shared Reports API
The Preflight API provides programmatic access to technical PDF inspection, production fact extraction, geometry box enforcement (TrimBox, BleedBox), automatic corrections, and sanitized customer-facing diagnostic reports.
- Core Inspection Engine: Executed by
ppos-preflight-service(listening on port 8001) and proxied through the Control Plane at/api/preflight/*. - Shared Diagnostic Link: Implemented at
src/api/routes/publicPreflight.js:6under/api/public/preflight/human-report/:token. - Customer Action Remediation: Implemented at
src/api/routes/marketplacePublic.js:125under/api/marketplace/orders/:orderId/customer-action/:token.
1. Capabilities Discovery (GET /api/preflight/capabilities)
Public endpoint returning active validation rules, supported trim geometry policies, and upload limits.
curl -X GET "https://api.printprice.pro/api/preflight/capabilities"
Response (200 OK)
{
"supportedRules": [
"GEOMETRY_TRIMBOX_VALIDATION",
"BLEED_3MM_ENFORCEMENT",
"IMAGE_RESOLUTION_300DPI",
"COLOR_CMYK_ONLY",
"FONTS_EMBEDDED_CHECK"
],
"availableFixes": [
"NORMALIZE_PAGE_BOXES",
"GENERATE_SYNTHETIC_BLEED",
"RGB_TO_FOGRA39_CONVERSION"
],
"geometryPolicies": [
"ISO_216_A_SERIES",
"STANDARD_BOOK_SIZES"
],
"maxUploadSizeBytes": 2147483648
}
2. Submit PDF for Inspection (POST /api/preflight/jobs)
Uploads a PDF file (up to 2GB) using multipart/form-data and triggers asynchronous worker analysis.
Request (curl)
curl -X POST "https://api.printprice.pro/api/preflight/jobs" \
-H "Authorization: Bearer YOUR_PARTNER_TOKEN" \
-F "file=@/path/to/manuscrito_interior.pdf"
Response (200 OK)
{
"ok": true,
"jobId": "pf_job_8a7d6e5c-1234",
"status": "QUEUED",
"filename": "manuscrito_interior.pdf",
"sizeBytes": 15420310
}
3. Retrieve Preflight Findings (GET /api/preflight/jobs/:id)
Queries the technical analysis report and generated artifacts for a job.
curl -X GET "https://api.printprice.pro/api/preflight/jobs/pf_job_8a7d6e5c-1234" \
-H "Authorization: Bearer YOUR_PARTNER_TOKEN"
Response (200 OK)
{
"ok": true,
"job": {
"id": "pf_job_8a7d6e5c-1234",
"status": "COMPLETED",
"outcome": "PASSED_WITH_WARNINGS",
"filename": "manuscrito_interior.pdf",
"report": {
"pageCount": 192,
"trimBox": { "widthMm": 148, "heightMm": 210 },
"bleedBox": { "widthMm": 154, "heightMm": 216, "bleedMm": 3 },
"colorProfile": "FOGRA39 (ISO 12647-2)",
"lowestImageDpi": 240,
"findings": [
{
"code": "IMAGE_DPI_SUBOPTIMAL",
"severity": "warning",
"page": 45,
"message": "Imagen en página 45 cuenta con 240 DPI (mínimo recomendado: 300 DPI)."
}
]
},
"artifacts": [
{ "id": "art_rep_01", "type": "report_json", "name": "report.json" },
{ "id": "art_norm_pdf", "type": "normalized_pdf", "name": "normalized.pdf" }
]
}
}
4. Trigger Automatic Corrections (POST /api/preflight/jobs/:id/actions/fix)
Executes automated page box normalization, synthetic bleed generation, or color space conversion:
curl -X POST "https://api.printprice.pro/api/preflight/jobs/pf_job_8a7d6e5c-1234/actions/fix" \
-H "Authorization: Bearer YOUR_PARTNER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"autoFixOptions": {
"normalizeBoxes": true,
"generateBleed": true,
"convertRgbToCmyk": true
}
}'
5. Download Inspection Artifacts (GET /api/preflight/jobs/:id/artifacts/:artifactId)
Streams the binary file (normalized PDF or structured JSON report):
curl -X GET "https://api.printprice.pro/api/preflight/jobs/pf_job_8a7d6e5c-1234/artifacts/art_norm_pdf" \
-H "Authorization: Bearer YOUR_PARTNER_TOKEN" \
--output normalized.pdf
6. Shared Preflight Human Report (GET /api/public/preflight/human-report/:token)
Allows print houses to share a customer-safe, visual diagnostic of an uploaded PDF without exposing internal server paths or operational logs.
Authentication & Token Validation
- Token Format: Signed JWT in path parameter (
:token). - Required Scope: Must be signed with
HUMAN_REPORT_VIEW. - Database Isolation: Enforces multitenant boundary matching
tenant_id,job_id, andid.
Response (200 OK)
{
"ok": true,
"job_id": "pf_job_8a7d6e5c-1234",
"snapshot_id": "snap_998877",
"tenant_id": "tenant_default",
"report": {
"outcome": "FIXED_REVIEW_REQUIRED",
"summary": {
"title": "Informe de Verificación de Archivos",
"description": "Se detectaron advertencias que requieren confirmación visual.",
"pages_analyzed": 192,
"color_space": "CMYK (FOGRA39)"
},
"artifact_recommendations": [
{
"artifact_id": "art_visual_diff_01",
"artifact_type": "VISUAL_DIFF_PAGE_12",
"label": "Comparativa de corrección en página 12 (resolución de imagen)",
"customer_visible": true,
"download_url": "/api/public/preflight/artifacts/art_visual_diff_01?token=..."
}
],
"customer_actions": [
{
"action_id": "review_required",
"label": "Revisión requerida antes de imprimir",
"description": "El archivo corregido debe ser aprobado antes de enviar a planchas.",
"severity": "warning"
}
]
}
}
In the current implementation (publicPreflight.js:12), missing snapshots (SNAPSHOT_NOT_FOUND) return HTTP 400 because the service does not assign a custom statusCode before evaluating result.statusCode || 400. Returning HTTP 404 represents a target contract proposal ([PROPUESTA DEV-02]).
7. Customer Action Remediation Link (GET /api/marketplace/orders/:orderId/customer-action/:token)
When preflight detects blocking errors that require the client to supply new files, a time-limited customer remediation token is dispatched.
Security & Lifecycle Details
- Hash Verification: The server computes
SHA-256(token)and matches it using string inequality!==againsttokenHashinmarketplaceCustomerActionService.js:522. Constant-time comparison (crypto.timingSafeEqual) is a recommended future hardening. - Expiration Enforcement: Validates
expiresAt. Expired links returnHTTP 410 Gone. - Execution Sequence & State: The endpoint returns
validation.actionas read from the database upon token validation. The initial state assigned upon action creation inmarketplaceCustomerActionService.js:165isPENDING_NOTIFICATION. The controller executesawait customerActionService.markCustomerActionViewed(orderId, token)before sending the HTTP response. This update is awaited, but wrapped within a non-fataltry/catchblock so that database persistence failures do not block the customer from receiving the remediation instructions. Therefore, on the initial request,statusis"PENDING_NOTIFICATION"(the state read at validation time). If the subsequent update in the database fails,VIEWEDis not persisted and subsequent queries cannot guarantee"VIEWED".
Response (200 OK — Initial Request)
{
"success": true,
"orderId": "ord_9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"action": {
"type": "FILE_REUPLOAD_REQUIRED",
"status": "PENDING_NOTIFICATION",
"requiredFiles": ["INTERIOR_PDF"],
"blockers": ["LOW_IMAGE_DPI_PAGE_45"],
"message": "Por favor, sustituya el PDF interior con imágenes a 300 DPI.",
"expiresAt": "2026-11-01T23:59:59.000Z",
"createdAt": "2026-10-25T14:00:00.000Z"
},
"currentFiles": [
{
"file_id": "fil_int_01",
"role": "INTERIOR_PDF",
"status": "REJECTED",
"preflight_status": "FAILED",
"preflight_outcome_category": "REJECTED_RESOLUTION",
"findings_count": 3,
"version": 1
}
],
"trace_id": "trace_99887766"
}
8. Contract Specifications
Download the formal OpenAPI 3.1 specifications for this domain: