Integration
External API V1 Documentation
Technical documentation package for partner IT review and feedback. This page summarizes the externally exposed API contract and rollout constraints.
Overview
The API accepts multipart uploads, returns JSON responses, and uses standard HTTP status codes and Bearer authentication. Submit a PDF invoice, wait for asynchronous processing, and then fetch the generated result.
Send a PDF invoice to a single endpoint and Invoice-Converter handles extraction, validation, and output generation. The result endpoint returns the generated file only after validation gates pass; otherwise it returns 422 VALIDATION_FAILED. Public operational endpoints are intentionally minimal and do not expose internal service topology.
Base path: /api/v1. Last synchronized 2026-04-11.
Key capabilities
- Single endpoint for PDF-to-XML conversion
- AI-powered invoice data extraction
- Automated EN 16931 and KoSIT validation
- XRechnung, ZUGFeRD, UBL, and CII output formats
- Async processing with polling - results in 5-15 seconds
- Idempotent writes for safe retries
Delivery Artifacts
Download machine-readable integration artifacts for the Developer API.
Quickstart
Three API calls complete a conversion. The convert endpoint is served at /api/v1 and requires authentication.
POST /api/v1/invoices:convert
liveConvert PDF to structured e-invoice
GET /api/v1/tasks/{task_id}
livePoll task status
GET /api/v1/tasks/{task_id}/result
liveDownload conversion result
Required request headers
- Authorization: Bearer <api_key>
Auth rules
Use your API key as a Bearer token. Keys are provisioned in your account settings under Profile → API keys.
- Keys are tenant-scoped and environment-scoped (`live` / `test`). Key prefix determines environment.
- Provision or rotate keys under `Profile` → `API keys` in your account, or contact support.
- Missing or invalid key returns `401`.
- Calls via the website proxy (`/api/v1`) receive an `X-Correlation-ID` automatically when omitted.
- Write calls require `Idempotency-Key`; keep this value stable across retries.
- Use server-to-server integration from your backend. Browser-origin access is restricted in production.
Idempotency contract
- Send an `Idempotency-Key` on every write call.
- Idempotency keys must match `[A-Za-z0-9._:-]+` and be at most 200 chars.
- If you provide your own key, the same key + identical payload returns the cached response.
- Same key + different payload returns `409 IDEMPOTENCY_CONFLICT`.
- Idempotency keys expire after `24 hours`.
Endpoint Reference
All endpoints are served through the website proxy at /api/v1. Upstream timeouts surface as 504 and other proxy connectivity failures as 502; correlation IDs propagate end-to-end for traceability. Trusted-host and origin controls are enforced in production deployments.
POST /api/v1/invoices:convert
liveUpload a PDF invoice and start asynchronous conversion. Returns a task_id for polling. Request: multipart/form-data. Response: 202 Accepted.
GET /api/v1/tasks/{task_id}
livePoll the current status of a conversion task. Returns pending, processing, completed, or failed. When failed, the response includes an error field with the failure reason. Request: none (GET). Response: 200 OK.
GET /api/v1/tasks/{task_id}/result
liveDownload the generated file (XML or PDF). Result syntax matches the original task format: XRECHNUNG/EN16931/UBL return UBL XML, CII/ZUGFERD return CII XML, and ZUGFERD + download=pdf returns a hybrid PDF/A-3. Repeated downloads may be served from cached generated artifacts. If blocking validation issues remain, this endpoint returns 422 VALIDATION_FAILED and no file body. Request: none (GET). Response: 200 OK.
Output format matrix
| Format | Syntax | Version / Profile | Content-Type | Extension |
|---|---|---|---|---|
| XRECHNUNG | UBL 2.1 XML | XRechnung 3.0.2 | application/xml | .xml |
| ZUGFERD | CII XML (download=xml) / hybrid PDF/A-3 (download=pdf) | ZUGFeRD 2.4 / Factur-X 1.08 | application/xml or application/pdf | .xml / .pdf |
| EN16931 | UBL 2.1 XML | EN 16931 | application/xml | .xml |
| UBL | UBL 2.1 XML | OASIS UBL 2.1 | application/xml | .xml |
| CII | UN/CEFACT CII XML | D16B | application/xml | .xml |
Changelog
Recent externally visible API changes.
2026-03-06
Made task-result downloads format-faithful for CII and ZUGFERD outputs. Added cached result artifact reuse for repeated XML/PDF downloads of the same task. Aligned polling quotas with endpoint-scoped weighted rate-limit buckets.
2026-02-23
Added clearer, consistent API error responses across all endpoints. Expanded convert options and documented XML/PDF download behavior for task results. Improved retry safety with stricter idempotency requirements and validation. Updated OpenAPI/Postman artifacts to match current API behavior.
2026-02-20
Simplified public health endpoint responses to status-focused output. Strengthened IndexNow submission validation and authentication checks. Hardened API access controls and request-limiting behavior in production.
Error Contract
| Code | HTTP | Retryable | Notes |
|---|---|---|---|
| AUTHENTICATION_REQUIRED | 401 | No | Missing/empty bearer token |
| INVALID_API_KEY | 401 | No | API key not found/revoked/expired |
| IDEMPOTENCY_KEY_REQUIRED | 400 | No | Write endpoint called without Idempotency-Key |
| INVALID_IDEMPOTENCY_KEY | 400 | No | Idempotency key has invalid format |
| IDEMPOTENCY_CONFLICT | 409 | No | Same key used with different request hash |
| IDEMPOTENCY_IN_PROGRESS | 409 | Yes | Safe to retry later with same key/payload |
| AUTH_SERVICE_UNAVAILABLE | 503 | Yes | Auth backend unavailable |
| RATE_LIMIT_SERVICE_UNAVAILABLE | 503 | Yes | Rate-limit backend unavailable |
| RATE_LIMITED | 429 | Yes | Respect Retry-After and quota headers |
| BAD_REQUEST | 400 | No | Invalid JSON or invalid UUID path parameter |
| PAYLOAD_TOO_LARGE | 413 | No | Over upload size limit |
| INVALID_UPLOAD | 400 | No | Upload read/parsing failure |
| UPLOAD_FAILED | 4xx/5xx | Conditional | Retry only for transient 5xx cases |
| TASK_NOT_READY | 202 | Yes | Poll again for async completion |
| TASK_STATUS_FAILED | 4xx/5xx | Conditional | Retry if transient upstream/backend condition |
| TASK_RESULT_FAILED | 4xx/5xx | Conditional | Retry if transient upstream/backend condition |
| XML_GENERATION_FAILED | 500 | Yes | Transient XML generation failure or timeout |
| PDF_GENERATION_FAILED | 500 | Yes | Transient PDF generation failure or timeout |
| OUTPUT_PROFILE_REQUIRED | 422 | No | Explicit profile missing for a generic syntax format such as UBL or CII |
| OUTPUT_PROFILE_CONFLICT | 422 | No | Profile contradicts the selected output format or explicit variant |
| PROXY_ERROR | 502/504 | Yes | Proxy/upstream failure (504 for timeout) |
Rate & payload limits
Per-key rate limits and payload size constraints are enforced at the proxy layer. Denied requests do not consume quota. Proxy-header trust is fail-closed by default unless explicitly enabled for trusted infrastructure.
- Endpoint-aware quotas are cost-weighted. Convert uses the baseline plan quota (default `30/min` and `500/hour`), while polling endpoints use lower weighted quotas.
- Read effective limits from `X-RateLimit-Limit-Minute` and `X-RateLimit-Limit-Hour` on responses.
- PDF upload max size: `20 MB`
- JSON payload max size: `1 MB`
- Rate-limit responses include `Retry-After`, `X-RateLimit-Limit-Minute`, and `X-RateLimit-Limit-Hour`.
Retry guidance
- Use exponential backoff with jitter.
- Retry only transient classes (`429`, `500`, `502`, `503`, `504`) using the same payload and idempotency key where possible.
- Do not blindly retry validation or contract errors (`400`, `401`, `403`, `409`, `413`).
Task lifecycle & retention
- Completed and failed tasks remain available for `10 minutes` after reaching terminal state.
- Processing times out after `5 minutes` — stuck tasks are automatically marked `failed`.
- Idempotency keys expire after `24 hours`.
- Rate-limit counters reset on a rolling window.
Support model
- Business-hours support.
- Target first response: 1 business day.
Send Technical Feedback
Share implementation questions, risks, and required contract changes with our team.