{"openapi":"3.1.0","info":{"title":"Zobraz e-faktúru API","description":"Render Peppol BIS Billing 3.0 invoices, credit notes, and self-billing documents to PDF. 100 renders/day free per account. Same renderer that powers epodatelna24.","version":"1.0.0","contact":{"name":"Zobraz e-faktúru","email":"info@epodatelna24.sk"},"license":{"name":"Service-specific terms","url":"https://www.zobrazfakturu.sk/developers"}},"servers":[{"url":"https://www.zobrazfakturu.sk","description":"Production"}],"security":[{"ApiKey":[],"ApiSecret":[]}],"tags":[{"name":"Render","description":"Render a Peppol BIS document to PDF."},{"name":"Audit","description":"Inspect render history."},{"name":"Status","description":"Liveness and dependency health."}],"components":{"securitySchemes":{"ApiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Public key half of the API key + secret pair."},"ApiSecret":{"type":"apiKey","in":"header","name":"X-API-Secret","description":"Secret half of the API key + secret pair."}},"parameters":{"XLanguage":{"name":"X-Language","in":"header","required":false,"schema":{"type":"string","enum":["sk","en"],"default":"sk"},"description":"Language for the rendered PDF labels."},"XDocumentId":{"name":"X-Document-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"When set, opts into Blob-upload mode: the PDF is uploaded to Vercel Blob at `peppol/rendered/<documentId>.pdf` and the response is JSON instead of PDF bytes. Same content (UBL + locale) is content-cached."},"XRequestId":{"name":"X-Request-Id","in":"header","required":false,"schema":{"type":"string"},"description":"Optional correlation ID. Echoed in the response; if absent the server generates one."}},"schemas":{"ValidationBlock":{"type":"object","required":["status","errors","warnings"],"properties":{"status":{"type":"string","enum":["valid","invalid","warning","unavailable"]},"errors":{"type":"integer","minimum":0},"warnings":{"type":"integer","minimum":0},"documentType":{"type":"string","description":"Detected Peppol document type (e.g. 'Invoice')."}}},"RenderJsonResponse":{"type":"object","required":["blobUrl","pathname","size","contentType","validation"],"properties":{"blobUrl":{"type":"string","format":"uri"},"pathname":{"type":"string","example":"peppol/rendered/<uuid>.pdf"},"size":{"type":"integer","minimum":0},"contentType":{"type":"string","example":"application/pdf"},"validation":{"$ref":"#/components/schemas/ValidationBlock"}}},"ErrorBody":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"code":{"type":"string"}}},"BatchInput":{"type":"object","required":["items"],"properties":{"items":{"type":"array","maxItems":100,"items":{"type":"object","required":["documentId","xml"],"properties":{"documentId":{"type":"string","format":"uuid"},"xml":{"type":"string","description":"Peppol BIS Billing 3.0 UBL XML body."},"locale":{"type":"string","enum":["sk","en"]}}}}}},"BatchOutput":{"type":"object","required":["requestId","totalRequested","totalSucceeded","items"],"properties":{"requestId":{"type":"string"},"totalRequested":{"type":"integer"},"totalSucceeded":{"type":"integer"},"items":{"type":"array","items":{"type":"object","required":["documentId","status"],"properties":{"documentId":{"type":"string","format":"uuid"},"status":{"type":"integer"},"blobUrl":{"type":"string","format":"uri"},"pathname":{"type":"string"},"size":{"type":"integer"},"contentType":{"type":"string"},"validation":{"$ref":"#/components/schemas/ValidationBlock"},"error":{"type":"string"},"code":{"type":"string"}}}}}},"RendersOutput":{"type":"object","required":["renders","pagination"],"properties":{"renders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"requestId":{"type":"string"},"ublHash":{"type":"string","description":"SHA-256 hex of the UBL body."},"documentType":{"type":"string"},"locale":{"type":"string","enum":["sk","en"]},"mode":{"type":"string","enum":["legacy","blob"]},"cacheStatus":{"type":"string","enum":["hit","miss"],"nullable":true},"responseCode":{"type":"integer"},"status":{"type":"string","enum":["ok","validation_failed","error"]},"errorCategory":{"type":"string","nullable":true},"responseTimeMs":{"type":"integer"},"outputBytes":{"type":"integer","nullable":true},"createdAt":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"nextCursor":{"type":"string","format":"date-time","nullable":true}}}}},"HealthOutput":{"type":"object","required":["status","version","timestamp","checks"],"properties":{"status":{"type":"string","enum":["ok","degraded"]},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"checks":{"type":"object","properties":{"db":{"type":"string","enum":["ok","degraded","unavailable","unconfigured"]},"validator":{"type":"string","enum":["ok","degraded","unavailable","unconfigured"]},"blob":{"type":"string","enum":["ok","degraded","unavailable","unconfigured"]}}}}}}},"paths":{"/api/v1/render":{"post":{"tags":["Render"],"summary":"Render a Peppol BIS XML invoice to PDF","description":"Default mode returns PDF bytes (Content-Type: application/pdf) with metadata in X-Peppol-* headers. When X-Document-Id is set, the PDF is uploaded to Vercel Blob and the response is a JSON descriptor. Repeat renders of the same (locale, xml) are content-cached when X-Document-Id is set.","parameters":[{"$ref":"#/components/parameters/XLanguage"},{"$ref":"#/components/parameters/XDocumentId"},{"$ref":"#/components/parameters/XRequestId"}],"requestBody":{"required":true,"content":{"application/xml":{"schema":{"type":"string"}},"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]}}}},"responses":{"200":{"description":"Success","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"$ref":"#/components/schemas/RenderJsonResponse"}}},"headers":{"X-Request-Id":{"schema":{"type":"string"}},"X-Peppol-Document-Type":{"schema":{"type":"string"}},"X-Peppol-Validator-Status":{"schema":{"type":"string","enum":["ok","failed","unavailable"]}},"X-Peppol-Errors":{"schema":{"type":"integer"}},"X-Peppol-Warnings":{"schema":{"type":"integer"}},"X-Peppol-Lines":{"schema":{"type":"integer"}},"X-Cache":{"description":"Present in Blob mode only.","schema":{"type":"string","enum":["HIT","MISS"]}}}},"400":{"description":"Bad XML, XXE rejection, or invalid X-Document-Id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"Quota exceeded"},"413":{"description":"Body larger than max_body_bytes"},"422":{"description":"LINE_LIMIT_EXCEEDED or BLOB_UPLOAD_FAILED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Rate limit (100/min per key)"},"500":{"description":"BLOB_NOT_CONFIGURED on the server"},"502":{"description":"RENDER_FAILED or OUTPUT_SIZE_ANOMALY","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}}}},"/api/v1/render/batch":{"post":{"tags":["Render"],"summary":"Render up to 100 invoices in one call","description":"All items are rendered in Blob mode. Individual item failures do not fail the batch — inspect items[i].status to decide retry.","parameters":[{"$ref":"#/components/parameters/XLanguage"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchInput"}}}},"responses":{"200":{"description":"Per-item results (some items may have failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchOutput"}}}},"400":{"description":"INVALID_BODY / MISSING_ITEMS / EMPTY_BATCH / BATCH_TOO_LARGE / per-item field validation"},"401":{"description":"Missing or invalid credentials"},"403":{"description":"BATCH_QUOTA_EXCEEDED — whole batch would exceed max_usage"},"429":{"description":"Rate limit (100/min per key)"}}}},"/api/v1/renders":{"get":{"tags":["Audit"],"summary":"List recent renders for this API key","description":"Returns up to `limit` rows (max 200, default 50), most recent first. Default window is the last 30 days.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","schema":{"type":"string","format":"date-time"},"description":"ISO timestamp; returns rows older than the cursor (for pagination)."},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"ISO timestamp; returns rows on or after."}],"responses":{"200":{"description":"Render history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RendersOutput"}}}},"401":{"description":"Missing or invalid credentials"},"403":{"description":"API_KEY_REQUIRED — cookie session callers"}}}},"/api/v1/health":{"get":{"tags":["Status"],"summary":"DB / validator / Blob dependency status","description":"Default returns 200 always; the body's `status` field is the truth. Append `?strict=true` to get 503 when degraded (for uptime monitors).","security":[],"parameters":[{"name":"strict","in":"query","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"All checks ok, or non-strict mode","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthOutput"}}}},"503":{"description":"Strict mode + at least one dependency degraded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthOutput"}}}}}}},"/api/v1/ping":{"get":{"tags":["Status"],"summary":"Minimal liveness probe","description":"Returns 200 OK + body `ok` (text/plain) as long as the serverless function is responding. No dependency probes. Designed for UptimeRobot HTTP(S) monitors.","security":[],"responses":{"200":{"description":"Alive","content":{"text/plain":{"schema":{"type":"string","example":"ok"}}}}}},"head":{"tags":["Status"],"summary":"Liveness probe — HEAD variant","description":"Same as GET but with no body.","security":[],"responses":{"200":{"description":"Alive"}}}}}}