{"openapi":"3.0.3","info":{"title":"ePostak Enterprise API","description":"Enterprise REST API pre e-fakturaciu cez Peppol. OAuth 2.0 JWT auth (vymeňte `sk_live_*`/`sk_int_*` API kľúč za 15 min JWT cez `POST /api/v1/auth/token`). JSON aj XML mode, multi-tenant, idempotency support, OCR, webhooks, contract-term AS4 envelope archive.\n\nDocs: https://epostak.sk/api/docs/enterprise","version":"1.5.1","contact":{"email":"info@epostak.sk","url":"https://epostak.sk"}},"servers":[{"url":"https://epostak.sk/api/v1","description":"Production"}],"tags":[{"name":"Connector","description":"Fast ERP connection through a managed flow over the Enterprise API. Connector V2 uses Connector Mailbox setup, customerRef routing, /connector/mapper for saved ERP export mappings, /connector/zen-input for tolerant ERP JSON intake, /connector/autopilot for exact document intake, /connector/sync for one unified feed, and document lifecycle/evidence endpoints. Webhooks and Events pull remain available as the advanced Enterprise layer; the full Enterprise API remains available when more control is needed."},{"name":"Box","description":"ePošťák Box durable execution layer for staged, scheduled and retryable Peppol dispatch. No public RabbitMQ/Kafka API in v1."},{"name":"Documents","description":"Odosielanie dokumentov cez Peppol"},{"name":"Inbox","description":"Prijate dokumenty"},{"name":"Account","description":"Informacie o ucte a firme"},{"name":"Extraction","description":"OCR extrakcia faktur z PDF/obrazkov (Enterprise only)"},{"name":"Webhooks","description":"Push webhook subscriptions and Events pull subscriptions (Enterprise only). Prefer /events/pull for pull-based event handling; webhook-queue paths remain compatibility endpoints."},{"name":"Firms","description":"Sprava firiem a Peppol identifikatorov"},{"name":"Peppol","description":"SMP lookup a Peppol directory"},{"name":"Reporting","description":"Statistiky a reporty"},{"name":"OAuth","description":"OAuth 2.0 token exchange"},{"name":"Auth","description":"API key introspection and rotation"},{"name":"Validation","description":"Public UBL/Peppol validator (no auth)"},{"name":"Payload Assistant","description":"Payload creation, OCR extraction, parse, convert and validation helpers for integrators. Legacy Extraction/Documents paths remain supported."},{"name":"Webhooks & Events","description":"Push webhooks and Events pull facade endpoints for reliable ERP delivery. Legacy webhook-queue paths remain supported as compatibility endpoints."},{"name":"Lifecycle & proof","description":"Document status, timeline, responses and support/evidence packets for audit and dispute workflows."}],"security":[{"bearerAuth":[]}],"paths":{"/box/items":{"get":{"tags":["Box"],"summary":"List ePošťák Box items","description":"Lists durable Box items for the authenticated firm from the dedicated Box model. Box is not a Connector outbox alias; REST, Connector and Dashboard flows attach to it as a shared reliability layer.","operationId":"boxListItems","responses":{"200":{"description":"OK"}}},"post":{"tags":["Box"],"summary":"Create ePošťák Box item","description":"Stages a document into ePošťák Box for durable, scheduled and retryable Peppol dispatch.","operationId":"boxCreateItem","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["payloadXml"],"properties":{"payloadXml":{"type":"string","description":"UBL XML payload to stage in encrypted Box storage."},"scheduledFor":{"type":"string","format":"date-time","description":"Optional future dispatch time."},"externalId":{"type":"string","description":"Optional caller-side id for idempotency and lookup."},"metadata":{"type":"object","additionalProperties":true}}}}}},"responses":{"201":{"description":"Created"}}}},"/box/items/{itemId}":{"get":{"tags":["Box"],"summary":"Get ePošťák Box item detail","description":"Returns status, safe storage summary, dispatch attempts and audit timeline without plaintext invoice payloads or attachments.","operationId":"boxGetItem","parameters":[{"name":"itemId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"},"404":{"description":"Not found"}}}},"/box/items/{itemId}/schedule":{"post":{"tags":["Box"],"summary":"Schedule a Box item","operationId":"boxScheduleItem","parameters":[{"name":"itemId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["scheduledFor"],"properties":{"scheduledFor":{"type":"string","format":"date-time","description":"Future dispatch time."}}}}}},"responses":{"200":{"description":"OK"}}}},"/box/items/{itemId}/send-now":{"post":{"tags":["Box"],"summary":"Send a Box item now","description":"Attempts dispatch for an outbound Box item when a Connector/Enterprise dispatch pointer is available. Returns 409 when the item cannot be dispatched by this route.","operationId":"boxSendNow","parameters":[{"name":"itemId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Dispatch attempted"},"409":{"description":"Dispatch pointer unavailable"}}}},"/box/items/{itemId}/retry":{"post":{"tags":["Box"],"summary":"Retry a Box item","description":"Moves a failed or repairable outbound Box item back into the retry flow and records an audit event.","operationId":"boxRetryItem","parameters":[{"name":"itemId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}}},"/box/items/{itemId}/cancel":{"post":{"tags":["Box"],"summary":"Cancel a Box item","description":"Cancels an unsent outbound Box item. Sent or received archive items are retained by retention policy.","operationId":"boxCancelItem","parameters":[{"name":"itemId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"OK"}}}},"/auth/token":{"post":{"tags":["Auth"],"summary":"Mint a JWT access token (OAuth 2.0 client_credentials)","description":"Exchange a `sk_live_*` or `sk_int_*` API key for a short-lived JWT access token + refresh token.\n\n**Body** (JSON or `application/x-www-form-urlencoded`):\n- `grant_type`: must be `client_credentials`\n- `client_id`: the client_id shown with the key; it must match the API key row UUID or displayed key prefix and must not be the secret\n- `client_secret`: the full `sk_live_*` or `sk_int_*` key\n- `scope` (optional): space-separated subset of the key's allowed scopes\n\n**Response** (RFC 6749):\n```json\n{\n  \"access_token\": \"eyJhbGciOiJSUzI1NiIs...\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 900,\n  \"refresh_token\": \"rt_...\",\n  \"scope\": \"documents:send documents:read\"\n}\n```\n\n**Errors** use Peppol error envelope: `{ error: { category, code, message, retryable, correlation_id, details? } }`.\n\nAccount lockout: 5 failed attempts within 10 min on the same `client_id` returns 423.\n\nThis endpoint is the canonical Enterprise URL; `/sapi/v1/auth/token` is the SAPI-spec equivalent and shares the same handler.","operationId":"authToken","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JwtTokenRequest"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/JwtTokenRequest"}}}},"responses":{"200":{"description":"Access token + refresh token issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JwtTokenResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Invalid grant_type or malformed body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolErrorResponse"}}}},"401":{"description":"Invalid client credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolErrorResponse"}}}},"403":{"description":"Requested scope(s) not allowed by key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolErrorResponse"}}}},"423":{"description":"Account locked after 5 failed attempts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolErrorResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}}}}},"/auth/renew":{"post":{"tags":["Auth"],"summary":"Refresh access token using a refresh token","description":"Rotate a refresh token: returns a new access JWT (15 min) + a new refresh token (30 days). The old refresh token is invalidated.\n\n**Body**:\n```json\n{ \"grant_type\": \"refresh_token\", \"refresh_token\": \"rt_...\" }\n```\n\nRefresh tokens are stateless JWTs verified server-side via Redis presence — once consumed, they cannot be reused (replay → 401).","operationId":"authRenew","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JwtRenewRequest"}}}},"responses":{"200":{"description":"New access + refresh token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JwtTokenResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Missing or malformed refresh_token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolErrorResponse"}}}},"401":{"description":"Refresh token invalid, expired, or already consumed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolErrorResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}}}}},"/auth/revoke":{"post":{"tags":["Auth"],"summary":"Revoke an access or refresh token (RFC 7009)","description":"Idempotent — always returns 200. Revoking an access token adds its `jti` to the Redis blocklist for the remainder of its lifetime. Revoking a refresh token deletes its server-side state.\n\n**Body**:\n```json\n{ \"token\": \"<jwt or refresh token>\", \"token_type_hint\": \"access_token\" | \"refresh_token\" }\n```\n\n`token_type_hint` is optional; the server detects the type automatically (`eyJ` prefix → JWT, `rt_` prefix → refresh).","operationId":"authRevoke","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JwtRevokeRequest"}}}},"responses":{"200":{"description":"Token revoked (or was already invalid — idempotent)","content":{"application/json":{"schema":{"type":"object","properties":{"revoked":{"type":"boolean"}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Missing token field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolErrorResponse"}}}}}}},"/auth/token/status":{"get":{"tags":["Auth"],"summary":"Inspect current JWT — expiry, refresh hint, scope","description":"Returns metadata about the JWT presented in `Authorization: Bearer`. Useful for SDKs to decide whether to renew before making a long-running request.","operationId":"authTokenStatus","responses":{"200":{"description":"Token introspection","content":{"application/json":{"schema":{"type":"object","properties":{"active":{"type":"boolean"},"expires_at":{"type":"string","format":"date-time"},"expires_in_seconds":{"type":"integer"},"should_refresh":{"type":"boolean","description":"True if within the last 25% of the access token's TTL"},"refresh_recommended_at":{"type":"string","format":"date-time"},"scope":{"type":"string"},"firm_id":{"type":"string","format":"uuid","nullable":true},"integrator_id":{"type":"string","format":"uuid","nullable":true}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Missing or invalid JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/status":{"get":{"tags":["Auth"],"summary":"API key introspection","description":"Returns metadata about the calling API key: permissions, linked firm, plan, rate-limit window. Cheap health-check alternative to `/account`.","operationId":"authStatus","responses":{"200":{"description":"Introspection OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthStatusResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}}}}},"/auth/rotate-secret":{"post":{"tags":["Auth"],"summary":"Rotate the current API key","description":"Issues a new API key with the same name/permissions and marks the old one inactive immediately. The new key is returned ONCE in the response. Integrator keys (sk_int_*) are not rotatable via this endpoint — use the integrator dashboard.","operationId":"rotateApiKey","responses":{"200":{"description":"Key rotated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateSecretResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Integrator keys cannot be rotated via this endpoint, or API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"API key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/ip-allowlist":{"get":{"tags":["Auth"],"summary":"Get IP allowlist for current key","description":"Returns the IP allowlist for the API key authenticating this request. Empty array → no IP restriction (any caller IP allowed). Per-key, not per-firm — `sk_live_*` and `sk_int_*` allowlists live in their own tables.\n\n**Requires `account:read` scope and an API-eligible actor: `api-enterprise` directly, or `integrator-managed` through the managing integrator.**","operationId":"getIpAllowlist","responses":{"200":{"description":"Current allowlist","content":{"application/json":{"schema":{"type":"object","properties":{"ip_allowlist":{"type":"array","items":{"type":"string"}}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Plan does not allow this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Auth"],"summary":"Replace IP allowlist for current key","description":"Replaces the IP allowlist for the API key authenticating this request. Each entry is either a bare IP (v4 or v6) or a CIDR `addr/prefix`. Max 50 entries. Empty array clears the restriction. Cache is busted so changes are effective on the next request.\n\n**Requires `account:read` scope and an API-eligible actor: `api-enterprise` directly, or `integrator-managed` through the managing integrator.**","operationId":"updateIpAllowlist","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ip_allowlist"],"properties":{"ip_allowlist":{"type":"array","maxItems":50,"items":{"type":"string","example":"203.0.113.42"}}}}}}},"responses":{"200":{"description":"Updated allowlist","content":{"application/json":{"schema":{"type":"object","properties":{"ip_allowlist":{"type":"array","items":{"type":"string"}}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Invalid entry or too many entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Plan does not allow this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/oauth/token":{"post":{"tags":["OAuth"],"summary":"OAuth 2.0 token exchange","description":"**Public endpoint at `https://epostak.sk/api/oauth/token`** (NOT under `/api/v1/`). Exchange an authorization code for a new `sk_int_*` client secret. The returned secret is not a bearer token; exchange it via `POST /api/v1/auth/token` to mint the short-lived JWT used on `/api/v1/*` routes. Supports PKCE via `code_verifier`.","operationId":"oauthTokenExchange","servers":[{"url":"https://epostak.sk/api","description":"Public base (no /v1 prefix)"}],"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenRequest"},"example":{"grant_type":"authorization_code","code":"auth_code_here","client_id":"client_id_here","client_secret":"client_secret_here","redirect_uri":"https://example.com/callback","code_verifier":"pkce_verifier_here"}}}},"responses":{"200":{"description":"Integrator client secret issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Invalid grant or request parameters (RFC 6749 error body)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthErrorResponse"}}}},"401":{"description":"Invalid client credentials (RFC 6749 error body)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthErrorResponse"}}}}}}},"/account":{"get":{"tags":["Account"],"summary":"Informacie o ucte","description":"Vrati zakladne informacie o firme, stav Peppol registracie, aktivny plan a statistiky odoslanych/prijatych dokumentov.","operationId":"getAccount","responses":{"200":{"description":"Informacie o ucte","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Firma nenajdena","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/licenses/info":{"get":{"tags":["Account"],"summary":"Plan and current-period usage","description":"Returns the firm's plan tier, current billing period usage (outbound + inbound API counts), overage so far, quota remaining, estimated month cost, and pricing tiers. Use for billing dashboards and quota warnings.\n\n**Requires `account:read` scope and an API-eligible actor: `api-enterprise` directly, or `integrator-managed` through the managing integrator.**","operationId":"getLicenseInfo","responses":{"200":{"description":"Plan + usage snapshot","content":{"application/json":{"schema":{"type":"object","properties":{"firm":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"sandbox":{"type":"boolean"}}},"plan":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"active":{"type":"boolean"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"daysUntilExpiry":{"type":"integer","nullable":true},"gracePeriodActive":{"type":"boolean"},"monthlyBase":{"type":"number"},"outboundLimit":{"type":"integer","nullable":true},"overageRate":{"type":"number","nullable":true},"inboundApiRate":{"type":"number","nullable":true},"hasApiAccess":{"type":"boolean"}}},"usage":{"type":"object","properties":{"period":{"type":"string","example":"2026-04"},"nextResetAt":{"type":"string","format":"date-time"},"outboundCount":{"type":"integer"},"inboundApiCount":{"type":"integer"},"overageAmount":{"type":"number"},"quotaRemaining":{"type":"integer","nullable":true},"usagePercent":{"type":"number","nullable":true},"estimatedMonthCost":{"type":"number"}}},"pricing":{"type":"object","properties":{"currency":{"type":"string","example":"EUR"},"model":{"type":"string","example":"tiered"},"outboundTiers":{"type":"array","items":{"type":"object"}},"inboundApiTiers":{"type":"array","items":{"type":"object"}}}}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Plan does not allow this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Firm not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/integrator/keys":{"get":{"tags":["Integrator"],"summary":"List integrator API keys","description":"Returns integrator API keys for the current `sk_int_*` JWT. No X-Firm-Id header — this is an integrator-level endpoint. Use it to find the `id` or `keyPrefix` of a key issued via `/api/oauth/token`.","operationId":"listIntegratorKeys","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Integrator API keys","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"keyPrefix":{"type":"string","example":"sk_int_xxxxx...abcd"},"name":{"type":"string","nullable":true},"scopes":{"type":"array","items":{"type":"string"}},"ipAllowlist":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"},"lastUsedAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing `firms:manage` scope or non-integrator key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}}}},"delete":{"tags":["Integrator"],"summary":"Deactivate an integrator API key","description":"Deactivates an active integrator API key. Send either `keyId` from `GET /api/v1/integrator/keys`, or `client_id` / `keyPrefix` returned by `/api/oauth/token`. The endpoint will not deactivate the integrator's last active key.","operationId":"deactivateIntegratorKey","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"keyId":{"type":"string","format":"uuid","description":"UUID from `GET /api/v1/integrator/keys`."},"client_id":{"type":"string","description":"`sk_int_*` keyPrefix/client_id returned by `/api/oauth/token`.","example":"sk_int_xxxxx...abcd"}},"anyOf":[{"required":["keyId"]},{"required":["client_id"]}]},"example":{"client_id":"sk_int_xxxxx...abcd"}}}},"responses":{"200":{"description":"API key deactivated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"API key deactivated."}}}}}},"400":{"description":"Invalid body, already inactive, or last active key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing `firms:manage` scope or non-integrator key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"API key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/integrator/licenses/info":{"get":{"tags":["Account"],"summary":"Aggregate plan + current-period usage for an integrator","description":"Returns the integrator plan and current-period usage **aggregated across every firm the integrator manages**. Tier rates apply to the AGGREGATE counts (not per-firm) — a 100-firm × 50-doc integrator lands in tier 2–3, not tier 1 like a standalone firm would. Volumes above `contactThreshold` (5 000) have no published rate (`exceedsAutoTier` flips true) — auto-billing stops there and sales handles invoicing manually.\n\n**Requires `account:read` scope on a `sk_int_*` integrator key.** No X-Firm-Id header — the endpoint is integrator-scoped, not firm-scoped.\n\n`billable` only includes firms on the `integrator-managed` plan (the integrator is the payer). `nonManaged` reports linked firms that pay their own plan. `perFirm` (returned as `firms`) breaks down both groups.","operationId":"getIntegratorLicenseInfo","security":[{"bearerAuth":[]}],"parameters":[{"name":"offset","in":"query","description":"Pagination offset for the per-firm list. Default 0.","required":false,"schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","description":"Page size for the per-firm list. Max 100. Default 50.","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Plan + aggregate usage snapshot","content":{"application/json":{"schema":{"type":"object","properties":{"integrator":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"plan":{"type":"string","example":"integrator"},"monthlyDocumentLimit":{"type":"integer","nullable":true}}},"period":{"type":"string","example":"2026-04","description":"Current billing period in YYYY-MM (SK timezone)."},"nextResetAt":{"type":"string","format":"date-time","description":"When counters reset — 1st of next month, SK midnight in UTC."},"billable":{"type":"object","description":"Aggregate over firms on the `integrator-managed` plan (the integrator pays).","properties":{"managedFirms":{"type":"integer"},"outboundCount":{"type":"integer"},"inboundApiCount":{"type":"integer"},"outboundCharge":{"type":"number","description":"Tier rates applied to the aggregate outboundCount."},"inboundApiCharge":{"type":"number","description":"Tier rates applied to the aggregate inboundApiCount."},"totalCharge":{"type":"number","description":"Sum of outboundCharge + inboundApiCharge, rounded to cents."},"currency":{"type":"string","example":"EUR"}}},"nonManaged":{"type":"object","description":"Linked firms that pay their own plan (not billed to the integrator).","properties":{"firms":{"type":"integer"},"outboundCount":{"type":"integer"},"inboundApiCount":{"type":"integer"}}},"exceedsAutoTier":{"type":"boolean","description":"True when outboundCount or inboundApiCount exceeds contactThreshold. Auto-billing pauses; sales handles invoicing manually."},"contactThreshold":{"type":"integer","example":5000,"description":"Threshold above which auto-billing stops and an individual contract is required."},"pricing":{"type":"object","properties":{"model":{"type":"string","example":"tiered"},"currency":{"type":"string","example":"EUR"},"outboundTiers":{"type":"array","items":{"type":"object","properties":{"upTo":{"type":"integer","nullable":true},"rate":{"type":"number","nullable":true},"label":{"type":"string"},"contactRequired":{"type":"boolean"}}}},"inboundApiTiers":{"type":"array","items":{"type":"object","properties":{"upTo":{"type":"integer","nullable":true},"rate":{"type":"number","nullable":true},"label":{"type":"string"},"contactRequired":{"type":"boolean"}}}}}},"firms":{"type":"array","description":"Per-firm breakdown for the requested page (sorted by outboundCount desc).","items":{"type":"object","properties":{"firmId":{"type":"string"},"name":{"type":"string","nullable":true},"ico":{"type":"string","nullable":true},"managed":{"type":"boolean","description":"true → counts in `billable`; false → counts in `nonManaged`."},"outboundCount":{"type":"integer"},"inboundApiCount":{"type":"integer"}}}},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"offset":{"type":"integer"},"total":{"type":"integer"}}}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing `account:read` scope or non-integrator key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Integrator not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/send":{"post":{"tags":["Documents"],"summary":"Odoslat dokument cez Peppol","description":"Odosle fakturu cez Peppol siet. Podporuje dva rezimy:\n\n**JSON mode** — poskytnete strukturovane data (`items`) pre standardnu fakturu, UBL XML sa vygeneruje automaticky. Odosielatel sa berie z autentifikovanej firmy, nie z payloadu.\n\n**XML mode** — poskytnete hotove UBL XML (`xml`), odosle sa priamo.\n\nV oboch pripadoch je `receiverPeppolId` povinne.\n\n**Idempotency (always strict):** pass `Idempotency-Key: <any unique string>` (alias `X-Idempotency-Key`) to safely retry after network errors — the second call with the same body returns the cached 201 response. If the same key is currently being processed, returns 409 CONFLICT. If the body SHA-256 differs from the stored hash, returns 422 IDEMPOTENCY_KEY_MISMATCH (body is canonicalized — keys sorted recursively — before hashing). There is no non-strict mode.\n\n**Cross-path dedup (XML mode):** if the same UBL XML SHA-256 was already accepted for this firm via dashboard mass-import, returns 200 with `{ data: { invoice_id, peppol_message_id, status, duplicate: true } }`.\n\n**Items[] max 999.** Unit codes use UN/ECE Rec 20 (C62, HUR, KGM, MTR, LTR, DAY, ...).\n\n**Attachments (BG-24):** up to 20 files, 10 MB per file, 15 MB total after base64 decode. MIME types enforced per BR-CL-22.\n\n**Required scope:** `documents:send`. Wildcard scopes (`*`, `full`, or empty `[]`) also satisfy this requirement.","operationId":"sendDocument","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Client-supplied idempotency key (canonical RFC-draft header). If the same key was used recently with the same body, the prior response is replayed."},{"name":"X-Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Alias for `Idempotency-Key`. Both headers are accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SendDocumentJsonRequest"},{"$ref":"#/components/schemas/SendDocumentXmlRequest"}]},"examples":{"json_mode":{"summary":"Complete JSON invoice mode","value":{"receiverPeppolId":"0245:2023038963","receiverName":"Zakaznik A s.r.o.","receiverIco":"50123456","receiverDic":"2123038963","receiverIcDph":"SK2123038963","receiverStreet":"Hlavna 12","receiverCity":"Bratislava","receiverPostalCode":"811 01","receiverCountry":"SK","invoiceNumber":"FA-2026-001","issueDate":"2026-07-01","dueDate":"2026-07-15","currency":"EUR","paymentMethod":"bank_transfer","iban":"SK3112000000198742637541","variableSymbol":"2026001","buyerReference":"PO-2026-4421","note":"Services for June 2026. Attachment: signed acceptance protocol.","prepaidAmount":100,"items":[{"description":"Implementation services","quantity":16,"unit":"HUR","unitPrice":75,"vatRate":23,"vatCategoryCode":"S","discount":5,"deliveryDate":"2026-06-30"},{"description":"Support subscription","quantity":1,"unit":"C62","unitPrice":240,"vatRate":23,"vatCategoryCode":"S"}],"attachments":[{"fileName":"acceptance-protocol.pdf","mimeType":"application/pdf","content":"JVBERi0xLjQKJc...","description":"Signed acceptance protocol"}]}},"json_mode_with_attachments":{"summary":"JSON mode s prilohami (BG-24)","value":{"receiverPeppolId":"0245:12345678","receiverName":"Zakaznik s.r.o.","invoiceNumber":"FAK-2026-0001","items":[{"description":"Konzultacne sluzby","quantity":10,"unitPrice":50,"vatRate":23}],"attachments":[{"fileName":"invoice-detail.pdf","mimeType":"application/pdf","content":"JVBERi0xLjQKJeLjz9MKMS...","description":"Rozpis odpracovanych hodin"}]}},"xml_mode":{"summary":"XML mode for ready UBL, including self-billing","value":{"receiverPeppolId":"0245:2023038963","xml":"<?xml version=\"1.0\" encoding=\"UTF-8\"?><Invoice>...<cbc:InvoiceTypeCode>389</cbc:InvoiceTypeCode>...</Invoice>"}}}}}},"responses":{"201":{"description":"Dokument uspesne odoslany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendDocumentResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"202":{"description":"Dokument bol dorucenny cez Peppol, ale zapis lokalneho stavu zlyhal. Reconcile cron stav doplni; idempotent retry vrati identicku odpoved.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendDocumentResponse"}}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"409":{"description":"Idempotency key in-flight — same X-Idempotency-Key is currently being processed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (> 25 MB JSON mode, > 5 MB XML mode)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation error. Two distinct failure shapes return 422 here: (a) UBL pre-flight rule violation — body matches UblValidationError with `code: \"UBL_VALIDATION_ERROR\"` and a `rule` field naming the violated BR-* / BT-* / PEPPOL-R* code; (b) IDEMPOTENCY_KEY_MISMATCH — same X-Idempotency-Key was replayed with a different request body hash, body matches the generic ErrorResponse.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/UblValidationError"},{"$ref":"#/components/schemas/ErrorResponse"}]}}}},"502":{"description":"SEND_FAILED — Peppol AP dispatch failed (retryable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"IDEMPOTENCY_STORE_UNAVAILABLE — Redis idempotency layer unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/send/batch":{"post":{"tags":["Documents"],"summary":"Send up to 50 documents in one call","description":"Batch version of `/documents/send`. Each item is dispatched through the regular send pipeline and returns its own status + documentId (or per-item error). Partial success is expected — the HTTP status is 200 even if some items fail; inspect each result. Body size cap: 20 MB (use individual sends for larger batches).","operationId":"sendDocumentBatch","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchSendRequest"}}}},"responses":{"200":{"description":"Batch processed (partial-success semantics)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchSendResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Payload too large (> 20 MB)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"UBL validation error (schematron rule failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UblValidationError"}}}}}}},"/documents/preflight":{"post":{"tags":["Documents"],"summary":"Pred-odosielacia validacia","description":"Enterprise reliability contract: capability -> preflight -> send -> events -> support. Dry-run send without creating a document or billing usage; run it after capability checks and before POST /documents/send. Read decision/canSend/errors/checks for the result, and retry the later send call with the same Idempotency-Key when it is the same payload.","operationId":"preflightDocument","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["receiverPeppolId"],"properties":{"receiverPeppolId":{"type":"string","example":"0245:12345678","description":"Peppol ID prijemcu"},"documentTypeId":{"type":"string","example":"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2","description":"Typ dokumentu (volitelne, default: Invoice)"}}}}}},"responses":{"200":{"description":"Vysledok preflight kontroly (tri-state booleans)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreflightResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Payload too large (> 6 MB)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"UBL validation error (schematron rule failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UblValidationError"}}}},"503":{"description":"SMP lookup service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/validate":{"post":{"tags":["Documents"],"summary":"Validovat dokument bez odoslania","description":"Overi UBL XML alebo JSON data voci Peppol pravidlam bez skutocneho odoslania. Vhodne pre testovanie integracie. Body cap: 6 MB.","operationId":"validateDocument","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SendDocumentJsonRequest"},{"$ref":"#/components/schemas/SendDocumentXmlRequest"}]}}}},"responses":{"200":{"description":"Validacia uspesna","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateDocumentResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Payload too large (> 6 MB)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"UBL validation error (schematron rule failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UblValidationError"}}}},"503":{"description":"VALIDATION_SERVICE_UNAVAILABLE — ion-docval unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/inbox":{"get":{"tags":["Inbox"],"summary":"Zoznam prijatych fakturacnych dokumentov","description":"Vrati strankovany zoznam fakturacnych dokumentov prijatych cez Peppol pre vasu firmu. Pre plny Peppol scope vratane non-billing typov pouzite GET /api/v1/inbound/documents. Oba endpointy funguju pre api-enterprise priamo alebo pre integrator-managed firmu cez spravujuci sk_int_* integratorsky token.","operationId":"listInbox","parameters":[{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Pocet preskocenych zaznamov"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Pocet vratenych zaznamov"},{"name":"status","in":"query","schema":{"type":"string","enum":["RECEIVED","ACKNOWLEDGED","ACCEPTED","REJECTED","PAID","VALIDATION_FAILED","FAILED"]},"description":"Filter podla stavu dokumentu"},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Return only documents received after this ISO 8601 timestamp"},{"name":"peppolMessageId","in":"query","schema":{"type":"string","maxLength":100},"description":"Filter by Peppol message ID (exact match)"},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from previous response's nextCursor. Stable pagination — preferred over offset for large result sets."}],"responses":{"200":{"description":"Zoznam prijatych dokumentov (response root key je `documents`, kazdy item je normalizovany InvoiceResponse so supplier/customer/totals nested objektami podla `formatInvoice()` v `lib/api/format.ts`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxListResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"422":{"description":"Invalid status or since parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/inbox/{id}":{"get":{"tags":["Inbox"],"summary":"Detail prijateho dokumentu","description":"Vrati kompletne data prijateho dokumentu vratane UBL XML payloadu (ak je dostupny).","operationId":"getInboxDocument","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID dokumentu"}],"responses":{"200":{"description":"Detail dokumentu","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxDocumentDetailResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Dokument nepatri vasej firme","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Dokument nenajdeny alebo nie je inbound","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/inbox/{id}/acknowledge":{"post":{"tags":["Inbox"],"summary":"Potvrdit prijatie dokumentu","description":"Oznaci dokument ako spracovany (`ACKNOWLEDGED`). Ak bol dokument uz potvrdeny, vrati chybu.","operationId":"acknowledgeDocument","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID dokumentu"}],"responses":{"200":{"description":"Dokument potvrdeny","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcknowledgeResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Dokument nepatri vasej firme alebo API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Dokument nenajdeny alebo nie je inbound","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Dokument bol uz potvrdeny alebo zly source state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/inbox/all":{"get":{"tags":["Inbox"],"summary":"Cross-firm bulk inbox","description":"Returns received documents across all assigned firms. No X-Firm-Id header needed. Requires a JWT minted from an sk_int_* key.","operationId":"getCrossFirmInbox","security":[{"bearerAuth":[]}],"parameters":[{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Pagination offset"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"description":"Maximum number of documents to return (max 200)"},{"name":"status","in":"query","schema":{"type":"string","enum":["RECEIVED","ACKNOWLEDGED","ACCEPTED","REJECTED","PAID","VALIDATION_FAILED","FAILED"]},"description":"Filter by document status"},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Return only documents received after this ISO 8601 timestamp"},{"name":"firm_id","in":"query","schema":{"type":"string","format":"uuid"},"description":"Filter by firm UUID"}],"responses":{"200":{"description":"List of received documents across all firms","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossFirmInboxResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/outbox":{"get":{"tags":["Outbox"],"summary":"Zoznam odoslanych dokumentov","description":"Vrati strankovany zoznam dokumentov odoslanych cez Peppol pre vasu firmu.","operationId":"listOutbox","parameters":[{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Pocet preskocenych zaznamov"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Pocet vratenych zaznamov"},{"name":"status","in":"query","schema":{"type":"string","enum":["SENT","DELIVERED","FAILED","REJECTED","ACKNOWLEDGED","SENDING","SEND_FAILED","VALIDATION_FAILED","PAID","DRAFT","OVERDUE","ACCEPTED"]},"description":"Filter podla stavu dokumentu"},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Return only documents created after this ISO 8601 timestamp"},{"name":"peppolMessageId","in":"query","schema":{"type":"string","maxLength":100},"description":"Filter by Peppol message ID (exact match)"}],"responses":{"200":{"description":"Zoznam odoslanych dokumentov (response root key je `documents`, kazdy item je normalizovany InvoiceResponse so supplier/customer/totals nested objektami podla `formatInvoice()` v `lib/api/format.ts`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutboxListResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"422":{"description":"Invalid status, since or peppolMessageId parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}":{"get":{"tags":["Documents"],"summary":"Detail dokumentu — invoice alebo non-billing Peppol doc","description":"Vráti dokument podľa ID. Najprv hľadá medzi invoices (BIS Billing); ak ho tam nenájde, hľadá medzi peppol_documents (non-billing T01/T16/T19/T76 atď.). Tenant-isolated cez firmId — dokumenty inej firmy nikdy nevráti.\n\n**Required scope:** `documents:read`.","operationId":"getDocument","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID dokumentu (invoice alebo peppol_document)"}],"responses":{"200":{"description":"Detail dokumentu — Invoice (BIS Billing) alebo PeppolDocument (non-billing) shape, podľa toho kam dokument patrí","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatný alebo chýbajúci JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Enterprise plán vyžadovaný","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Dokument nenájdený","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["Documents"],"summary":"Upraviť draft fakturu","description":"Aktualizuje draft fakturu pred odoslaním. Pracuje len s `status=draft` invoice rows — non-draft a non-invoice dokumenty vrátia 422. Telo je strict (neznáme polia odmietne). Polia, ktoré nie sú v tele, ostanú nezmenené.\n\n**Required scope:** `documents:write`.","operationId":"patchDocument","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID draft faktury"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"invoiceNumber":{"type":"string","minLength":1},"issueDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"dueDate":{"type":"string","nullable":true,"pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"currency":{"type":"string","minLength":1},"note":{"type":"string","nullable":true},"iban":{"type":"string","nullable":true},"variableSymbol":{"type":"string","nullable":true},"buyerReference":{"type":"string","nullable":true},"receiverName":{"type":"string","minLength":1},"receiverIco":{"type":"string","nullable":true},"receiverDic":{"type":"string","nullable":true},"receiverIcDph":{"type":"string","nullable":true},"receiverAddress":{"type":"string","nullable":true},"receiverCountry":{"type":"string","nullable":true},"receiverPeppolId":{"type":"string","nullable":true},"items":{"type":"array","minItems":1,"items":{"type":"object","required":["description","quantity","unitPrice","vatRate"],"properties":{"description":{"type":"string","minLength":1},"quantity":{"type":"number","exclusiveMinimum":0},"unit":{"type":"string","default":"C62","description":"UN/ECE Rec 20"},"unitPrice":{"type":"number","minimum":0},"vatRate":{"type":"number","enum":[0,5,10,19,20,23],"description":"SK VAT rates from 2025 plus historical 20% for older correction documents"},"discount":{"type":"number","minimum":0,"maximum":100,"default":0}}}}}}}}},"responses":{"200":{"description":"Updated invoice","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error or non-draft / non-invoice document","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/status":{"get":{"tags":["Documents"],"summary":"Stav dokumentu — uplny lifecycle","description":"Vrati aktualny stav dokumentu vratane kompletnej historie stavov.","operationId":"getDocumentStatus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID dokumentu"}],"responses":{"200":{"description":"Stav dokumentu","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentStatusResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Dokument nenajdeny","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/status/batch":{"post":{"tags":["Documents"],"summary":"Hromadný status check (až 100 dokumentov)","description":"Vráti stav až 100 dokumentov v jednom volaní. Výsledky sú v rovnakom poradí ako vstupné `ids`. Dokumenty, ktoré nepatria volajúcej firme alebo neexistujú, sú v odpovedi označené `{ \"error\": \"not_found\" }` — endpoint nikdy nevráti 404 pre celé volanie ani neprezradí existenciu dokumentov inej firmy.\n\n**Rate limit:** 300 req/min na API kľúč (až 30 000 stavov za minútu). Pre jednotlivé dokumenty použite `GET /documents/{id}/status` (limit 400 req/min).\n\n**Telo cap:** 64 KB.\n\n**Required scope:** `documents:read`.","operationId":"batchDocumentStatus","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string","minLength":1},"description":"Pole 1-100 document IDs. Duplicity sú deduplikované pred query, ale poradie volajúceho je zachované v results."}}}}}},"responses":{"200":{"description":"Per-item statuses v poradí volajúcich `ids`","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"integer","example":42},"found":{"type":"integer","example":38,"description":"Count of items in results that are NOT marked {error: not_found}."},"notFound":{"type":"integer","example":4},"results":{"type":"array","items":{"oneOf":[{"type":"object","required":["id","status","statusHistory","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"status":{"type":"string"},"documentType":{"type":"string","nullable":true},"direction":{"type":"string","enum":["inbound","outbound"],"description":"`inbound` = my sme prijímateľ. `outbound` = my sme odosielateľ. Sémantika `deliveredAt`/`acknowledgedAt` závisí od smeru — pozri DocumentStatusResponse popis."},"senderPeppolId":{"type":"string","nullable":true},"receiverPeppolId":{"type":"string","nullable":true},"statusHistory":{"type":"array","items":{"type":"object"}},"validationResult":{"type":"object","nullable":true},"deliveredAt":{"type":"string","format":"date-time","nullable":true},"acknowledgedAt":{"type":"string","format":"date-time","nullable":true},"invoiceResponseStatus":{"type":"string","nullable":true},"peppolMessageId":{"type":"string","nullable":true,"description":"Alias k `as4MessageId` (rovnaká hodnota)."},"as4MessageId":{"type":"string","nullable":true,"description":"Alias k `peppolMessageId` (rovnaká hodnota)."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},{"type":"object","required":["id","error"],"properties":{"id":{"type":"string"},"error":{"type":"string","enum":["not_found"]}}}]}}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Invalid request — empty ids[], > 100, non-string elements","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Body exceeds 64 KB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/events":{"get":{"tags":["Documents"],"summary":"Document timeline — AS4/Peppol/lifecycle events","description":"Paginated, reverse-chronological timeline for a single document: creation, validation, AS4 send/receipt, MLR, invoice response, FS SR reporting, user actions. Synthesized from invoice fields when `document_events` has no rows yet, real DB rows once events are emitted.","operationId":"listDocumentEvents","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Document ID"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque cursor from previous response"}],"responses":{"200":{"description":"Event list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentEventsResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied or API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/mark":{"post":{"tags":["Documents"],"summary":"Report downstream state (delivered/processed/failed/read)","description":"Granular state-transition endpoint for integrators running their own processing pipeline. Report when the external channel confirmed delivery, the ERP consumed the document, the user opened it, or delivery terminally failed. Keeps status/events/reporting accurate.","operationId":"markDocumentState","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Document ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkRequest"}}}},"responses":{"200":{"description":"State updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied or API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Invalid state value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/pdf":{"get":{"tags":["Documents"],"summary":"Stiahnut PDF dokumentu","description":"Vrati PDF verziu faktury ako binarny subor.","operationId":"getDocumentPdf","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID dokumentu"}],"responses":{"200":{"description":"PDF subor","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Dokument nenajdeny alebo PDF nie je dostupne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/ubl":{"get":{"tags":["Documents"],"summary":"Stiahnut UBL XML dokumentu","description":"Vrati UBL XML reprezentaciu dokumentu.","operationId":"getDocumentUbl","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID dokumentu"}],"responses":{"200":{"description":"UBL XML subor","content":{"application/xml":{"schema":{"type":"string","format":"binary"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Dokument nenajdeny alebo UBL nie je dostupne","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/evidence":{"get":{"tags":["Documents"],"summary":"Dokazy o doruceni dokumentu","description":"Vrati AS4 receipt, Message Level Response (MLR) a invoice response pre odoslany dokument.","operationId":"getDocumentEvidence","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID dokumentu"}],"responses":{"200":{"description":"Dokazy o doruceni","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentEvidenceResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Dokument nenajdeny","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/envelope":{"get":{"tags":["Documents"],"summary":"Download signed AS4 envelope","description":"Streams the raw multipart AS4 envelope for this document from the Enterprise API evidence archive exactly as it was transmitted on the Peppol network — signed, timestamped, tamper-evident. The archive is available during the active contract term plus the agreed exit period after termination; it is not a standalone accounting archive outside the contract. Response headers include `X-Envelope-Archived-At` (ISO 8601) and `X-Envelope-Direction` (inbound|outbound).\n\nArchive cron runs on a short interval, so brand-new documents may briefly 404 until archived.\n\n**Requires an API-eligible actor: `api-enterprise` directly, or `integrator-managed` through the managing integrator.**","operationId":"getDocumentEnvelope","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Document ID"}],"responses":{"200":{"description":"Signed AS4 envelope","headers":{"Content-Disposition":{"schema":{"type":"string","example":"attachment; filename=\"<id>.as4\""}},"X-Envelope-Archived-At":{"schema":{"type":"string","format":"date-time"},"description":"When the envelope was written to the WORM archive"},"X-Envelope-Direction":{"schema":{"type":"string","enum":["inbound","outbound"]}},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}},"multipart/related":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Document not found OR envelope not yet archived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/responses":{"get":{"tags":["Documents"],"summary":"Zoznam invoice responses dokumentu","description":"Vrati zoznam invoice responses (AP/RE/UQ) pre odoslany dokument.","operationId":"listDocumentResponses","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID dokumentu"}],"responses":{"200":{"description":"Zoznam invoice responses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponsesListResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Dokument nenajdeny","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/respond":{"post":{"tags":["Documents"],"summary":"Odoslat invoice response","description":"Odosle invoice response (UBL ApplicationResponse) pre prijaty dokument. Podporuje 7 stavov: AB, IP, UQ, CA, RE, AP, PD.\n\nReturns HTTP 200 when AS4 dispatch succeeded, 202 when the response was persisted but dispatch failed (will retry async — inspect `dispatchError`).","operationId":"respondToDocument","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID dokumentu"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceRespondRequest"},"example":{"status":"AP","note":"Faktura akceptovana"}}}},"responses":{"200":{"description":"Invoice response dispatched successfully via AS4","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceRespondResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"202":{"description":"Response persisted; AS4 dispatch failed and will be retried (inspect `dispatchError`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceRespondResponse"}}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Dokument nenajdeny alebo nie je inbound","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"UBL validation error (schematron rule failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UblValidationError"}}}}}}},"/documents/parse":{"post":{"tags":["Documents"],"summary":"Parse raw UBL into normalized JSON","description":"Parse-as-a-service: accept raw UBL 2.1 Invoice or CreditNote XML and return the normalized JSON structure the send endpoint would accept. Useful when ingesting invoices over non-Peppol channels (email, SFTP) or migrating from another AP.\n\nAccepts either `Content-Type: application/xml` (body = XML) or `application/json` with `{ xml: \"...\" }`. Body cap: 10 MB.\n\nThe supplier `EndpointID` in the submitted XML must match the authenticated firm's Peppol ID. Forwarding cross-tenant XML is rejected with 422 (`VALIDATION_ERROR`). Documents that omit the supplier `EndpointID` entirely (OCR imports) are accepted. The same guard is applied to `/documents/convert`, `/documents/validate` (UBL mode) and `/documents/preflight` (when raw XML is supplied).","operationId":"parseDocument","requestBody":{"required":true,"content":{"application/xml":{"schema":{"type":"string","format":"xml"}},"application/json":{"schema":{"type":"object","required":["xml"],"properties":{"xml":{"type":"string","description":"UBL Invoice or CreditNote XML"}}}}}},"responses":{"200":{"description":"Parsed invoice payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParseResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Payload too large (> 10 MB)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation or parse error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/convert":{"post":{"tags":["Documents"],"summary":"Konverzia formatov dokumentu","description":"Konvertuje medzi JSON a UBL XML formatmi bez odoslania cez Peppol. Smer uvedte cez `input_format` (`json`|`ubl`) a `output_format` (`ubl`|`json`). Podporovane pary: json→ubl, ubl→json. JSON→UBL respektuje `items[].vatCategoryCode` rovnako ako `/documents/send`, takze vystupne XML mozete pouzit na kontrolu TaxSubtotalov pred odoslanim.","operationId":"convertDocument","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertDocumentRequest"},"examples":{"jsonToUbl":{"summary":"JSON → UBL","value":{"input_format":"json","output_format":"ubl","document":{"invoiceNumber":"FAK-001","items":[{"description":"Sluzba s prenesenim DPH","quantity":1,"unitPrice":200,"vatRate":0,"vatCategoryCode":"AE"}]}}},"ublToJson":{"summary":"UBL → JSON","value":{"input_format":"ubl","output_format":"json","document":"<?xml version=\"1.0\"?>..."}}}}}},"responses":{"200":{"description":"Konverzia uspesna. Pre `output_format=ubl` je `document` string, pre `output_format=json` je objekt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertDocumentResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Payload too large (> 6 MB)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Konverzia zlyhala alebo nepodporovana kombinacia input_format/output_format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Backend conversion service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/peppol-documents":{"get":{"tags":["Documents"],"summary":"List non-billing Peppol documents","description":"List endpoint for non-billing Peppol doctypes (Order, OrderResponse, DespatchAdvice, Catalogue, CatalogueResponse, OrderAgreement, AdvancedOrdering family, PunchOut). Lives in its own `peppol_documents` table to avoid changing the `/documents/inbox`/`/documents/outbox` Invoice-shaped contract.\n\n**Requires `documents:read` scope and an API-eligible actor: `api-enterprise` directly, or `integrator-managed` through the managing integrator.**","operationId":"listPeppolDocuments","parameters":[{"name":"direction","in":"query","schema":{"type":"string","enum":["inbound","outbound"]}},{"name":"doctypeKey","in":"query","schema":{"type":"string"},"description":"Specific non-billing doctype key (see registry)"},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"peppolMessageId","in":"query","schema":{"type":"string"}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Non-billing Peppol documents","content":{"application/json":{"schema":{"type":"object","properties":{"documents":{"type":"array","items":{"type":"object","properties":{"document_id":{"type":"string"},"doctype_key":{"type":"string"},"direction":{"type":"string","enum":["inbound","outbound"]},"status":{"type":"string"},"sender_peppol_id":{"type":"string","nullable":true},"receiver_peppol_id":{"type":"string","nullable":true},"sender_name":{"type":"string","nullable":true},"receiver_name":{"type":"string","nullable":true},"document_type_id":{"type":"string","nullable":true},"process_id":{"type":"string","nullable":true},"peppol_message_id":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Plan does not allow this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/extract":{"post":{"tags":["Extraction"],"summary":"Extrahovat fakturu z PDF alebo obrazka","description":"Nahra PDF alebo obrazok faktury a extrahuje data pomocou Gemini Vision. Pri prijatej/inbound fakture vrati strukturovane data spolu s vygenerovanym Peppol BIS 3.0 UBL XML. Pri vystavenej/outbound standardnej fakture neodosiela priamo z OCR; vrati direction=outbound a send_payload ako navrh JSON tela pre POST /api/v1/documents/send. Integrator musi payload skontrolovat, doplnit chybajuce polia (najma receiverPeppolId, ak sa neda vyriesit) a odoslat ho samostatne s Idempotency-Key. Pre outbound typy mimo JSON send flow (napr. dobropis) vrati extrakciu na kontrolu bez send_payload; odoslite validne UBL XML cez /documents/send.\n\n**Vyzaduje API pristup: `api-enterprise` priamo alebo `integrator-managed` cez spravujuceho integratora.** Rate limit: 10 req/min per firm.\n\nPovolene typy: `application/pdf`, `image/jpeg`, `image/png`, `image/webp`. Max. velkost: 20 MB.","operationId":"extractDocument","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"PDF alebo obrazok faktury (max 20 MB)"}}}}}},"responses":{"200":{"description":"Extrakcia uspesna","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Chybajuci subor, nepodporovany typ alebo prilis velky subor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleErrorResponse"}}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleErrorResponse"}}}},"422":{"description":"Extrakcia alebo UBL generovanie zlyhalo. Vystavene/outbound PDF faktury vracaju 200 s direction=outbound; standardne faktury obsahuju send_payload na kontrolu.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractErrorResponse"}}}},"429":{"description":"Rate limit exceeded (10/min/firm)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"503":{"description":"Gemini API key not configured (SERVICE_UNAVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/extract/batch":{"post":{"tags":["Extraction"],"summary":"Batch OCR extraction","description":"Extract invoice data from multiple PDF/image files. Max 50 files, 20 MB per file, 200 MB total request body. Rate limit: 3 req/min per firm.\n\n**Requires an API-eligible actor: `api-enterprise` directly, or `integrator-managed` through the managing integrator.**","operationId":"extractBatch","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["files"],"properties":{"files":{"type":"array","items":{"type":"string","format":"binary"},"maxItems":50,"description":"PDF or image files"}}}}}},"responses":{"200":{"description":"Batch extraction results (per-file success or error)","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Total body exceeds 200 MB or individual file > 20 MB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded (3/min/firm)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"503":{"description":"Gemini API not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhooks":{"post":{"tags":["Webhooks"],"summary":"Vytvorit webhook","description":"Zaregistruje novu webhook URL pre vybrane udalosti. URL musi byt HTTPS a nesmie byt localhost ani privatna siet (SSRF ochrana). Max 10 webhookov per firma.\n\n**Vyzaduje API pristup: `api-enterprise` priamo alebo `integrator-managed` cez spravujuceho integratora.**\n\nPodporovane udalosti (7): `document.created`, `document.sent`, `document.received`, `document.validated`, `document.delivered`, `document.rejected`, `document.response_received`.","operationId":"createWebhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"},"example":{"url":"https://vas-system.sk/webhooks/epostak","events":["document.received","document.sent"]}}}},"responses":{"201":{"description":"Webhook vytvoreny","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDetailResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Neplatna URL alebo udalosti","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}}}},"get":{"tags":["Webhooks"],"summary":"Zoznam webhookov","description":"Vrati vsetky webhook odoberania pre vasu firmu.\n\n**Vyzaduje API pristup: `api-enterprise` priamo alebo `integrator-managed` cez spravujuceho integratora.**","operationId":"listWebhooks","responses":{"200":{"description":"Zoznam webhookov","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookListResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}}}}},"/webhooks/{id}":{"get":{"tags":["Webhooks"],"summary":"Detail webhooku","description":"Vrati detaily webhooku vratane poslednych 20 doruceni.\n\n**Vyzaduje API pristup: `api-enterprise` priamo alebo `integrator-managed` cez spravujuceho integratora.**","operationId":"getWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID webhooku"}],"responses":{"200":{"description":"Detail webhooku","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookWithDeliveriesResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Webhook nenajdeny","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["Webhooks"],"summary":"Upravit webhook","description":"Aktualizuje URL, zoznam udalosti alebo aktivny stav webhooku. Vsetky polia su volitelne.\n\n**Vyzaduje API pristup: `api-enterprise` priamo alebo `integrator-managed` cez spravujuceho integratora.**","operationId":"updateWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID webhooku"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookRequest"}}}},"responses":{"200":{"description":"Webhook aktualizovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Neplatna URL alebo udalosti","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty alebo API plan vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Webhook nenajdeny","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Webhooks"],"summary":"Zmazat webhook","description":"Trvalo zmaze webhook.\n\n**Vyzaduje API pristup: `api-enterprise` priamo alebo `integrator-managed` cez spravujuceho integratora.**","operationId":"deleteWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID webhooku"}],"responses":{"204":{"description":"Webhook zmazany (prazdne telo odpovede)","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty alebo API plan vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Webhook nenajdeny","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"summary":"Send a synthetic test delivery","description":"Dispatches one or more synthetic test payloads to the webhook URL with fresh HMAC signatures. Returns HTTP 200 with a result envelope regardless of whether delivery succeeded — inspect `success`, `succeeded`, `failed`, and `statusCodes`. One aggregate `webhook_deliveries` row is written so the test run appears in `/webhooks/{id}/deliveries`.\n\n**Requires an API-eligible actor: `api-enterprise` directly, or `integrator-managed` through the managing integrator.**","operationId":"testWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook ID"},{"name":"event","in":"query","required":false,"schema":{"type":"string","enum":["document.sent","document.received","document.delivered","document.delivery_failed","document.rejected","document.response_received"]},"description":"Event type to simulate. Takes precedence over the request body field. Default: document.sent"},{"name":"count","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":30000,"default":1},"description":"Number of synthetic webhook POSTs to send in one test run. Takes precedence over the request body field."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","enum":["document.sent","document.received","document.delivered","document.delivery_failed","document.rejected","document.response_received"],"description":"Event to simulate (default: document.sent)"},"count":{"type":"integer","minimum":1,"maximum":30000,"default":1,"description":"Number of synthetic webhook POSTs to send in one test run."}}}}}},"responses":{"200":{"description":"Test dispatched (check `success` for delivery outcome)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTestResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied or API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Invalid event type supplied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhooks/{id}/deliveries":{"get":{"tags":["Webhooks"],"summary":"Paginated delivery history","description":"Returns the full delivery log for a webhook (test deliveries included). Supports status + event filters.\n\n**`responseBody` is omitted by default** because a legitimate webhook receiver may echo sensitive content (PII, tokens) in its 4xx/5xx body. Pass `?includeResponseBody=true` (or `?include=responseBody`) to opt in. The first 200 chars are stored at delivery time — older deliveries written before this cap shipped may be longer.\n\n**Requires an API-eligible actor: `api-enterprise` directly, or `integrator-managed` through the managing integrator.**","operationId":"listWebhookDeliveries","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook ID"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"status","in":"query","schema":{"type":"string","enum":["PENDING","SUCCESS","FAILED","RETRYING"]},"description":"Filter by delivery status (UPPERCASE enum)"},{"name":"event","in":"query","schema":{"type":"string"},"description":"Filter by event name"},{"name":"includeResponseBody","in":"query","schema":{"type":"boolean","default":false},"description":"Set to `true` to include the (truncated, 200-char) `responseBody` field on each delivery. Default `false` to avoid leaking content from receivers that echo sensitive data."},{"name":"include","in":"query","schema":{"type":"string","enum":["responseBody"]},"description":"Alternative spelling: `?include=responseBody` is equivalent to `?includeResponseBody=true`."}],"responses":{"200":{"description":"Delivery list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveriesResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied or API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhook-dead-letter":{"get":{"tags":["Webhooks"],"summary":"Webhook dead-letter queue","description":"Returns unresolved terminally failed push deliveries across your firm's webhooks. Use it for ERP runbooks: what needs replay or manual resolution.","operationId":"listWebhookDeadLetters","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"event","in":"query","schema":{"type":"string"},"description":"Filter by event name"},{"name":"subscriptionId","in":"query","schema":{"type":"string"},"description":"Filter to one webhook subscription"},{"name":"includeResponseBody","in":"query","schema":{"type":"boolean","default":false},"description":"Set to true to include the last ERP endpoint response body."}],"responses":{"200":{"description":"Dead-letter delivery list","content":{"application/json":{"schema":{"type":"object","required":["items","total","limit","offset"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryDetail"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied or API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}}}}},"/webhook-dead-letter/{deliveryId}/replay":{"post":{"tags":["Webhooks"],"summary":"Replay failed webhook delivery","description":"Creates a new PENDING delivery from the original FAILED row and enqueues it. The original row remains in audit history and is marked resolved by replay. webhook_event_id stays stable; webhook_id is a new per-delivery identifier.","operationId":"replayWebhookDeadLetter","parameters":[{"name":"deliveryId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Delivery ID from GET /webhook-dead-letter"}],"responses":{"202":{"description":"Replay accepted","content":{"application/json":{"schema":{"type":"object","required":["replayedFrom","deliveryId","webhookId","webhookEventId"],"properties":{"replayedFrom":{"type":"string","format":"uuid"},"deliveryId":{"type":"string","format":"uuid"},"webhookId":{"type":"string"},"webhookEventId":{"type":"string","format":"uuid"}}}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied or API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Dead-letter delivery not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Delivery cannot be replayed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhook-dead-letter/{deliveryId}/resolve":{"post":{"tags":["Webhooks"],"summary":"Resolve webhook failure","description":"Hides a failed delivery from the dead-letter queue without deleting or overwriting audit history. Use when the state was handled manually in the ERP or replay is no longer needed.","operationId":"resolveWebhookDeadLetter","parameters":[{"name":"deliveryId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Delivery ID from GET /webhook-dead-letter"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":500}}}}}},"responses":{"200":{"description":"Resolved","content":{"application/json":{"schema":{"type":"object","required":["resolved"],"properties":{"resolved":{"type":"boolean"}}}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied or API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Dead-letter delivery not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhooks/{id}/rotate-secret":{"post":{"tags":["Webhooks"],"summary":"Rotate HMAC signing secret","description":"Generates a new 64-char hex secret and immediately discards the old one. In-flight deliveries signed with the old secret will fail signature verification at the receiver. Returns the new secret ONCE.","operationId":"rotateWebhookSecret","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook ID"}],"responses":{"200":{"description":"Secret rotated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRotateSecretResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Access denied or API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhook-queue":{"get":{"tags":["Webhooks"],"summary":"Compatibility: webhook queue pull","description":"Compatibility endpoint for pull events. New ERP integrations should use the preferred GET /api/v1/events/pull alias; it returns the same unacknowledged events (oldest-first). After processing, acknowledge each event through /api/v1/events/{eventId}/ack or /api/v1/events/batch-ack.\n\n**Vyzaduje API pristup: `api-enterprise` priamo alebo `integrator-managed` cez spravujuceho integratora.**","operationId":"getWebhookQueue","responses":{"200":{"description":"Zoznam cakajucich udalosti","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookQueueResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}}}}},"/webhook-queue/{eventId}":{"delete":{"tags":["Webhooks"],"summary":"Compatibility: webhook queue ack","description":"Compatibility endpoint for acknowledging one event. New ERP integrations should use POST /api/v1/events/{eventId}/ack. Marks a single event as acknowledged and returns 200 with body { acknowledged: true }.\n\n**Vyzaduje API pristup: `api-enterprise` priamo alebo `integrator-managed` cez spravujuceho integratora.**","operationId":"acknowledgeWebhookEvent","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"description":"ID udalosti"}],"responses":{"200":{"description":"Udalost potvrdena","content":{"application/json":{"schema":{"type":"object","properties":{"acknowledged":{"type":"boolean","example":true}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Udalost nenajdena","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhook-queue/batch-ack":{"post":{"tags":["Webhooks"],"summary":"Compatibility: webhook queue batch ack","description":"Compatibility endpoint for batch ack. New ERP integrations should use POST /api/v1/events/batch-ack. Acknowledges multiple events at once. Up to 1000 IDs per request. Returns 200 with body { acknowledged: N }.\n\n**Vyzaduje API pristup: `api-enterprise` priamo alebo `integrator-managed` cez spravujuceho integratora.**","operationId":"batchAcknowledgeWebhookEvents","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event_ids"],"properties":{"event_ids":{"type":"array","items":{"type":"string"},"example":["evt_1","evt_2","evt_3"],"description":"Zoznam ID udalosti na potvrdenie"}}}}}},"responses":{"200":{"description":"Udalosti potvrdene","content":{"application/json":{"schema":{"type":"object","properties":{"acknowledged":{"type":"integer","example":3,"description":"Pocet potvrdenych udalosti"}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Chybajuci alebo prazdny zoznam event_ids","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}}}}},"/webhook-queue/all":{"get":{"tags":["Webhooks"],"summary":"Cross-firm webhook queue poll","description":"Poll pending webhook events across all assigned firms. No X-Firm-Id header needed. Requires a JWT minted from an sk_int_* key.","operationId":"getCrossFirmWebhookQueue","security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":500,"default":100},"description":"Maximum number of events to return (max 500)"},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Return only events created after this ISO 8601 timestamp"}],"responses":{"200":{"description":"Pending webhook events across all firms","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossFirmWebhookQueueResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/webhook-queue/all/batch-ack":{"post":{"tags":["Webhooks"],"summary":"Cross-firm batch acknowledge webhook events","description":"Acknowledge multiple webhook events across all firms in a single request. Maximum 1000 event IDs.","operationId":"batchAckCrossFirmWebhookEvents","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchAckWebhookRequest"},"example":{"event_ids":["uuid-1","uuid-2"]}}}},"responses":{"200":{"description":"Number of events acknowledged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchAckWebhookResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/peppol/participants/{scheme}/{identifier}":{"get":{"tags":["Peppol"],"summary":"SMP lookup ucastnika","description":"Vyhlada Peppol ucastnika v SMP (Service Metadata Publisher) podla scheme a identifikatora.","operationId":"smpLookup","parameters":[{"name":"scheme","in":"path","required":true,"schema":{"type":"string","example":"0245"},"description":"ICD scheme kod (napr. 0245 pre slovenske ICO)"},{"name":"identifier","in":"path","required":true,"schema":{"type":"string","example":"12345678"},"description":"Identifikator v danej scheme"}],"responses":{"200":{"description":"Ucastnik najdeny","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmpLookupResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Ucastnik nie je registrovany v Peppol sieti","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/peppol/participants/batch":{"post":{"tags":["Peppol"],"summary":"Bulk participant existence + capability lookup","description":"Pre-check a list of recipients before fan-out send. Max 100 per batch. Individual results are cached so repeat queries are cheap.","operationId":"peppolParticipantsBatch","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantsBatchRequest"}}}},"responses":{"200":{"description":"Batch results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantsBatchResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"422":{"description":"participants[] missing/empty or > 100","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/peppol/participants/resolve":{"get":{"tags":["Peppol"],"summary":"Resolve company to Peppol participant","description":"One-step lookup for ERP integrations: pass exactly one identifier (`ico`, `dic`, `icDph`, `peppolId`, or `scheme` + `identifier`). The endpoint enriches Slovak company data when available and checks the exact Peppol routing capability for `documentTypeId` + `processId`. Use this before preflight/send when the ERP knows IČO or DIČ, not the final Peppol ID.","operationId":"resolvePeppolParticipant","parameters":[{"name":"ico","in":"query","required":false,"schema":{"type":"string"},"description":"Slovak IČO, 6-8 digits. Mutually exclusive with other identifiers."},{"name":"dic","in":"query","required":false,"schema":{"type":"string"},"description":"Slovak DIČ, 10 digits. Mutually exclusive with other identifiers."},{"name":"icDph","in":"query","required":false,"schema":{"type":"string"},"description":"VAT ID, e.g. SK2020123456. Mutually exclusive with other identifiers."},{"name":"peppolId","in":"query","required":false,"schema":{"type":"string","example":"0245:2020123456"},"description":"Direct Peppol participant ID."},{"name":"scheme","in":"query","required":false,"schema":{"type":"string","example":"0245"},"description":"ISO 6523 scheme when using scheme+identifier."},{"name":"identifier","in":"query","required":false,"schema":{"type":"string","example":"2020123456"},"description":"Participant identifier when using scheme+identifier."},{"name":"documentTypeId","in":"query","required":false,"schema":{"type":"string"},"description":"Peppol document type URN. Defaults to BIS Billing 3.0 Invoice."},{"name":"processId","in":"query","required":false,"schema":{"type":"string"},"description":"Peppol process ID. Defaults to BIS Billing 3.0."}],"responses":{"200":{"description":"Company and Peppol routing capability","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Invalid or ambiguous query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Company or participant candidate not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/peppol/capabilities":{"post":{"tags":["Peppol"],"summary":"Capability probe — does receiver accept this doctype?","description":"Storecove-style `discovery/receives`: given a participant + optional candidate document type + process id, answer whether the receiver accepts it. Enterprise reliability contract starts here: before building the payload, read `networkReady` and `matchedDocumentTypes`, then continue capability -> preflight -> send -> events -> support.\n\nWhen `documentType` or `processId` are omitted, the endpoint defaults to BIS Billing 3.0 Invoice over the BIS Billing process. Response `matchedDocumentType` is the probed document type when accepted, otherwise `null`. Send `documentTypes[]` to check 1-20 document type URNs in one request; the response includes `capabilities[]` and `matchedDocumentTypes[]`.","operationId":"peppolCapabilities","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapabilitiesRequest"}}}},"responses":{"200":{"description":"Lookup result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapabilitiesResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Participant not registered in Peppol network","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapabilitiesResponse"}}}},"422":{"description":"Invalid scheme/identifier format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/peppol/directory/search":{"get":{"tags":["Peppol"],"summary":"Prehladavat Peppol directory","description":"Prehladava Peppol Business Card directory podla nazvu firmy, krajiny a inych kriterii.","operationId":"peppolDirectorySearch","parameters":[{"name":"q","in":"query","schema":{"type":"string","example":"Moja firma"},"description":"Vyhladavaci vyraz (nazov firmy, ICO)"},{"name":"country","in":"query","schema":{"type":"string","example":"SK"},"description":"Filtrovanie podla kodu krajiny (ISO 3166-1 alpha-2)"},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1},"description":"Cislo strany"},{"name":"page_size","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Pocet vysledkov na stranu"}],"responses":{"200":{"description":"Vysledky vyhladavania","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolDirectorySearchResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Neplatne parametre","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/company/lookup/{ico}":{"get":{"tags":["Peppol"],"summary":"Vyhladanie firmy podla ICO","description":"Vyhlada verejne informacie o firme podla ICO (slovensky obchodny register).","operationId":"companyLookup","parameters":[{"name":"ico","in":"path","required":true,"schema":{"type":"string","example":"12345678"},"description":"ICO firmy (8 cislic)"}],"responses":{"200":{"description":"Informacie o firme","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyLookupResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Firma s danym ICO nenajdena","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/firms":{"get":{"tags":["Firms"],"summary":"Zoznam pristupnych firiem","description":"Vrati zoznam firiem, ku ktorym ma API kluc pristup. Relevantne pre multi-tenant API kluce.","operationId":"listFirms","responses":{"200":{"description":"Zoznam firiem","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirmsListResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/firms/{id}":{"get":{"tags":["Firms"],"summary":"Detail firmy","description":"Vrati detailne informacie o konkretnej firme vratane Peppol statusu.","operationId":"getFirm","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID firmy"}],"responses":{"200":{"description":"Detail firmy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirmDetailResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Firma nenajdena","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/firms/{id}/documents":{"get":{"tags":["Firms"],"summary":"Dokumenty firmy","description":"Vrati strankovany zoznam dokumentov (odoslanych aj prijatych) pre danu firmu.","operationId":"listFirmDocuments","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID firmy"},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Pocet preskocenych zaznamov"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Pocet vratenych zaznamov"},{"name":"direction","in":"query","schema":{"type":"string","enum":["inbound","outbound"]},"description":"Filter podla smeru"}],"responses":{"200":{"description":"Zoznam dokumentov firmy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxListResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Firma nenajdena","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/firms/{id}/peppol-identifiers":{"post":{"tags":["Firms"],"summary":"Registrovat Peppol identifikator","description":"Zaregistruje novy Peppol identifikator (scheme:identifier) pre firmu v SMP.","operationId":"registerPeppolIdentifier","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"ID firmy"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["scheme","identifier"],"properties":{"scheme":{"type":"string","example":"0245","description":"ICD scheme kod"},"identifier":{"type":"string","example":"12345678","description":"Identifikator v danej scheme"}}},"example":{"scheme":"0245","identifier":"12345678"}}}},"responses":{"201":{"description":"Peppol identifikator zaregistrovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeppolIdentifierResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Neplatny scheme alebo identifikator","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Pristup odmietnuty","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Identifikator uz existuje","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/firms/assign":{"post":{"tags":["Firms"],"summary":"Assign firm by DIC or ICO","description":"Assign a firm to the enterprise account by its DIC or ICO. DIC is preferred because Slovak PFS/SMP and Peppol use 0245:DIC. ICO remains supported for lookup and backward compatibility. Requires a JWT minted from an sk_int_* key. No X-Firm-Id header needed.","operationId":"assignFirmByIco","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignFirmRequest"},"example":{"dic":"2123456789"}}}},"responses":{"201":{"description":"Firm assigned successfully (plan automatically promoted to `integrator-managed`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignFirmResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Invalid JSON body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid or missing integrator token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing `firms:manage` scope, or firm already on a paid plan (must use OAuth consent flow)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Firm not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Already assigned and active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"UNPROCESSABLE_ENTITY — provide a 10-digit DIC or 8-digit ICO","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/firms/assign/batch":{"post":{"tags":["Firms"],"summary":"Batch assign firms by DIC or ICO list","description":"Assign multiple firms at once. Prefer `dics`; `icos` remains supported for backward compatibility. Maximum 50 identifiers per request.","operationId":"batchAssignFirms","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchAssignFirmsRequest"},"example":{"dics":["2123456789","2123456790"]}}}},"responses":{"200":{"description":"Batch assign results (per-ICO success or error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchAssignFirmsResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/reporting/statistics":{"get":{"tags":["Reporting"],"summary":"Statistiky dokumentov","description":"Vrati agregovane statistiky odoslanych a prijatych dokumentov za zvolene obdobie.","operationId":"getStatistics","parameters":[{"name":"from","in":"query","schema":{"type":"string","format":"date","example":"2026-01-01"},"description":"Zaciatok obdobia (YYYY-MM-DD)"},{"name":"to","in":"query","schema":{"type":"string","format":"date","example":"2026-03-31"},"description":"Koniec obdobia (YYYY-MM-DD)"}],"responses":{"200":{"description":"Statistiky dokumentov","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatisticsResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/reporting/submissions":{"get":{"tags":["Reporting"],"summary":"List EUSR/TSR submissions to OpenPeppol","description":"Paginated read-only history of EUSR/TSR statistics reports submitted by ePošťák as a Peppol AP operator to OpenPeppol. Internal fields (checksum, raw error message, receiver ID) are intentionally omitted; clients receive a `has_error` boolean instead.\n\nThis is a global operator-level history (not per-firm), reflecting that EUSR/TSR are AP-operator obligations.","operationId":"listReportingSubmissions","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0}},{"name":"report_type","in":"query","required":false,"schema":{"type":"string","enum":["EUSR","TSR"]}}],"responses":{"200":{"description":"Paginated list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportingSubmissionsResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"422":{"description":"Invalid query parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/audit":{"get":{"tags":["Account"],"summary":"Audit event feed (Wave 3.4)","description":"Per-firm security/auth audit log. Tenant-isolated by firmId from JWT (sk_live_*) or X-Firm-Id header (sk_int_*). Cursor pagination over `(occurred_at DESC, id DESC)`.\n\n**Requires `audit:read` scope and an API-eligible actor: `api-enterprise` directly, or `integrator-managed` through the managing integrator.**","operationId":"listAuditEvents","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"event","in":"query","schema":{"type":"string"},"description":"Exact event name match (e.g. `jwt.issued`, `webhook.created`)"},{"name":"actor_type","in":"query","schema":{"type":"string","enum":["user","apiKey","integratorKey","system"]}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque cursor from previous response's `next_cursor`"}],"responses":{"200":{"description":"Audit events","content":{"application/json":{"schema":{"type":"object","required":["items","has_more"],"properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"occurred_at":{"type":"string","format":"date-time"},"actor_type":{"type":"string"},"actor_id":{"type":"string","nullable":true},"event":{"type":"string"},"target_type":{"type":"string","nullable":true},"target_id":{"type":"string","nullable":true},"ip":{"type":"string","nullable":true},"user_agent":{"type":"string","nullable":true},"metadata":{"type":"object","additionalProperties":true,"nullable":true}}}},"next_cursor":{"type":"string","nullable":true},"has_more":{"type":"boolean"}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Plan does not allow this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/validate":{"post":{"tags":["Validation"],"summary":"Public UBL validator (no auth)","description":"**Public endpoint — NOT under `/api/v1/`.** Full path: `https://epostak.sk/api/validate`.\n\nValidator-as-a-service. Anyone can POST UBL XML (or `{ xml: \"...\" }` JSON) and get back the full 3-layer report our own send pipeline runs: UBL 2.1 XSD, EN 16931, Peppol BIS 3.0 schematrons. Rate-limited per-IP to 20/min. Body cap: 2 MB. Designed as a dry-run hook for integrators pre-signup.\n\nServer: `https://epostak.sk` (override the `/api/v1` server shown elsewhere).","operationId":"validatePublic","servers":[{"url":"https://epostak.sk/api","description":"Public base (no /v1 prefix)"}],"security":[],"requestBody":{"required":true,"content":{"application/xml":{"schema":{"type":"string","format":"xml"}},"application/json":{"schema":{"type":"object","required":["xml"],"properties":{"xml":{"type":"string"}}}}}},"responses":{"200":{"description":"Validation report (3-layer)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Malformed request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Payload too large (> 2 MB)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"body.xml is required or empty body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded (20/min/IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"503":{"description":"ion-docval unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/inbound/import":{"post":{"tags":["Pull API — Inbound"],"summary":"Import received UBL document","description":"Stores a UBL billing document received outside the Peppol network (email, SFTP, migration from another access point) in the same inbound document store as Peppol receipts. Accepts raw `application/xml` or `application/json` with an `xml` field. The XML receiver Peppol ID must match the authenticated firm. Emits `document.received` after the row is stored.","operationId":"importInboundDocument","requestBody":{"required":true,"content":{"application/xml":{"schema":{"type":"string","format":"xml"}},"text/xml":{"schema":{"type":"string","format":"xml"}},"application/json":{"schema":{"$ref":"#/components/schemas/InboundImportRequest"}}}},"responses":{"201":{"description":"Document imported","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundImportResponse"}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires documents:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Invalid XML, unsupported document type, or receiver Peppol ID does not match this firm","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/inbound/documents":{"get":{"tags":["Pull API — Inbound"],"summary":"List inbound documents","description":"Cursor-based list of documents received from Peppol. Returns newest-first by default. Use ?since= cursor for forward-paging (oldest-to-newest order is ascending).\n\n**Auth:** scope `documents:read`, plan `api-enterprise` directly, or `integrator-managed` through the managing integrator.\n\nResponse shape is produced by `formatInboundDocument`.","operationId":"listInboundDocuments","parameters":[{"name":"since","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque versioned cursor from previous response next_cursor. Omit to start from beginning."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"name":"kind","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by doctype key (invoice, credit_note, etc.)"},{"name":"sender","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by sender Peppol ID (exact match)"}],"responses":{"200":{"description":"Paginated list of inbound documents","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundDocumentsListResponse"}}}},"400":{"description":"Invalid query parameters (e.g. malformed cursor, limit out of range)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires api-enterprise directly or integrator-managed through the managing integrator, scope documents:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/inbound/documents/{id}":{"get":{"tags":["Pull API — Inbound"],"summary":"Get inbound document","description":"Fetch a single inbound document by ID. 404 when the document does not exist or belongs to a different tenant.","operationId":"getInboundDocument","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Document ID"}],"responses":{"200":{"description":"Inbound document","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundDocument"}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires api-enterprise directly or integrator-managed through the managing integrator, scope documents:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Document not found or does not belong to this tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/inbound/documents/{id}/ubl":{"get":{"tags":["Pull API — Inbound"],"summary":"Get raw UBL XML for inbound document","description":"Returns the raw AS4-received UBL XML. 404 when no rawXmlPath stored (documents received before the raw-archive feature was enabled).\n\n**Response:**  with .","operationId":"getInboundDocumentUbl","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Raw UBL XML","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/xml":{"schema":{"type":"string","format":"xml"}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires api-enterprise directly or integrator-managed through the managing integrator, scope documents:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Document not found or does not belong to this tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/inbound/documents/{id}/ack":{"post":{"tags":["Pull API — Inbound"],"summary":"Acknowledge inbound document","description":"Mark an inbound document as acknowledged by the client. Idempotent — calling again with a new client_reference overwrites the previous one (latest-ack-wins).\n\n**Auth:** scope `documents:write` (NOT `documents:read` — this is a write operation).\n\n**Response:** Returns the full document shape post-ack.","operationId":"ackInboundDocument","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundAckRequest"}}}},"responses":{"200":{"description":"Document acknowledged; returns updated document shape","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundDocument"}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires api-enterprise directly or integrator-managed through the managing integrator, scope documents:write)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Document not found or does not belong to this tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/outbound/documents":{"get":{"tags":["Pull API — Outbound"],"summary":"List outbound documents","description":"Cursor-based list of outbound documents (both Invoice-backed billing and PeppolDocument non-billing). Merged and sorted newest-first. Uses a union cursor (-prefixed base64url, v=1) to correctly paginate across two source tables.\n\n**Auth:** scope `documents:read`, plan `api-enterprise` directly, or `integrator-managed` through the managing integrator.","operationId":"listOutboundDocuments","parameters":[{"name":"since","in":"query","required":false,"schema":{"type":"string"},"description":"Union cursor from previous next_cursor"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"name":"kind","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by doctype key"},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["queued","sending","sent","delivered","failed","dead"]},"description":"Filter by transport_status"},{"name":"business_status","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by invoice business_status (billing docs only)"},{"name":"recipient","in":"query","required":false,"schema":{"type":"string"},"description":"Filter by recipient Peppol ID"},{"name":"since_date","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Filter: rows created at or after this timestamp (ISO 8601)"}],"responses":{"200":{"description":"Paginated list of outbound documents","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutboundDocumentsListResponse"}}}},"400":{"description":"Invalid query params","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires api-enterprise directly or integrator-managed through the managing integrator, scope documents:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/outbound/documents/{id}":{"get":{"tags":["Pull API — Outbound"],"summary":"Get outbound document","description":"Fetch a single outbound document by ID. Probes Invoice and PeppolDocument tables. The detail view includes attempt_history (delivery attempts) which is absent from the list view.","operationId":"getOutboundDocument","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Outbound document with attempt_history populated","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutboundDocument"}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires api-enterprise directly or integrator-managed through the managing integrator, scope documents:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Document not found or does not belong to this tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/outbound/documents/{id}/ubl":{"get":{"tags":["Pull API — Outbound"],"summary":"Get raw UBL XML for outbound document","description":"Returns the raw UBL XML. Probes Invoice.ublXmlPath then PeppolDocument.rawXmlPath, returning whichever is populated first. 404 when neither path is stored.","operationId":"getOutboundDocumentUbl","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Raw UBL XML","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/xml":{"schema":{"type":"string","format":"xml"}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires api-enterprise directly or integrator-managed through the managing integrator, scope documents:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Document not found or does not belong to this tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/outbound/documents/{id}/mdn":{"get":{"tags":["Pull API — Outbound"],"summary":"Get raw AS4 MDN receipt for outbound document","description":"Returns the raw AS4 signal-message receipt (MDN/receipt) for an outbound document when it has been forward-retained in the evidence archive. This endpoint is for audit/dispute scenarios; normal delivery tracking should use `transport_status`, `delivered_at`, or webhooks/events. 404 when the document is missing, foreign-tenant, not outbound, or no retained MDN receipt exists yet.","operationId":"getOutboundDocumentMdn","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Raw AS4 receipt bytes. Headers include X-MDN-Message-Id, X-MDN-Ref-To-Message-Id, X-MDN-SHA256, and X-MDN-Received-At.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/xml":{"schema":{"type":"string","format":"xml"}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires api-enterprise directly or integrator-managed through the managing integrator, scope documents:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Document not found, not outbound, or no retained MDN receipt exists yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"MDN evidence integrity check failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/outbound/events":{"get":{"tags":["Pull API — Outbound"],"summary":"Outbound document lifecycle event stream","description":"Cursor-based stream of outbound document lifecycle events (DocumentEvent table). Sorted oldest-to-newest (ascending) — a saved cursor naturally consumes events forward in time.\n\n**Coverage:** Invoice-backed events only in v1. Non-billing outbound docs (Order, DespatchAdvice, etc.) are tracked by polling /outbound/documents directly.\n\n**Auth:** scope `documents:read`, plan `api-enterprise` directly, or `integrator-managed` through the managing integrator.","operationId":"getOutboundEvents","parameters":[{"name":"since","in":"query","required":false,"schema":{"type":"string"},"description":"Versioned cursor from previous next_cursor"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"name":"document_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Filter to events for a specific document ID"}],"responses":{"200":{"description":"Paginated event stream","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutboundEventsListResponse"}}}},"400":{"description":"Invalid cursor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires api-enterprise directly or integrator-managed through the managing integrator, scope documents:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/company/search":{"get":{"tags":["Peppol"],"summary":"Search companies by name","description":"Full-text search against the Slovak company registry (ARES/FinStat). Returns matches scored by relevance. Minimum 2-character query.\n\n**Auth:** scope `peppol:lookup`, API-eligible actor.","operationId":"searchCompanies","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2},"description":"Search query (company name, minimum 2 chars)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":10}}],"responses":{"200":{"description":"Company search results","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"401":{"description":"Invalid or missing API key / JWT","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient plan or scope (requires api-enterprise directly or integrator-managed through the managing integrator, scope documents:read)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"429":{"description":"Rate limit exceeded","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/connector/zen-input":{"post":{"tags":["Connector"],"summary":"Connector Zen input","description":"Tolerant Connector V2 entry point for ERP documents. Send customerRef and looser ERP invoice JSON such as invoiceNo, receiver.peppolId and lines; ePošťák normalizes it into a Connector Autopilot request, resolves the Connector Mailbox, and then validates, stages, schedules or sends through the same lifecycle. No X-Firm-Id header is needed. Set previewOnly=true to inspect normalization and repair hints without storing or sending.","operationId":"connectorZenInput","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["customerRef"],"properties":{"customerRef":{"type":"string","description":"ERP customer/company reference mapped to a Connector Mailbox."},"previewOnly":{"type":"boolean","description":"When true, returns the normalized Autopilot request and repair hints without storing or sending."},"mode":{"type":"string","enum":["shadow","stage","send"],"default":"stage"},"externalId":{"type":"string","nullable":true},"idempotencyKey":{"type":"string","nullable":true},"invoiceNo":{"type":"string","description":"Loose alias for invoiceNumber; used as externalId when externalId is not provided."},"invoiceNumber":{"type":"string"},"receiverPeppolId":{"type":"string"},"receiver":{"type":"object","additionalProperties":true,"properties":{"peppolId":{"type":"string"},"name":{"type":"string"}}},"buyer":{"type":"object","additionalProperties":true},"customer":{"type":"object","additionalProperties":true},"lines":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"name":{"type":"string"},"description":{"type":"string"},"qty":{"type":"number"},"quantity":{"type":"number"},"price":{"type":"number"},"unitPrice":{"type":"number"},"vat":{"type":"number"},"vatRate":{"type":"number"}}}},"items":{"type":"array","items":{"type":"object","additionalProperties":true}},"send":{"type":"object","additionalProperties":false,"properties":{"policy":{"type":"string","enum":["stage_only","immediate","scheduled_at","daily_batch","paused"]},"sendAt":{"type":"string","format":"date-time","nullable":true}}}},"additionalProperties":true},"example":{"customerRef":"cust-acme","mode":"stage","invoiceNo":"FA-2026-001","receiver":{"peppolId":"0245:2020123456"},"lines":[{"name":"Service","qty":1,"price":100,"vat":23}],"send":{"policy":"stage_only"}}}}},"responses":{"200":{"description":"Normalization preview or idempotent Autopilot replay","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"201":{"description":"Input normalized and Autopilot run stored","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden or insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Required fields are missing; response includes repair hints","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/connector/mapper":{"post":{"tags":["Connector"],"summary":"Connector Mapper","description":"ERP-facing entry point for saved Connector Mapper templates. After one setup in Connector Mapper Studio, send the ERP export with templateKey; ePošťák maps CSV, XML, JSON, PDF text or plain text into a Connector Autopilot request, returns a launch checklist, and can preview, stage or send according to execute. No UBL/BIS3 implementation is required in the ERP.","operationId":"connectorMapper","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"templateKey":{"type":"string","description":"Saved mapping template key from Connector Mapper Studio."},"sourceType":{"type":"string","enum":["json","csv","xml","pdf_text","text"],"default":"json"},"sourceText":{"type":"string","description":"Raw CSV, XML, PDF text or plain ERP export."},"sourceJson":{"type":"object","additionalProperties":true,"description":"Raw ERP JSON export when sourceType=json."},"customerRef":{"type":"string","description":"Optional override for the Connector Mailbox customerRef stored in the template defaults."},"execute":{"type":"string","enum":["preview","stage","send"],"default":"preview"},"confirmed":{"type":"boolean","description":"Required for send, and for uncertain mapping confirmations."},"fieldMap":{"type":"object","additionalProperties":true,"description":"Optional per-call field map override."},"defaults":{"type":"object","additionalProperties":true,"description":"Optional per-call default values such as currency or customerRef."}},"additionalProperties":true},"example":{"templateKey":"pohoda-csv-v1","sourceType":"csv","execute":"stage","sourceText":"Doklad,PeppolID,Partner,Popis,Pocet,CenaBezDph,Sadzba\nFA-2026-001,0245:2020123456,Odberatel s.r.o.,Servis,1,100,23"}}}},"responses":{"200":{"description":"Mapping preview or ready launch checklist","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"201":{"description":"Mapped payload was staged or sent through Connector Autopilot","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"404":{"description":"Mapping template was not found for the integrator","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Requested send was not performed, for example Autopilot returned a replayed staged run","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"413":{"description":"Request body is too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Required mapping fields are missing or confirmations are required","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/connector/autopilot":{"post":{"tags":["Connector"],"summary":"Connector Autopilot","description":"Primary Connector V2 entry point for ERP documents. Send customerRef, externalId, idempotencyKey and payload; ePošťák resolves the Connector Mailbox, verifies firm consent, stores lifecycle state, and validates, stages, schedules, batches or sends according to mode and send.policy.","operationId":"connectorAutopilot","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["customerRef","mode","payload"],"properties":{"mode":{"type":"string","enum":["shadow","stage","send"]},"externalId":{"type":"string","nullable":true},"idempotencyKey":{"type":"string","nullable":true},"payload":{"type":"object","additionalProperties":true},"options":{"type":"object","additionalProperties":true},"customerRef":{"type":"string","description":"ERP customer/company reference mapped to a Connector Mailbox."},"send":{"type":"object","additionalProperties":false,"properties":{"policy":{"type":"string","enum":["stage_only","immediate","scheduled_at","daily_batch","paused"]},"sendAt":{"type":"string","format":"date-time","nullable":true}}}}},"example":{"customerRef":"cust-acme","mode":"shadow","externalId":"ERP-FA-2026-001","idempotencyKey":"erp-fa-2026-001","payload":{"receiverPeppolId":"0245:2123456789","items":[{"description":"Service","quantity":1,"unitPrice":100,"vatRate":23}]}}}}},"responses":{"200":{"description":"Idempotent replay of an existing run"},"201":{"description":"Autopilot run stored","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"409":{"description":"Idempotency or external ID replay with a different payload"},"422":{"description":"Autopilot run needs repair before it can be sent"}}}},"/connector/autopilot/{autopilotId}":{"get":{"tags":["Connector"],"summary":"Get Connector Autopilot run","operationId":"connectorGetAutopilotRun","parameters":[{"name":"autopilotId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Autopilot lifecycle state, repair report, links, and send/status snapshots"},"404":{"description":"Autopilot run not found"}}}},"/connector/autopilot/{autopilotId}/send":{"post":{"tags":["Connector"],"summary":"Send Connector Autopilot run","operationId":"connectorSendAutopilotRun","parameters":[{"name":"autopilotId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Run sent or idempotently already sent"},"422":{"description":"Run needs repair before sending"},"503":{"description":"External send failure; retry with the same run"}}}},"/connector/reconcile":{"get":{"tags":["Connector"],"summary":"Connector reconciliation","description":"Polling-first reconciliation API for ERP sync. Returns exceptions such as Autopilot runs needing repair, unsent outbox items, failed sends, and unacknowledged inbound documents.","operationId":"connectorReconcile","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["exceptions","all"],"default":"exceptions"}},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Reconciliation items"},"422":{"description":"Invalid reconciliation filter"}}}},"/connector/preflight":{"post":{"tags":["Connector"],"summary":"Connector preflight repair report","description":"Connector is the simplest recommended start for ERP teams: fast test connection, polling-first, no webhook setup required at the start. It is a managed flow over the Enterprise API, not a separate lower-quality API. Enterprise API remains available for full control with the same credentials and documentId. SAPI is standards compatibility mode; Connector is ePošťák-specific and not SAPI-compatible. We do not claim global superiority over Storecove; the focus is Slovakia-native integration, repair report feedback, and simple polling operations. A test connection is typically possible in one day after access approval and prepared payloads.\n\nValidate receiver reachability and payload readiness before sending. Returns a repair report that ERP teams can show or map back into their local data model.","operationId":"connectorPreflight","parameters":[{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorPreflightRequest"}}}},"responses":{"200":{"description":"Repair report and readiness result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorPreflightResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed; inspect repair report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorPreflightResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/send":{"post":{"tags":["Connector"],"summary":"Connector send","description":"Connector is the simplest recommended start for ERP teams: fast test connection, polling-first, no webhook setup required at the start. It is a managed flow over the Enterprise API, not a separate lower-quality API. Enterprise API remains available for full control with the same credentials and documentId. SAPI is standards compatibility mode; Connector is ePošťák-specific and not SAPI-compatible. We do not claim global superiority over Storecove; the focus is Slovakia-native integration, repair report feedback, and simple polling operations. A test connection is typically possible in one day after access approval and prepared payloads.\n\nAccepts an ERP document payload and returns the same documentId used by the full Enterprise API status, evidence, and document endpoints.","operationId":"connectorSend","parameters":[{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorSendRequest"}}}},"responses":{"201":{"description":"Document created and queued/sent through the Enterprise send path","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorSendResponse"}}}},"202":{"description":"Accepted for Peppol dispatch when Enterprise send is still completing a persistence/update step","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorSendResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation failed; run preflight for repair details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorPreflightResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/outbox":{"get":{"tags":["Connector"],"summary":"Connector outbox list","description":"Lists prepared outbound invoices for ERP polling. Use this to review ready, blocked, scheduled, sent, failed, or cancelled Connector outbox items before or after send.","operationId":"connectorListOutbox","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["ready","blocked","scheduled","sending","sent","failed","cancelled"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0}},{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"responses":{"200":{"description":"Connector outbox items","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorOutboxListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Connector"],"summary":"Connector outbox stage now / send later","description":"Prepares one or more ERP invoices without sending immediately: stage now and send later. Each item runs Enterprise preflight and stores a repair report. Ready items can be sent later through Connector outbox send endpoints.","operationId":"connectorStageOutbox","parameters":[{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorOutboxStageRequest"}}}},"responses":{"201":{"description":"Outbox items prepared","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorOutboxStageResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Invalid staging request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/outbox/{outboxId}":{"get":{"tags":["Connector"],"summary":"Connector outbox detail","description":"Returns one prepared outbound item including repair report, send link, and documentId after send.","operationId":"connectorGetOutboxItem","parameters":[{"name":"outboxId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"responses":{"200":{"description":"Connector outbox item","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorOutboxItem"}}}},"404":{"description":"Outbox item not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]},"delete":{"tags":["Connector"],"summary":"Connector outbox cancel","description":"Cancels a prepared item before send. Already-sent Peppol invoices cannot be cancelled through Connector outbox.","operationId":"connectorCancelOutboxItem","parameters":[{"name":"outboxId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"responses":{"200":{"description":"Outbox item cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorOutboxItem"}}}},"422":{"description":"Item can no longer be cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/outbox/{outboxId}/send":{"post":{"tags":["Connector"],"summary":"Connector outbox send","description":"Sends one ready, scheduled, or failed prepared item through the existing Connector send flow. Blocked items return their repair report and are not sent.","operationId":"connectorSendOutboxItem","parameters":[{"name":"outboxId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"force":{"type":"boolean","description":"Send before scheduledFor when true."}}}}}},"responses":{"200":{"description":"Outbox item sent or idempotently already sent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorOutboxItem"}}}},"422":{"description":"Outbox item is blocked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorOutboxItem"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/outbox/send":{"post":{"tags":["Connector"],"summary":"Connector outbox bulk send","description":"Sends ready or failed outbox items in bulk. Without ids it sends ready, failed, and due scheduled items. With ids it sends specific items and returns per-item results.","operationId":"connectorSendOutboxBatch","parameters":[{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorOutboxBatchSendRequest"}}}},"responses":{"200":{"description":"Per-item send results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorOutboxBatchSendResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/status/{documentId}":{"get":{"tags":["Connector"],"summary":"Connector document status","description":"Polling-first status endpoint for a sent document. The documentId is shared with Enterprise API, so integrators can move to full Enterprise endpoints without remapping IDs.","operationId":"connectorGetStatus","parameters":[{"name":"documentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Document ID returned by Connector or Enterprise API send."},{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorStatusResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/inbox":{"get":{"tags":["Connector"],"summary":"Connector inbox","description":"Polling-first inbox for ERP import. No webhook receiver is required; persist the cursor and acknowledge documents after successful local processing.","operationId":"connectorListInbox","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from the previous response."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Maximum documents to return. Default 20, max 100."},{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorInboxListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/inbox/{documentId}":{"get":{"tags":["Connector"],"summary":"Connector inbox detail","description":"Returns one received document for ERP import, including structured fields and the original UBL/XML reference.","operationId":"connectorGetInboxDocument","parameters":[{"name":"documentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Document ID returned by Connector or Enterprise API send."},{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorInboxDocument"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/inbox/{documentId}/ack":{"post":{"tags":["Connector"],"summary":"Connector inbox ack","description":"Idempotently confirms that the ERP processed a received document. Intended for polling-first import jobs.","operationId":"connectorAckInboxDocument","parameters":[{"name":"documentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Document ID returned by Connector or Enterprise API send."},{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"responses":{"200":{"description":"Acknowledged","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorAckResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/events":{"get":{"tags":["Connector"],"summary":"Connector events","description":"Polling-first event stream for ERP jobs. This is a simplified managed-flow view over Enterprise events, with the full Enterprise API available when more control is needed.","operationId":"connectorListEvents","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from the previous response."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}},{"name":"X-Firm-Id","in":"header","required":false,"schema":{"type":"string","format":"uuid"},"description":"Required when the JWT was minted from an sk_int_* integrator key and the call targets one managed firm."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorEventsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearerAuth":[]}]}},"/connector/mailbox":{"get":{"tags":["Connector"],"summary":"Connector Mailbox readiness","description":"Returns Connector Mailbox readiness for every firm managed by the integrator. No X-Firm-Id header is required; this is an integrator-level endpoint.","operationId":"connectorListMailboxes","parameters":[],"responses":{"200":{"description":"Mailbox list and readiness","content":{"application/json":{"schema":{"type":"object","properties":{"mailboxes":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/connector/mailbox/repair":{"post":{"tags":["Connector"],"summary":"Repair Connector Mailbox setup","description":"Creates or repairs Connector Mailbox setup and the internal pull subscriptions for all managed firms, or for one customerRef when provided.","operationId":"connectorRepairMailboxes","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"customerRef":{"type":"string"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Repair summary","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/connector/mailbox/{customerRef}/send-policy":{"patch":{"tags":["Connector"],"summary":"Update Connector Mailbox send policy","description":"Configures when documents for one managed firm should be sent: stage only, immediate, scheduled, daily batch, or paused.","operationId":"connectorUpdateMailboxSendPolicy","parameters":[{"name":"customerRef","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["policy"],"properties":{"policy":{"type":"string","enum":["stage_only","immediate","scheduled_at","daily_batch","paused"]},"sendAt":{"type":"string","format":"date-time"}},"additionalProperties":true}}}},"responses":{"200":{"description":"Updated mailbox","content":{"application/json":{"schema":{"type":"object","properties":{"mailbox":{"type":"object","additionalProperties":true}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Mailbox not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/connector/sync":{"get":{"tags":["Connector"],"summary":"Connector unified feed","description":"One cursor-based feed for ERP integrations: mailbox readiness, outbox, Autopilot, documents, MLR/MLS, InvoiceResponse, TDD evidence and pending actions. No X-Firm-Id header is required.","operationId":"connectorSyncFeed","parameters":[{"name":"customerRef","in":"query","required":false,"schema":{"type":"string"},"description":"Filter to one managed customer reference."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque cursor from the previous response."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"Cursor-paged Connector feed","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","additionalProperties":true}},"nextCursor":{"type":"string","nullable":true},"hasMore":{"type":"boolean"}}}}}},"400":{"description":"Invalid cursor or limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/connector/documents/{documentId}":{"get":{"tags":["Connector"],"summary":"Connector document lifecycle","description":"Returns one document in an ERP-friendly lifecycle shape: status, AS4 delivery, MLR/MLS, InvoiceResponse, TDD, evidence links, and recommended next actions. Visibility is limited to documents created after the firm granted consent to the integrator.","operationId":"connectorGetDocumentLifecycle","parameters":[{"name":"documentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Document lifecycle","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/connector/documents/{documentId}/ubl":{"get":{"tags":["Connector"],"summary":"Connector document UBL","description":"Downloads the original UBL/XML for a managed document. Visibility is limited to documents created after firm consent.","operationId":"connectorGetDocumentUbl","parameters":[{"name":"documentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"UBL/XML document","content":{"application/xml":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/connector/documents/{documentId}/evidence":{"get":{"tags":["Connector"],"summary":"Connector document evidence","description":"Returns structured AS4, MLR/MLS, InvoiceResponse, TDD and timestamp evidence for one document.","operationId":"connectorGetDocumentEvidence","parameters":[{"name":"documentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Structured evidence","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/connector/documents/{documentId}/evidence-bundle":{"get":{"tags":["Connector"],"summary":"Connector evidence bundle manifest","description":"Returns an evidence-bundle manifest without internal storage paths: UBL link, AS4, MLR/MLS, InvoiceResponse, TDD and timestamps.","operationId":"connectorGetDocumentEvidenceBundle","parameters":[{"name":"documentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Evidence bundle manifest","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/connector/actions/{actionId}":{"post":{"tags":["Connector"],"summary":"Execute Connector action","description":"Executes an action returned by /connector/sync through its href. The actionId can be a stored ConnectorAction UUID or a stable synthetic ID such as confirm:{outboxId}, reschedule:{outboxId}, ack_inbound:{documentId}, or send:{autopilotId}. Integrators do not need X-Firm-Id.","operationId":"connectorRunAction","parameters":[{"name":"actionId","in":"path","required":true,"schema":{"type":"string"},"description":"Action ID from the sync feed; use the encoded href returned by the feed."}],"responses":{"200":{"description":"Action completed","content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"object","additionalProperties":true}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Action not executable by this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"sendAt":{"type":"string","format":"date-time","description":"Required for reschedule_send synthetic actions."},"status":{"type":"string","description":"Invoice response status for respond_invoice actions."},"note":{"type":"string"}}},"examples":{"reschedule":{"value":{"sendAt":"2026-06-10T16:00:00+02:00"}},"invoiceResponse":{"value":{"status":"AP","note":"Accepted by ERP"}}}}}}}},"/payloads/extract":{"post":{"tags":["Payload Assistant"],"summary":"Extract payload fields from PDF or image","description":"Preferred Payload Assistant alias for OCR extraction. Returns the same response as /extract; the legacy path remains supported.","operationId":"payloadExtractDocument","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"PDF alebo obrazok faktury (max 20 MB)"}}}}}},"responses":{"200":{"description":"Extrakcia uspesna","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Chybajuci subor, nepodporovany typ alebo prilis velky subor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleErrorResponse"}}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleErrorResponse"}}}},"422":{"description":"Extrakcia alebo UBL generovanie zlyhalo. Vystavene/outbound PDF faktury vracaju 200 s direction=outbound; standardne faktury obsahuju send_payload na kontrolu.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractErrorResponse"}}}},"429":{"description":"Rate limit exceeded (10/min/firm)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"503":{"description":"Gemini API key not configured (SERVICE_UNAVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/payloads/extract/batch":{"post":{"tags":["Payload Assistant"],"summary":"Batch OCR extraction for payload creation","description":"Preferred Payload Assistant alias for batch OCR extraction. Returns the same response as /extract/batch; the legacy path remains supported.","operationId":"payloadExtractBatch","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["files"],"properties":{"files":{"type":"array","items":{"type":"string","format":"binary"},"maxItems":50,"description":"PDF or image files"}}}}}},"responses":{"200":{"description":"Batch extraction results (per-file success or error)","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Total body exceeds 200 MB or individual file > 20 MB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded (3/min/firm)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"503":{"description":"Gemini API not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/payloads/parse":{"post":{"tags":["Payload Assistant"],"summary":"Parse raw UBL into normalized JSON","description":"Preferred Payload Assistant alias for parsing UBL/XML into normalized JSON. The legacy /documents/parse path remains supported.","operationId":"payloadParseDocument","requestBody":{"required":true,"content":{"application/xml":{"schema":{"type":"string","format":"xml"}},"application/json":{"schema":{"type":"object","required":["xml"],"properties":{"xml":{"type":"string","description":"UBL Invoice or CreditNote XML"}}}}}},"responses":{"200":{"description":"Parsed invoice payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParseResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Payload too large (> 10 MB)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation or parse error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/payloads/convert":{"post":{"tags":["Payload Assistant"],"summary":"Convert payload formats","description":"Preferred Payload Assistant alias for converting supported document payload formats. The legacy /documents/convert path remains supported.","operationId":"payloadConvertDocument","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertDocumentRequest"},"examples":{"jsonToUbl":{"summary":"JSON → UBL","value":{"input_format":"json","output_format":"ubl","document":{"invoiceNumber":"FAK-001","items":[{"description":"Sluzba s prenesenim DPH","quantity":1,"unitPrice":200,"vatRate":0,"vatCategoryCode":"AE"}]}}},"ublToJson":{"summary":"UBL → JSON","value":{"input_format":"ubl","output_format":"json","document":"<?xml version=\"1.0\"?>..."}}}}}},"responses":{"200":{"description":"Konverzia uspesna. Pre `output_format=ubl` je `document` string, pre `output_format=json` je objekt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertDocumentResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Payload too large (> 6 MB)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Konverzia zlyhala alebo nepodporovana kombinacia input_format/output_format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Backend conversion service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/payloads/validate":{"post":{"tags":["Payload Assistant"],"summary":"Validate payload without sending","description":"Preferred Payload Assistant alias for preflight document validation. The legacy /documents/validate path remains supported.","operationId":"payloadValidateDocument","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SendDocumentJsonRequest"},{"$ref":"#/components/schemas/SendDocumentXmlRequest"}]}}}},"responses":{"200":{"description":"Validacia uspesna","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateDocumentResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"413":{"description":"Payload too large (> 6 MB)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"UBL validation error (schematron rule failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UblValidationError"}}}},"503":{"description":"VALIDATION_SERVICE_UNAVAILABLE — ion-docval unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/events/pull":{"get":{"tags":["Webhooks & Events"],"summary":"Pull unacknowledged events","description":"Preferred Events facade for polling queued webhook events in the Enterprise reliability contract. After send, poll unacknowledged events and acknowledge after local commit in the ERP; if processing fails, leave the event unacknowledged and pull it again. The server keeps state through acknowledgements, so clients do not need client-side cursor bookkeeping. The legacy /webhook-queue path remains supported as a compatibility queue.","operationId":"eventsPull","responses":{"200":{"description":"Zoznam cakajucich udalosti","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsPullResponse"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}}}}},"/events/batch-ack":{"post":{"tags":["Webhooks & Events"],"summary":"Acknowledge multiple events","description":"Preferred Events alias for batch acknowledgement. Enterprise reliability contract: acknowledge after local commit, not when the event is fetched. Use this after a batch import commit; on retry, leave events unacknowledged and read them again from /events/pull. Returns the same response as /webhook-queue/batch-ack; the legacy path remains supported.","operationId":"eventsBatchAck","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event_ids"],"properties":{"event_ids":{"type":"array","items":{"type":"string"},"example":["evt_1","evt_2","evt_3"],"description":"Zoznam ID udalosti na potvrdenie"}}}}}},"responses":{"200":{"description":"Udalosti potvrdene","content":{"application/json":{"schema":{"type":"object","properties":{"acknowledged":{"type":"integer","example":3,"description":"Pocet potvrdenych udalosti"}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"400":{"description":"Chybajuci alebo prazdny zoznam event_ids","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}}}}},"/events/{eventId}/ack":{"post":{"tags":["Webhooks & Events"],"summary":"Acknowledge one event","description":"Preferred Events alias for acknowledging one queued event. It performs the same acknowledgement as DELETE /webhook-queue/{eventId}; the legacy path remains supported.","operationId":"eventsAck","parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"},"description":"ID udalosti"}],"responses":{"200":{"description":"Udalost potvrdena","content":{"application/json":{"schema":{"type":"object","properties":{"acknowledged":{"type":"boolean","example":true}}}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}}},"401":{"description":"Neplatny alebo chybajuci API kluc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan je vyzadovany","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"}}}},"404":{"description":"Udalost nenajdena","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/evidence-bundle":{"get":{"tags":["Lifecycle & proof"],"summary":"Evidence ZIP bundle","description":"Returns a ZIP bundle for audit, dispute handling or support: manifest.json, evidence.json, UBL XML, PDF and available AS4/MDN artifacts.","operationId":"getDocumentEvidenceBundle","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Document ID"}],"responses":{"200":{"description":"Evidence ZIP bundle","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Evidence bundle too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"MDN evidence integrity check failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/documents/{id}/support-packet":{"get":{"tags":["Lifecycle & proof"],"summary":"Document support packet","description":"Preferred Lifecycle & proof alias for the document evidence ZIP bundle. Enterprise reliability contract final step: store requestId, documentId/submissionId, messageId, payloadSha256 and support-packet for incidents instead of sending full XML when a hash and evidence bundle are enough. Returns the same ZIP artifacts as /documents/{id}/evidence-bundle; the legacy path remains supported.","operationId":"getDocumentSupportPacket","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Document ID"}],"responses":{"200":{"description":"Document support packet","content":{"application/zip":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"API plan required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Support packet too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"MDN evidence integrity check failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/connector/documents/{documentId}/support-packet":{"get":{"tags":["Connector"],"summary":"Connector document support packet","description":"Preferred Connector alias for the document support/evidence manifest. Returns the same manifest as /connector/documents/{documentId}/evidence-bundle; the legacy path remains supported.","operationId":"connectorGetDocumentSupportPacket","parameters":[{"name":"documentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Support packet manifest","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth 2.0 client_credentials JWT access token (15 min TTL).\n\n**Obtain a token:** `POST /api/v1/auth/token` with the `client_id` shown with the key plus `client_secret` (the full `sk_live_*` or `sk_int_*` API key). Response contains `access_token` (JWT) and `refresh_token`.\n\n**Use the JWT:** `Authorization: Bearer eyJhbGciOiJSUzI1NiIs...`\n\n**Two key types:**\n- JWT minted from `sk_live_*` — direct firm access, no X-Firm-Id needed.\n- JWT minted from `sk_int_*` — requires `X-Firm-Id: <UUID>` header to target a specific assigned firm. For cross-firm endpoints (`/documents/inbox/all`, `/webhook-queue/all`, `/firms/assign`) X-Firm-Id is not required.\n\n**Direct API key bearer (Bearer sk_live_… or Bearer sk_int_…) is no longer accepted.**\n\nRate limit: 200 requests per minute per key."},"integratorBearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT access token minted from a `sk_int_*` integrator API key via `POST /api/v1/auth/token`. Cross-firm endpoints require no X-Firm-Id header."}},"schemas":{"LineItem":{"type":"object","required":["description","quantity","unitPrice","vatRate"],"properties":{"description":{"type":"string","example":"Konzultacne sluzby"},"quantity":{"type":"number","example":10},"unit":{"type":"string","example":"HUR","description":"Jednotka (UN/CEFACT kod). Napr. HUR=hodiny, C62=kusy, KGM=kg."},"unitPrice":{"type":"number","example":50},"vatRate":{"type":"number","enum":[0,5,10,19,20,23],"example":23,"description":"DPH sadzba v percentach; includes historical 20% for older correction documents"},"vatCategoryCode":{"type":"string","enum":["S","Z","AE","E","K","G","O","L","M"],"example":"AE","description":"DPH kategoria BT-151 podla UNCL5305. Ak chyba, odvodi sa zo sadzby: vatRate > 0 = S, vatRate 0 = Z. Pre prenesenie danovej povinnosti pouzite AE."},"vatCategory":{"type":"string","enum":["S","Z","AE","E","K","G","O","L","M"],"example":"AE","description":"Alias for vatCategoryCode."},"vat_category":{"type":"string","enum":["S","Z","AE","E","K","G","O","L","M"],"example":"AE","description":"Snake_case alias for vatCategoryCode."},"discount":{"type":"number","example":10,"description":"Zlava v percentach (volitelne)"},"deliveryDate":{"type":"string","format":"date","example":"2026-04-01","description":"Line delivery date (BT-134). ISO timestamps are accepted by the route and emitted as date-only in UBL. When line delivery dates represent a summary invoice, they must stay within one calendar month and issueDate must be no later than the 15th day after that month ends."},"lineType":{"type":"string","enum":["standard","advance_deduction"],"example":"advance_deduction","description":"Line type. Use advance_deduction for a negative advance deduction line on the final invoice."},"advanceInvoiceReference":{"type":"string","example":"ZF-2026-001","description":"Advance invoice number. Required when lineType is advance_deduction. Emitted to UBL as AdditionalItemProperty named AdvanceInvoiceNumber."},"customsTariffCode":{"type":"string","pattern":"^\\d{4,10}$","example":"72044910","description":"Customs tariff / combined nomenclature code. Emitted as CommodityClassification/ItemClassificationCode listID=HS; KV DPH A2 uses the first 4 digits as TK."},"commodityClassificationCode":{"type":"string","example":"72044910","description":"Generic item classification code when customsTariffCode is not used."},"commodityClassificationListId":{"type":"string","example":"HS","description":"Classification list identifier from UNTDID 7143. Defaults to HS for customsTariffCode."},"reverseChargeParagraphLetter":{"type":"string","example":"f","description":"Domestic §69(12) paragraph letter for reverse charge evidence. Emitted as AdditionalItemProperty."},"controlStatementType":{"type":"string","enum":["IO","MT"],"example":"MT","description":"Slovak KV DPH A2 TD value."},"controlStatementQuantity":{"type":"number","example":1250,"description":"Slovak KV DPH A2 Mn quantity."},"controlStatementUnit":{"type":"string","enum":["kg","t","m","ks"],"example":"kg","description":"Slovak KV DPH A2 MJ unit."}}},"SendDocumentJsonRequest":{"type":"object","required":["receiverPeppolId","receiverName","items"],"description":"JSON mode — UBL XML sa generuje automaticky pre standardnu fakturu. Sender fields are not accepted in this payload; the authenticated firm is used as AccountingSupplierParty. For self-billing and other ready UBL variants, use SendDocumentXmlRequest with InvoiceTypeCode 389/261 in the xml field.","properties":{"receiverPeppolId":{"type":"string","example":"0245:12345678","description":"Peppol ID prijemcu"},"invoiceNumber":{"type":"string","example":"FAK-2026-0001","description":"Cislo faktury (ak nie je zadane, generuje sa automaticky)"},"issueDate":{"type":"string","format":"date","example":"2026-04-01"},"dueDate":{"type":"string","format":"date","example":"2026-04-15"},"currency":{"type":"string","example":"EUR","default":"EUR"},"note":{"type":"string","example":"Dakujeme za objednavku."},"iban":{"type":"string","example":"SK1234567890123456789012"},"paymentMethod":{"type":"string","example":"bank_transfer"},"variableSymbol":{"type":"string","example":"20260001"},"buyerReference":{"type":"string","example":"PO-2026-99"},"receiverName":{"type":"string","example":"Zakaznik s.r.o."},"receiverIco":{"type":"string","example":"12345678"},"receiverDic":{"type":"string","example":"2020123456"},"receiverIcDph":{"type":"string","example":"SK2020123456"},"receiverStreet":{"type":"string","example":"Hlavna 1","description":"Receiver street and number. Preferred over parsing receiverAddress."},"receiverCity":{"type":"string","example":"Bratislava"},"receiverPostalCode":{"type":"string","example":"81101"},"receiverAddress":{"type":"string","example":"Hlavna 1, Bratislava, 81101"},"receiverCountry":{"type":"string","example":"SK","default":"SK"},"prepaidAmount":{"type":"number","minimum":0,"example":123,"description":"Amount paid in advance (BT-113). Emitted as LegalMonetaryTotal/PrepaidAmount and reduces PayableAmount. Do not combine with items[].lineType=advance_deduction."},"items":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/LineItem"}},"attachments":{"type":"array","maxItems":20,"description":"Prilohy faktury (BG-24). Vlozia sa do UBL XML ako base64 cez AdditionalDocumentReference / EmbeddedDocumentBinaryObject. Max 20 suborov, 10 MB na subor, 15 MB celkovo.","items":{"$ref":"#/components/schemas/DocumentAttachment"}}}},"DocumentAttachment":{"type":"object","required":["fileName","mimeType","content"],"description":"Priloha faktury zakodovana ako base64. MIME typ sa overuje magic-byte kontrolou.","properties":{"fileName":{"type":"string","maxLength":255,"example":"invoice-detail.pdf","description":"Nazov suboru"},"mimeType":{"type":"string","enum":["application/pdf","image/png","image/jpeg","text/csv","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/vnd.oasis.opendocument.spreadsheet"],"example":"application/pdf","description":"Povolene MIME typy podla BR-CL-22"},"content":{"type":"string","format":"byte","description":"Base64-encoded obsah suboru (bez data: prefixu). Max 10 MB po dekodovani.","example":"JVBERi0xLjQKJeLjz9MKMS..."},"description":{"type":"string","example":"Rozpis odpracovanych hodin","description":"Kratky popis prilohy (volitelne)"}}},"SendDocumentXmlRequest":{"type":"object","required":["receiverPeppolId","xml"],"description":"XML mode — poskytnute UBL XML sa odosle priamo v JSON poli xml. Pouzite ho pre hotovy Peppol UBL, self-billing InvoiceTypeCode 389, self-billing credit note 261 alebo ine specifika mimo JSON line-item mode.","properties":{"receiverPeppolId":{"type":"string","example":"0245:12345678"},"xml":{"type":"string","description":"Kompletne UBL XML (Invoice alebo CreditNote). Pri self-billing pouzite InvoiceTypeCode 389 alebo CreditNoteTypeCode 261.","example":"<?xml version=\"1.0\" encoding=\"UTF-8\"?><Invoice>...<cbc:InvoiceTypeCode>389</cbc:InvoiceTypeCode>...</Invoice>"}}},"SendDocumentLinks":{"type":"object","description":"Convenience links for the created outbound document submission.","properties":{"document":{"type":"string","example":"/api/v1/documents/clx1234abcdef"},"status":{"type":"string","example":"/api/v1/documents/clx1234abcdef/status"},"events":{"type":"string","example":"/api/v1/documents/clx1234abcdef/events"},"ubl":{"type":"string","example":"/api/v1/documents/clx1234abcdef/ubl"},"evidence":{"type":"string","example":"/api/v1/documents/clx1234abcdef/evidence"},"evidenceBundle":{"type":"string","example":"/api/v1/documents/clx1234abcdef/evidence-bundle"}}},"SendDocumentResponse":{"type":"object","properties":{"documentId":{"type":"string","example":"clx1234abcdef","description":"Interne ID dokumentu"},"submissionId":{"type":"string","example":"clx1234abcdef","description":"Storecove-style alias for documentId. Use this as the submission handle if your integration models sends as submissions."},"messageId":{"type":"string","example":"msg-uuid-here","description":"Peppol messageId"},"status":{"type":"string","enum":["SENT","SENT_DB_PENDING"],"example":"SENT","description":"`SENT` = HTTP 201 (delivered + local DB persisted). `SENT_DB_PENDING` = HTTP 202 (delivered via Peppol but local DB write failed; reconciled by the post-send cron). Idempotent retry of the same `Idempotency-Key` after `SENT_DB_PENDING` will replay the same response."},"payloadSha256":{"type":"string","example":"a1b2c3d4e5f60718...","description":"Lowercase-hex SHA-256 of the canonical UBL XML bytes that were placed on the AS4 wire. Receivers can verify the payload they received off Peppol matches what we logged on send. Only present in `SENT` (201) responses; absent in `SENT_DB_PENDING` (202) because the DB persist that captures it failed."},"warning":{"type":"string","description":"Human-readable explanation when `status=SENT_DB_PENDING` — describes the partial-failure mode and what reconciliation will do.","example":"Document delivered via Peppol but local status update failed — will be reconciled automatically"},"links":{"$ref":"#/components/schemas/SendDocumentLinks"}}},"PartyResponse":{"type":"object","properties":{"name":{"type":"string","example":"Moja firma s.r.o."},"ico":{"type":"string","example":"12345678"},"dic":{"type":"string","example":"2020123456"},"icDph":{"type":"string","example":"SK2020123456"},"address":{"type":"object","properties":{"street":{"type":"string","example":"Hlavna 1"},"city":{"type":"string","example":"Bratislava"},"zip":{"type":"string","example":"81101"},"country":{"type":"string","example":"SK"}}},"peppolId":{"type":"string","example":"0245:12345678"}}},"LineItemResponse":{"type":"object","properties":{"description":{"type":"string"},"quantity":{"type":"number"},"unit":{"type":"string"},"unitPrice":{"type":"number"},"vatRate":{"type":"number"},"vatCategory":{"type":"string","example":"S"},"lineTotal":{"type":"number"}}},"DocumentResponse":{"type":"object","properties":{"id":{"type":"string"},"number":{"type":"string","example":"FAK-2026-0001"},"status":{"type":"string","example":"received"},"direction":{"type":"string","enum":["inbound","outbound"]},"docType":{"type":"string","example":"invoice"},"issueDate":{"type":"string","format":"date-time"},"dueDate":{"type":"string","format":"date-time","nullable":true},"currency":{"type":"string","example":"EUR"},"supplier":{"$ref":"#/components/schemas/PartyResponse"},"customer":{"$ref":"#/components/schemas/PartyResponse"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/LineItemResponse"}},"totals":{"type":"object","properties":{"withoutVat":{"type":"number"},"vat":{"type":"number"},"withVat":{"type":"number"}}},"peppolMessageId":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"InboxListResponse":{"type":"object","properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/DocumentResponse"}},"total":{"type":"integer","example":42},"limit":{"type":"integer","example":20},"offset":{"type":"integer","example":0},"nextCursor":{"type":"string","nullable":true,"description":"Opaque cursor to fetch the next page. null when no more results.","example":"eyJpZCI6ImNseDlhYmMxMjMifQ=="}}},"OutboxListResponse":{"type":"object","properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/DocumentResponse"}},"total":{"type":"integer"},"offset":{"type":"integer"},"limit":{"type":"integer"}}},"InboxDocumentDetailResponse":{"type":"object","description":"Inbox document detail. `document` and `payload` are siblings (payload is NOT nested inside document). `document` matches the normalized shape from `lib/api/format.ts#formatInvoice` — supplier/customer are nested PartyResponse objects (supplier.peppolId carries the original sender).","properties":{"document":{"$ref":"#/components/schemas/DocumentResponse"},"payload":{"type":"string","nullable":true,"description":"UBL XML content (null if not yet retrieved from storage). Starts with `<?xml...?>`."}}},"AcknowledgeResponse":{"type":"object","properties":{"documentId":{"type":"string"},"status":{"type":"string","enum":["ACKNOWLEDGED"]},"acknowledgedAt":{"type":"string","format":"date-time"}}},"AccountResponse":{"type":"object","properties":{"firm":{"type":"object","properties":{"name":{"type":"string","example":"Moja firma s.r.o."},"ico":{"type":"string","nullable":true,"example":"12345678"},"peppolId":{"type":"string","nullable":true,"example":"0245:12345678"},"peppolStatus":{"type":"string","example":"active"}}},"plan":{"type":"object","properties":{"name":{"type":"string","example":"api-enterprise"},"status":{"type":"string","enum":["active","expired"]}}},"usage":{"type":"object","properties":{"outbound":{"type":"integer","description":"Pocet odoslanych dokumentov"},"inbound":{"type":"integer","description":"Pocet prijatych dokumentov"}}}}},"ExtractResponse":{"type":"object","properties":{"extraction":{"type":"object","description":"Extrahovane data z dokumentu"},"direction":{"type":"string","enum":["inbound","outbound"],"description":"For issued invoice PDFs this is outbound. Standard invoices include send_payload instead of treating OCR as an immediate send."},"send_payload":{"type":"object","nullable":true,"description":"Draft JSON body for POST /api/v1/documents/send. Returned for outbound standard-invoice OCR; caller must review it, fill missing fields, and submit it separately. Null for outbound document types outside the JSON send flow."},"send_payload_missing_fields":{"type":"array","items":{"type":"string"},"description":"Fields the caller must fill before POST /api/v1/documents/send, commonly receiverPeppolId."},"send_ready":{"type":"boolean","description":"True when send_payload has the blocking fields needed by /documents/send; review is still required."},"ubl_xml":{"type":"string","description":"Vygenerovane UBL XML z extrahovanych dat. Present for inbound extraction; outbound standard invoices return send_payload for review instead."},"confidence":{"type":"string","enum":["high","medium","low"],"description":"Overall confidence bucket."},"confidence_scores":{"type":"object","description":"Per-field confidence (0..1). Fields: vendor_name, vendor_ico, invoice_number, issue_date, due_date, items, subtotal, vat_total, total, currency, iban, variable_symbol.","additionalProperties":{"type":"number"}},"needs_review":{"type":"boolean","description":"True when confidence is low or medium — surface a human review UI."},"file_name":{"type":"string","example":"faktura-2026-001.pdf"}}},"ExtractErrorResponse":{"oneOf":[{"type":"object","description":"Structured error for /extract — Gemini extraction failure.","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"EXTRACTION_FAILED"},"message":{"type":"string","example":"Extraction failed"},"details":{"type":"string","description":"Gemini error detail"}}}}},{"type":"object","description":"Compatibility plain-string error for /extract — UBL generation failure path.","properties":{"error":{"type":"string","example":"UBL generation failed"},"details":{"type":"string"},"extraction":{"type":"object","description":"Partial extraction payload (so caller can retry with manual edits)"}}}]},"CreateWebhookRequest":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","example":"https://vas-system.sk/webhooks/epostak","description":"HTTPS URL (http rejected, private/loopback/metadata addresses rejected by SSRF filter)"},"events":{"type":"array","items":{"type":"string","enum":["document.created","document.sent","document.received","document.validated","document.delivered","document.rejected","document.response_received"]},"description":"Subscribed events. If omitted, subscribes to all 7.","example":["document.received","document.sent"]}}},"UpdateWebhookRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["document.created","document.sent","document.received","document.validated","document.delivered","document.rejected","document.response_received"]}},"isActive":{"type":"boolean"}}},"WebhookResponse":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"},"failedAttempts":{"type":"integer","description":"Consecutive failure counter. Webhooks auto-disable after 10 consecutive failures.","example":0},"createdAt":{"type":"string","format":"date-time"}}},"WebhookDetailResponse":{"allOf":[{"$ref":"#/components/schemas/WebhookResponse"},{"type":"object","properties":{"secret":{"type":"string","description":"HMAC-SHA256 signing secret (vrateny iba pri vytvoreni)","example":"a3f8...hex64chars"}}}]},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"webhookId":{"type":"string","description":"Per-attempt delivery ID sent as X-Webhook-Id request header. Different on each retry attempt. Distinct from idempotency_key which is per-logical-event."},"event":{"type":"string","example":"document.received"},"status":{"type":"string","enum":["PENDING","SUCCESS","FAILED","RETRYING"],"example":"SUCCESS","description":"Delivery status (UPPERCASE enum)"},"attempts":{"type":"integer","example":1},"responseStatus":{"type":"integer","nullable":true,"example":200},"createdAt":{"type":"string","format":"date-time"},"idempotency_key":{"type":"string","format":"sha256-hex","description":"Deterministic SHA-256 hex identifying the logical delivery event (per PR #112). Stable across retry attempts — two attempts for the same logical event share the same idempotency_key. Distinct from webhook_id (X-Webhook-Id header), which is per-attempt."}}},"WebhookWithDeliveriesResponse":{"allOf":[{"$ref":"#/components/schemas/WebhookResponse"},{"type":"object","properties":{"deliveries":{"type":"array","description":"Poslednych 20 doruceni","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}}]},"WebhookListResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookResponse"}}}},"ErrorResponse":{"type":"object","description":"Standard error envelope for `/api/v1/*` endpoints (excluding `/auth/token|renew|revoke` which use `PeppolErrorResponse`, and `/oauth/token` which uses RFC 6749 `OAuthErrorResponse`). The `requestId` echoes the `X-Request-Id` response header — quote it in support tickets.","required":["error"],"properties":{"error":{"type":"object","required":["code","message","requestId"],"properties":{"code":{"type":"string","description":"Machine-readable error code. Branch on this value, not only on HTTP status. Known codes:\n- VALIDATION_ERROR (422) - JSON, XML shape, or required field validation failed; fix the payload and retry.\n- UBL_VALIDATION_ERROR (422) - Peppol/CEN schematron rejection; inspect details[].rule such as BR-CO-26.\n- UNPROCESSABLE_ENTITY (422) - business rule rejection.\n- IDEMPOTENCY_KEY_MISMATCH (422) - the same Idempotency-Key was reused with a different canonicalized body.\n- IDEMPOTENCY_IN_FLIGHT (409) - the same idempotency key is still processing; wait and poll status.\n- NOT_FOUND (404).\n- FORBIDDEN (403) - plan, scope, or ownership denied.\n- CONFLICT (409) - duplicate or unique-constraint collision.\n- BAD_REQUEST (400) - malformed body or parameters.\n- INVALID_PARAM (400).\n- PAYLOAD_TOO_LARGE (413).\n- RATE_LIMITED (429) - respect Retry-After when present.\n- VALIDATION_SERVICE_UNAVAILABLE (503) - retry with backoff.\n- IDEMPOTENCY_STORE_UNAVAILABLE (503) - retry the same payload with the same Idempotency-Key.\n- SEND_FAILED (502) - Peppol AP dispatch failed, retryable when the same payload and key are used.\n- SERVICE_UNAVAILABLE (503) - upstream dependency unavailable.\n- INTERNAL_ERROR (500).\nBusiness error catalog:\n- participant_not_found (422) - retryable=false; fix_hint=change or verify the receiver Peppol ID.\n- receiver_unsupported_document_type (422) - retryable=false; fix_hint=change document type/profile or receiver capability.\n- validation_failed (422) - retryable=false; fix_hint=fix the UBL/JSON payload using details/rule.\n- temporary_transport_error (502/503) - retryable=true; fix_hint=retry with backoff and the same Idempotency-Key.\n- delivery_dead_lettered (409) - retryable=false; fix_hint=inspect events/support-packet, then retry manually or contact support.\n- duplicate_idempotency_key (422) - retryable=false; fix_hint=send the original body or use a new key for changed payload.","example":"VALIDATION_ERROR"},"message":{"type":"string","example":"receiverPeppolId is required"},"requestId":{"type":"string","format":"uuid","description":"Mirror of the `X-Request-Id` response header — for tracing."},"details":{"description":"Optional structured details (e.g., Zod error array, Peppol schematron rule IDs)"},"conflictTarget":{"type":"string","description":"On 409 from a unique-constraint collision: comma-joined target columns (e.g. `firm_id,idempotency_key`)."}}}}},"ForbiddenErrorResponse":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse"}],"description":"403 variant of `ErrorResponse`. The 401/403 responses also include `WWW-Authenticate: Bearer error=\"invalid_token\"|\"insufficient_scope\" scope=\"<required-scope>\"` per RFC 6750 — clients should parse `scope=\"…\"` to learn what scope is required."},"SimpleErrorResponse":{"type":"object","description":"Compatibility non-canonical error shape used by a few multipart upload endpoints (e.g. `/extract`). Standard endpoints use `ErrorResponse`.","properties":{"error":{"type":"string","example":"file is required (multipart/form-data field: file)"}}},"PeppolErrorResponse":{"type":"object","description":"Error envelope used by the JWT auth endpoints (`/auth/token`, `/auth/renew`, `/auth/revoke`) and any `/sapi/v1/*` endpoint. Different from `ErrorResponse` — designed for Peppol Access Point error semantics with retry hints.","required":["error"],"properties":{"error":{"type":"object","required":["category","code","message","retryable","correlation_id"],"properties":{"category":{"type":"string","enum":["AUTH","VALIDATION","PROCESSING","TEMPORARY","PERMANENT"]},"code":{"type":"string","example":"SAPI-AUTH-001","description":"Stable machine-readable code (e.g. `SAPI-AUTH-001` invalid creds, `SAPI-AUTH-008` scope denied, `SAPI-AUTH-099` internal)."},"message":{"type":"string","example":"Invalid client credentials"},"retryable":{"type":"boolean","description":"True for 5xx/429 — caller may retry with backoff."},"correlation_id":{"type":"string","format":"uuid"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"issue":{"type":"string"},"value":{"type":"string"}}}}}}}},"JwtTokenRequest":{"type":"object","required":["grant_type","client_id","client_secret"],"properties":{"grant_type":{"type":"string","enum":["client_credentials"]},"client_id":{"type":"string","description":"The client_id shown with the key. It must match the API key row UUID or displayed key prefix; it is not the sk_live_*/sk_int_* secret."},"client_secret":{"type":"string","description":"The full `sk_live_*` or `sk_int_*` API key."},"scope":{"type":"string","description":"Optional space-separated subset of the key's allowed scopes. If omitted, the JWT inherits the key's full scope set (or `*` for wildcard keys)."}}},"JwtTokenResponse":{"type":"object","required":["access_token","token_type","expires_in","refresh_token","scope"],"properties":{"access_token":{"type":"string","description":"Short-lived JWT (RS256, 15 min TTL). Use as `Authorization: Bearer <token>` on all `/api/v1/*` endpoints."},"token_type":{"type":"string","enum":["Bearer"]},"expires_in":{"type":"integer","example":900},"refresh_token":{"type":"string","description":"Refresh token (30 day TTL). Single-use — rotated on each `/auth/renew` call."},"scope":{"type":"string","example":"documents:send documents:read"}}},"JwtRenewRequest":{"type":"object","required":["grant_type","refresh_token"],"properties":{"grant_type":{"type":"string","enum":["refresh_token"]},"refresh_token":{"type":"string"}}},"JwtRevokeRequest":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"Either a JWT access token (starts with `eyJ`) or a refresh token."},"token_type_hint":{"type":"string","enum":["access_token","refresh_token"],"description":"Optional hint — the server detects type automatically."}}},"StatusHistoryEntry":{"type":"object","properties":{"status":{"type":"string","example":"SENT"},"timestamp":{"type":"string","format":"date-time"},"detail":{"type":"string","nullable":true}}},"DocumentStatusResponse":{"type":"object","description":"Stav dokumentu z pohľadu volajúceho — `direction` rozlišuje, či ide o **inbound** riadok (prijímateľ) alebo **outbound** riadok (odosielateľ). To isté Peppol message ID môže existovať na oboch stranách (prijímateľ aj odosielateľ majú vlastný riadok), ale ich timestampy a stavy sú **nezávislé**:\n\n- `deliveredAt` a `acknowledgedAt` na **inbound** riadku nastavuje prijímateľ cez `POST /documents/{id}/mark` resp. `POST /documents/inbox/{id}/acknowledge`. Tieto signály sú **lokálne** — Peppol BIS Billing 3.0 pre ne nemá ekvivalentnú správu, takže sa neposielajú odosielateľovi.\n- `acknowledgedAt` na **outbound** riadku sa vyplní iba vtedy, keď cez Peppol AS4 dorazí Invoice Response (kódy AP / AB / RE / …) — to je sieťový signál vygenerovaný cez `POST /documents/{id}/respond`.\n- `deliveredAt` na **outbound** riadku sa nikdy nepropaguje z prijímateľa. Ak odosielateľ potrebuje vidieť, že prijímateľ doručil/spracoval dokument, prijímateľ musí volať `/respond` s vhodným kódom (`AP` = accepted, `IP` = in process, `RE` = rejected).","properties":{"id":{"type":"string"},"status":{"type":"string","example":"DELIVERED"},"documentType":{"type":"string","nullable":true,"example":"invoice"},"direction":{"type":"string","enum":["inbound","outbound"],"description":"`inbound` = my sme prijímateľ (faktúru sme dostali). `outbound` = my sme odosielateľ. Určuje sémantiku timestampov: kto čo nastavuje a kedy."},"senderPeppolId":{"type":"string","nullable":true},"receiverPeppolId":{"type":"string","nullable":true},"statusHistory":{"type":"array","items":{"$ref":"#/components/schemas/StatusHistoryEntry"}},"validationResult":{"nullable":true,"description":"`null` on success, or `{ errors: string[] }` when validation failed.","type":"object","properties":{"errors":{"type":"array","items":{"type":"string"}}}},"deliveredAt":{"type":"string","format":"date-time","nullable":true,"description":"Inbound: nastavené prijímateľom cez `/mark state=delivered`. Outbound: vždy `null` — Peppol nemá delivery callback."},"acknowledgedAt":{"type":"string","format":"date-time","nullable":true,"description":"Inbound: nastavené prijímateľom cez `/acknowledge` alebo `/mark state=processed`. Outbound: nastavené v okamihu, keď nám AS4 doručí prijímateľov Invoice Response (cez `/respond`) — pokrýva celú sieťovú latenciu, takže timestamp sa typicky líši od inbound `acknowledgedAt`."},"invoiceResponseStatus":{"type":"string","enum":["AB","IP","UQ","CA","RE","AP","PD"],"nullable":true,"description":"Buyer's last invoice response status (7 UBL-2005 codes)."},"peppolMessageId":{"type":"string","nullable":true,"description":"Identifikátor správy v Peppol/AS4. Rovnaká hodnota ako `as4MessageId` (alias)."},"as4MessageId":{"type":"string","nullable":true,"description":"Identifikátor AS4 správy. Rovnaká hodnota ako `peppolMessageId` — oba aliasy sú v odpovedi pre uľahčenie konzumácie (detail faktúry vracia `peppolMessageId`, AS4-orientovaní integrátori používajú `as4MessageId`)."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"DocumentEvidenceResponse":{"type":"object","properties":{"documentId":{"type":"string"},"as4Receipt":{"type":"object","nullable":true,"description":"AS4 receipt od pristupoveho bodu prijemcu"},"mlrDocument":{"type":"string","nullable":true,"description":"Message Level Response XML"},"invoiceResponse":{"type":"object","nullable":true,"description":"Invoice Response od prijemcu","properties":{"status":{"type":"string","enum":["AB","IP","UQ","CA","RE","AP","PD"],"nullable":true},"document":{"type":"string","description":"Invoice Response UBL XML"}}},"tdd":{"type":"object","nullable":true,"description":"Populated when the document was reported to FS SR as a Tax Data Document.","properties":{"reportedAt":{"type":"string","format":"date-time"},"reported":{"type":"boolean"}}},"sentAt":{"type":"string","format":"date-time","nullable":true},"deliveredAt":{"type":"string","format":"date-time","nullable":true}}},"InvoiceResponseItem":{"type":"object","properties":{"id":{"type":"string"},"responseCode":{"type":"string","enum":["AB","IP","UQ","CA","RE","AP","PD"],"description":"AB=Accepted Billing, IP=In Process, UQ=Under Query, CA=Conditionally Accepted, RE=Rejected, AP=Accepted, PD=Paid"},"note":{"type":"string","nullable":true},"senderPeppolId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"InvoiceResponsesListResponse":{"type":"object","properties":{"documentId":{"type":"string"},"responses":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceResponseItem"}}}},"InvoiceRespondRequest":{"type":"object","required":["status"],"description":"Request body for POST /documents/{id}/respond. Field is `status` (not `responseCode`). 7 valid values mapping to UBL ApplicationResponse codes.","properties":{"status":{"type":"string","enum":["AB","IP","UQ","CA","RE","AP","PD"],"description":"AB=accepted_billing, IP=in_process, UQ=under_query, CA=conditionally_accepted, RE=rejected, AP=accepted, PD=paid"},"note":{"type":"string","maxLength":500,"example":"Faktura akceptovana","description":"Optional note, truncated to 500 characters."}}},"InvoiceRespondResponse":{"type":"object","description":"Returned with HTTP 200 when the AS4 dispatch succeeded, 202 when the response XML was persisted but dispatch failed and will be retried async.","properties":{"documentId":{"type":"string"},"responseStatus":{"type":"string","enum":["AB","IP","UQ","CA","RE","AP","PD"]},"respondedAt":{"type":"string","format":"date-time"},"peppolMessageId":{"type":"string","nullable":true},"dispatchStatus":{"type":"string","enum":["sent","failed_queued"]},"dispatchError":{"type":"string","description":"Populated only when dispatchStatus=failed_queued (HTTP 202)"}}},"ValidateDocumentResponse":{"type":"object","properties":{"valid":{"type":"boolean","example":true},"warnings":{"type":"array","items":{"type":"string"},"description":"Upozornenia (nie fatalne chyby)"},"ubl":{"type":"string","nullable":true,"description":"Vygenerovane UBL XML (len pri JSON mode)"}}},"PreflightResponse":{"type":"object","description":"Pre-flight lookup. Three booleans use tri-state (true|false|null) — null means 'unable to determine' (e.g., SMP timeout, no doctype filter specified).","properties":{"receiverPeppolId":{"type":"string","example":"0245:12345678"},"recipientAcceptsDocumentType":{"type":"boolean","nullable":true,"description":"Tri-state: true = doctype in SMP, false = not advertised, null = no documentType probed or lookup inconclusive."},"validationPassed":{"type":"boolean","nullable":true,"description":"Tri-state: true = schematron clean, false = errors, null = skipped (no UBL payload to validate)."},"canSend":{"type":"boolean","nullable":true,"description":"Overall verdict. false blocks the send, null = caller should still attempt (non-blocking warning)."},"warnings":{"type":"array","items":{"type":"string"}},"errors":{"type":"array","items":{"type":"string"}}}},"ConvertDocumentRequest":{"type":"object","required":["input_format","output_format","document"],"properties":{"input_format":{"type":"string","enum":["json","ubl"],"description":"Format vstupneho dokumentu"},"output_format":{"type":"string","enum":["json","ubl"],"description":"Format vystupneho dokumentu"},"document":{"oneOf":[{"type":"object"},{"type":"string"}],"description":"JSON objekt (pre input_format=json) alebo UBL XML string (pre input_format=ubl)"}}},"ConvertDocumentResponse":{"type":"object","properties":{"output_format":{"type":"string","enum":["json","ubl"]},"document":{"description":"Vysledok konverzie — UBL XML string (pre output_format=ubl) alebo JSON objekt (pre output_format=json)"},"warnings":{"type":"array","items":{"type":"string"}}}},"SmpParticipantCapability":{"type":"object","properties":{"documentTypeId":{"type":"string"},"processId":{"type":"string"},"transportProfile":{"type":"string","example":"peppol-transport-as4-v2_0"}}},"SmpLookupResponse":{"type":"object","properties":{"peppolId":{"type":"string","example":"0245:12345678"},"name":{"type":"string","nullable":true,"example":"Moja firma s.r.o."},"country":{"type":"string","nullable":true,"example":"SK"},"capabilities":{"type":"array","items":{"$ref":"#/components/schemas/SmpParticipantCapability"}}}},"PeppolDirectoryEntry":{"type":"object","properties":{"peppolId":{"type":"string","example":"0245:12345678"},"name":{"type":"string","example":"Moja firma s.r.o."},"country":{"type":"string","example":"SK"},"registeredAt":{"type":"string","format":"date-time","nullable":true}}},"PeppolDirectorySearchResponse":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/PeppolDirectoryEntry"}},"total":{"type":"integer","example":42},"page":{"type":"integer","example":1},"page_size":{"type":"integer","example":20}}},"CompanyLookupResponse":{"type":"object","description":"Slovenská firma podľa IČO. Dáta pochádzajú z denného exportu Finančnej správy SR (`fs_tax_subjects` + `fs_vat_violations`). 200 odpoveď znamená, že IČO je v exporte FS — buď ako aktívny subjekt (`active: true`), alebo ako deaktivovaný (`active: false`, vyplnený `cancelled_at`). Skutočne neznáme IČO vracia 404.","properties":{"name":{"type":"string","example":"Moja firma s.r.o."},"tax_id_1":{"type":"string","description":"IČO (8 číslic, padded zľava nulami).","example":"12345678"},"tax_id_2":{"type":"string","nullable":true,"description":"DIČ.","example":"2020123456"},"tax_id_3":{"type":"string","nullable":true,"description":"IČ DPH (`SK<dic>` ak je platca).","example":"SK2020123456"},"address_street":{"type":"string","nullable":true},"address_city":{"type":"string","nullable":true},"address_zip":{"type":"string","nullable":true},"address_country":{"type":"string","example":"SK"},"legal_form":{"type":"string","nullable":true,"description":"Klasifikácia odvodená iba z názvu subjektu vo feede Finančnej správy (`NAZOV_DS`). Vracia sa len pri explicitnom signáli v názve, napr. `s.r.o.`, `a.s.`, `o.z.`, `združenie`, `pozemkové spoločenstvo`, `nadácia`; neznáme prípady sú `null`, nie hádaná `živnosť`.","enum":["s.r.o.","a.s.","j.s.a.","k.s.","v.o.s.","družstvo","š.p.","n.o.","n.f.","o.z.","združenie","pozemkové spoločenstvo","spoločenstvo vlastníkov","nadácia","cirkev","komora"]},"legal_form_source":{"type":"string","nullable":true,"description":"Zdroj klasifikácie právnej formy. `fs_name` znamená explicitný regex match v názve z Finančnej správy; `null` znamená, že právnu formu nevieme z FS dát určiť.","enum":["fs_name"]},"legal_form_status":{"type":"string","description":"`classified` keď `legal_form` vznikol z explicitného FS name matchu; `unknown` keď sa právna forma nedala spoľahlivo určiť z FS dát.","enum":["classified","unknown"]},"vat_reg_type":{"type":"string","nullable":true,"description":"§-paragraf zákona č. 222/2004 Z.z. o DPH, podľa ktorého je subjekt registrovaný. Pozri `vat_reg_type_description` pre slovenský popis.","enum":["§4","§4b","§5","§7","§7a"]},"vat_reg_type_description":{"type":"string","nullable":true,"description":"Slovenský popis hodnoty `vat_reg_type`."},"dph_reg_from":{"type":"string","format":"date","nullable":true,"description":"Dátum registrácie za platiteľa DPH (`PLAT_DPH_OD` z FS feedu)."},"is_vat_payer":{"type":"boolean","description":"Odvodený flag. `true` keď: subjekt je `active`, má `dph_reg_from` a žiadna ds_dphv deregistrácia neprekrýva registráciu. Pre presnú interpretáciu zákazníckeho stavu DPH stále preferujte vlastnú kontrolu nad `vat_violations` + `dph_reg_from`."},"active":{"type":"boolean","description":"`true` keď subjekt bol v poslednom dennom dumpe FS. `false` znamená že FS subjekt vyradila → typicky zaniknutá / zrušená firma.","default":true},"cancelled_at":{"type":"string","format":"date","nullable":true,"description":"Dátum, kedy bol subjekt naposledy videný v FS dumpe pred deaktiváciou. Vyplnené iba ak `active: false`."},"vat_violations":{"type":"array","description":"Históriai aktuálne sankcie DPH. `ds_dphv` = deregistrácia za porušenie zákona o DPH (historický KYC indikátor). `ds_dphz` = aktuálne sankcionovaný platca DPH (otvorený dlh / porušenie). Prázdne pole = subjekt v sankčných zoznamoch FS nie je.","items":{"type":"object","properties":{"source":{"type":"string","enum":["ds_dphv","ds_dphz"]},"year_violation":{"type":"integer","nullable":true},"deletion_date":{"type":"string","format":"date","nullable":true},"publication_date":{"type":"string","format":"date","nullable":true}}}}}},"FirmSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Example s.r.o."},"ico":{"type":"string","example":"12345678"},"dic":{"type":"string","example":"2123456789","nullable":true},"peppol_id":{"type":"string","example":"0245:2123456789","nullable":true},"peppol_status":{"type":"string","enum":["ACTIVE","PENDING","NONE"],"example":"ACTIVE"}}},"FirmsListResponse":{"type":"object","properties":{"firms":{"type":"array","items":{"$ref":"#/components/schemas/FirmSummary"}}}},"FirmDetailResponse":{"allOf":[{"$ref":"#/components/schemas/FirmSummary"},{"type":"object","properties":{"dic":{"type":"string","nullable":true},"icDph":{"type":"string","nullable":true},"address":{"type":"object","properties":{"street":{"type":"string"},"city":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"}}},"peppolIdentifiers":{"type":"array","items":{"type":"object","properties":{"scheme":{"type":"string"},"identifier":{"type":"string"}}}},"createdAt":{"type":"string","format":"date-time"}}}]},"PeppolIdentifierResponse":{"type":"object","properties":{"peppolId":{"type":"string","example":"0245:12345678"},"scheme":{"type":"string","example":"0245"},"identifier":{"type":"string","example":"12345678"},"registeredAt":{"type":"string","format":"date-time"}}},"WebhookQueueEvent":{"type":"object","description":"Snake_case keys on `/webhook-queue/all`. The per-firm `/webhook-queue` route returns the same shape.","properties":{"event_id":{"type":"string","format":"uuid","example":"a3d2...-uuid"},"firm_id":{"type":"string","format":"uuid"},"event":{"type":"string","example":"document.received"},"payload":{"type":"object","description":"Event-specific payload"},"created_at":{"type":"string","format":"date-time"}}},"WebhookQueueResponse":{"type":"object","required":["items","has_more"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/WebhookQueueEvent"}},"has_more":{"type":"boolean","description":"True when more unacknowledged events exist beyond this page"}}},"StatisticsResponse":{"type":"object","properties":{"period":{"type":"object","properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"}}},"outbound":{"type":"object","properties":{"total":{"type":"integer","example":120},"delivered":{"type":"integer","example":115},"failed":{"type":"integer","example":5}}},"inbound":{"type":"object","properties":{"total":{"type":"integer","example":48},"acknowledged":{"type":"integer","example":40},"pending":{"type":"integer","example":8}}}}},"AssignFirmRequest":{"type":"object","anyOf":[{"required":["dic"]},{"required":["ico"]}],"properties":{"dic":{"type":"string","minLength":10,"maxLength":10,"pattern":"^\\d{10}$","example":"2123456789","description":"10-digit Slovak tax identifier (DIČ), preferred for PFS/SMP and Peppol 0245:DIČ"},"ico":{"type":"string","minLength":8,"maxLength":8,"pattern":"^\\d{8}$","example":"12345678","description":"8-digit company registration number (IČO), fallback for lookup/backward compatibility"}}},"AssignFirmResponse":{"type":"object","properties":{"firm":{"$ref":"#/components/schemas/FirmSummary"},"status":{"type":"string","example":"active"}}},"BatchAssignFirmsRequest":{"type":"object","anyOf":[{"required":["dics"]},{"required":["icos"]}],"x-totalMaxItems":50,"properties":{"dics":{"type":"array","items":{"type":"string","minLength":10,"maxLength":10,"pattern":"^\\d{10}$"},"minItems":1,"maxItems":50,"example":["2123456789","2123456790"],"description":"Preferred list of DIČ identifiers."},"icos":{"type":"array","items":{"type":"string","minLength":8,"maxLength":8,"pattern":"^\\d{8}$"},"minItems":1,"maxItems":50,"example":["12345678","87654321"],"description":"Fallback list of IČO identifiers for backward compatibility."}}},"BatchAssignFirmsResultItem":{"type":"object","properties":{"ico":{"type":"string","example":"12345678"},"dic":{"type":"string","example":"2123456789","nullable":true},"identifier":{"type":"string","example":"2123456789","nullable":true},"firm":{"$ref":"#/components/schemas/FirmSummary"},"status":{"type":"string","example":"active"},"error":{"type":"string","example":"not_found","nullable":true},"message":{"type":"string","example":"Firm not found","nullable":true}}},"BatchAssignFirmsResponse":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/BatchAssignFirmsResultItem"}}}},"CrossFirmInboxDocument":{"type":"object","properties":{"firm_id":{"type":"string","format":"uuid"},"firm_name":{"type":"string","example":"Example s.r.o."},"id":{"type":"string","format":"uuid"},"number":{"type":"string","example":"FAK-2026-0001"},"status":{"type":"string","enum":["RECEIVED","ACKNOWLEDGED"]},"sender_peppol_id":{"type":"string","example":"0245:99887766"},"sender_name":{"type":"string","example":"Supplier s.r.o."},"amount":{"type":"number","example":1210},"currency":{"type":"string","example":"EUR"},"received_at":{"type":"string","format":"date-time"}}},"CrossFirmInboxResponse":{"type":"object","properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/CrossFirmInboxDocument"}},"total":{"type":"integer","example":120},"limit":{"type":"integer","example":50},"offset":{"type":"integer","example":0}}},"CrossFirmWebhookEvent":{"type":"object","properties":{"event_id":{"type":"string","format":"uuid"},"firm_id":{"type":"string","format":"uuid"},"event":{"type":"string","example":"document.received"},"payload":{"type":"object"},"created_at":{"type":"string","format":"date-time"}}},"CrossFirmWebhookQueueResponse":{"type":"object","required":["items","has_more"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/CrossFirmWebhookEvent"}},"has_more":{"type":"boolean","description":"True when more unacknowledged events exist beyond this page"}}},"BatchAckWebhookRequest":{"type":"object","required":["event_ids"],"properties":{"event_ids":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":1000,"example":["uuid-1","uuid-2"]}}},"BatchAckWebhookResponse":{"type":"object","properties":{"acknowledged":{"type":"integer","example":42}}},"OAuthTokenRequest":{"type":"object","required":["grant_type","code","client_id","client_secret","redirect_uri"],"properties":{"grant_type":{"type":"string","enum":["authorization_code"],"example":"authorization_code"},"code":{"type":"string","example":"auth_code_here"},"client_id":{"type":"string","example":"client_id_here"},"client_secret":{"type":"string","example":"client_secret_here"},"redirect_uri":{"type":"string","format":"uri","example":"https://example.com/callback"},"code_verifier":{"type":"string","description":"PKCE code verifier (optional)","example":"pkce_verifier_here"}}},"OAuthTokenResponse":{"type":"object","required":["client_id","client_secret","secret_type","token_type","scope","firm_id"],"properties":{"client_id":{"type":"string","description":"Identifier to send as client_id when exchanging this secret at /api/v1/auth/token.","example":"sk_int_abc...xyz"},"client_secret":{"type":"string","description":"New sk_int_* secret. Store once; it is not shown again.","example":"sk_int_abc123"},"secret_type":{"type":"string","enum":["sk_int"]},"token_type":{"type":"string","enum":["client_secret"]},"scope":{"type":"string","example":"firms:manage documents:send documents:read"},"firm_id":{"type":"string","format":"uuid"},"firm_name":{"type":"string","example":"Example s.r.o."},"firm_ico":{"type":"string","example":"12345678"}}},"OAuthErrorResponse":{"type":"object","description":"RFC 6749 OAuth 2.0 error response. Uses top-level `error` and `error_description` strings, not the `error: { code, message }` envelope used everywhere else in this API.","required":["error"],"properties":{"error":{"type":"string","enum":["invalid_request","invalid_client","invalid_grant","unauthorized_client","unsupported_grant_type","invalid_scope"],"example":"invalid_grant"},"error_description":{"type":"string","example":"Authorization code is invalid or expired"}}},"AuthStatusResponse":{"type":"object","properties":{"key":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","example":"Production integration"},"prefix":{"type":"string","example":"sk_live_abc123"},"permissions":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"lastUsedAt":{"type":"string","format":"date-time","nullable":true}}},"firm":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"peppolStatus":{"type":"string","example":"active"}}},"plan":{"type":"object","properties":{"name":{"type":"string","example":"api-enterprise"},"expiresAt":{"type":"string","format":"date-time","nullable":true},"active":{"type":"boolean"}}},"rateLimit":{"type":"object","properties":{"perMinute":{"type":"integer","example":200},"window":{"type":"string","example":"60s"}}},"integrator":{"type":"object","nullable":true,"description":"Present only for sk_int_* keys","properties":{"id":{"type":"string","format":"uuid"}}}}},"RotateSecretResponse":{"type":"object","properties":{"key":{"type":"string","description":"New full API key, shown once.","example":"sk_live_abc...xyz"},"prefix":{"type":"string","example":"sk_live_abc123"},"message":{"type":"string","example":"Key rotated. Save it — it will not be shown again. The previous key is now inactive."}}},"ReportingSubmissionsResponse":{"type":"object","required":["items","total","limit","offset"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ReportingSubmissionItem"}},"total":{"type":"integer","example":24},"limit":{"type":"integer","example":20},"offset":{"type":"integer","example":0}}},"ReportingSubmissionItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"report_type":{"type":"string","enum":["EUSR","TSR"]},"period":{"type":"object","properties":{"from":{"type":"string","format":"date"},"to":{"type":"string","format":"date"}}},"status":{"type":"string","enum":["sent","failed","pending","submitting"]},"message_id":{"type":"string","nullable":true,"description":"Peppol AS4 message ID (null if not yet submitted)."},"submitted_at":{"type":"string","format":"date-time","nullable":true},"has_error":{"type":"boolean"}}},"BatchSendItem":{"type":"object","description":"Same shape as the POST /documents/send body (JSON or XML mode), plus an optional per-item idempotencyKey.","properties":{"idempotencyKey":{"type":"string","description":"Optional per-item idempotency key (propagated as `Idempotency-Key` header on the underlying single send)."}},"additionalProperties":true},"BatchSendRequest":{"type":"object","required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":50,"items":{"$ref":"#/components/schemas/BatchSendItem"}}}},"BatchSendResponse":{"type":"object","properties":{"total":{"type":"integer","example":50},"succeeded":{"type":"integer","example":48},"failed":{"type":"integer","example":2},"results":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","description":"0-based position in the input items[]"},"status":{"type":"integer","description":"HTTP status of the underlying single send (201, 422, 502, ...)"},"result":{"description":"Full response body from the underlying call (SendDocumentResponse or ErrorResponse)"}}}}}},"ParseResponse":{"type":"object","description":"Full normalized invoice payload. `invoice` contains the UBL body in ePostak's canonical JSON shape. `extras` holds BG-24 attachment descriptors, notes, and other UBL-specific fields. `allowances` lists document-level charges/allowances.","properties":{"invoice":{"type":"object","description":"Normalized invoice payload — see `/documents/parse` route implementation for the full field list."},"extras":{"type":"object"},"allowances":{"type":"array","items":{"type":"object"}}}},"MarkRequest":{"type":"object","required":["state"],"properties":{"state":{"type":"string","enum":["delivered","processed","failed","read"],"description":"delivered = external channel confirmed physical delivery; processed = buyer's ERP consumed the document; failed = terminal failure (blocks retries); read = user opened it (sets `read_at`)."},"note":{"type":"string","description":"Optional audit note appended to statusHistory."}}},"MarkResponse":{"type":"object","properties":{"id":{"type":"string"},"state":{"type":"string","example":"delivered"},"status":{"type":"string","description":"Invoice status after transition"},"deliveredAt":{"type":"string","format":"date-time","nullable":true},"acknowledgedAt":{"type":"string","format":"date-time","nullable":true},"readAt":{"type":"string","format":"date-time","nullable":true}}},"DocumentEvent":{"type":"object","properties":{"id":{"type":"string"},"eventType":{"type":"string","example":"document.sent","description":"One of: document.created, document.status_changed, document.approved, document.sent, document.send_failed, document.as4_delivered, document.mlr_received, document.response_received, document.response_sent, document.paid, document.fs_reported."},"actor":{"type":"string","enum":["system","user","api"]},"detail":{"type":"string","nullable":true},"meta":{"description":"Event-specific metadata (peppolMessageId, toStatus, approvedBy, ...)"},"occurredAt":{"type":"string","format":"date-time"}}},"DocumentEventsResponse":{"type":"object","properties":{"documentId":{"type":"string"},"events":{"type":"array","items":{"$ref":"#/components/schemas/DocumentEvent"}},"pagination":{"type":"object","properties":{"limit":{"type":"integer","example":20},"nextCursor":{"type":"string","nullable":true},"hasMore":{"type":"boolean"}}}}},"CapabilitiesRequest":{"type":"object","required":["participant"],"properties":{"participant":{"type":"object","required":["scheme","identifier"],"properties":{"scheme":{"type":"string","example":"0245","description":"4-digit ISO 6523 ICD scheme (SK = 0245)"},"identifier":{"type":"string","example":"2122701339"}}},"documentType":{"type":"string","description":"BIS 3.0 document type ID. Defaults to Peppol BIS Billing 3.0 Invoice when omitted.","example":"urn:cen.eu:en16931:2017"},"documentTypes":{"type":"array","minItems":1,"maxItems":20,"description":"Optional batch probe. When supplied, each document type is checked with the same participant/processId and the response includes capabilities[] and matchedDocumentTypes[].","items":{"type":"string"}},"processId":{"type":"string","description":"Optional BIS 3.0 process ID filter."}}},"CapabilityCheckResult":{"type":"object","properties":{"documentTypeId":{"type":"string"},"processId":{"type":"string"},"found":{"type":"boolean"},"accepts":{"type":"boolean"},"routingStatus":{"type":"string","nullable":true},"networkReady":{"type":"boolean"},"accessPoint":{"type":"object","nullable":true},"source":{"type":"string","nullable":true},"certificate":{"type":"object","nullable":true},"supportedDocumentTypes":{"type":"array","items":{"type":"string"}}}},"CapabilitiesResponse":{"type":"object","properties":{"found":{"type":"boolean"},"accepts":{"type":"boolean","description":"Receiver accepts the probed documentType/processId. Always `false` when `found=false`."},"reason":{"type":"string","description":"Populated when found=false.","example":"Participant not registered in Peppol network"},"participant":{"type":"object","properties":{"scheme":{"type":"string"},"identifier":{"type":"string"},"id":{"type":"string","example":"0245:2122701339"}}},"accessPoint":{"type":"object","nullable":true,"description":"Receiver's Peppol AP endpoint. null when found=false.","properties":{"url":{"type":"string","example":"https://ap.epostak.sk/as4"},"transportProfile":{"type":"string","example":"peppol-transport-as4-v2_0"}}},"internal":{"type":"boolean","description":"Receiver is hosted on this AP"},"supportedDocumentTypes":{"type":"array","items":{"type":"string"}},"matchedDocumentType":{"type":"string","nullable":true,"description":"The probed document type when accepted, otherwise `null`."},"matchedDocumentTypes":{"type":"array","description":"Document type URNs accepted among documentTypes[]. Present for batch probes.","items":{"type":"string"}},"capabilities":{"type":"array","description":"Per-document-type probe results. Present for batch probes.","items":{"$ref":"#/components/schemas/CapabilityCheckResult"}},"capability":{"$ref":"#/components/schemas/CapabilityCheckResult"},"source":{"type":"string","nullable":true,"description":"Lookup cache origin (e.g. `sml`, `cache`, `internal`)"}}},"ParticipantsBatchRequest":{"type":"object","required":["participants"],"properties":{"participants":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"object","required":["scheme","identifier"],"properties":{"scheme":{"type":"string","example":"0245"},"identifier":{"type":"string","example":"12345678"}}}}}},"ParticipantsBatchResponse":{"type":"object","properties":{"total":{"type":"integer","example":42},"found":{"type":"integer","example":38},"notFound":{"type":"integer","example":4},"results":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"participant":{"type":"object","properties":{"scheme":{"type":"string"},"identifier":{"type":"string"},"id":{"type":"string"}}},"found":{"type":"boolean"},"accessPoint":{"type":"object","nullable":true,"description":"Receiver's Peppol AP endpoint. null when found=false.","properties":{"url":{"type":"string","example":"https://ap.epostak.sk/as4"},"transportProfile":{"type":"string","example":"peppol-transport-as4-v2_0"}}},"internal":{"type":"boolean"},"supportedDocumentTypes":{"type":"array","items":{"type":"string"},"nullable":true},"source":{"type":"string","nullable":true},"error":{"type":"string","nullable":true,"description":"Invalid scheme/identifier format (per-item)"}}}}}},"WebhookTestResponse":{"type":"object","properties":{"success":{"type":"boolean"},"statusCode":{"type":"integer","nullable":true,"example":200},"responseTime":{"type":"integer","description":"Elapsed milliseconds end-to-end.","example":142},"webhookId":{"type":"string","description":"Synthetic `whk_test_*` ID used in the delivery headers."},"event":{"type":"string","example":"document.sent"},"requested":{"type":"integer","description":"Requested synthetic webhook POST count.","example":30000},"sent":{"type":"integer","description":"Synthetic webhook POSTs attempted.","example":30000},"succeeded":{"type":"integer","description":"Receiver responses with 2xx status.","example":29980},"failed":{"type":"integer","description":"Non-2xx responses or request errors.","example":20},"concurrency":{"type":"integer","description":"Internal concurrent outbound request cap used by the test runner.","example":250},"statusCodes":{"type":"object","additionalProperties":{"type":"integer"},"description":"Counts grouped by receiver HTTP status code.","example":{"200":29980,"500":20}},"error":{"type":"string","nullable":true,"description":"Populated when success=false."}}},"WebhookDeliveryDetail":{"type":"object","properties":{"id":{"type":"string"},"webhookId":{"type":"string"},"event":{"type":"string"},"status":{"type":"string","enum":["PENDING","SUCCESS","FAILED","RETRYING"]},"attempts":{"type":"integer"},"responseStatus":{"type":"integer","nullable":true},"responseBody":{"type":"string","nullable":true,"description":"First 200 chars of the receiver's response body (or error message). **Only present when the request included `?includeResponseBody=true` or `?include=responseBody`.** Omitted by default to avoid leaking content from receivers that echo sensitive data."},"lastAttemptAt":{"type":"string","format":"date-time","nullable":true},"nextRetryAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"DeliveriesResponse":{"type":"object","properties":{"deliveries":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryDetail"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"WebhookRotateSecretResponse":{"type":"object","properties":{"id":{"type":"string"},"secret":{"type":"string","description":"New 64-char hex HMAC secret. Shown once.","example":"a3f8...hex64chars"},"message":{"type":"string","example":"Secret rotated. Save it — it will not be shown again. The previous secret is now invalid."}}},"ValidateResponse":{"type":"object","description":"3-layer validation report. Structure mirrors the internal `validateUBLXml()` return type.","properties":{"valid":{"type":"boolean"},"layers":{"type":"object","properties":{"xsd":{"type":"object","properties":{"passed":{"type":"boolean"},"errors":{"type":"array","items":{"type":"string"}}}},"en16931":{"type":"object","properties":{"passed":{"type":"boolean"},"errors":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"string"}}}},"peppol":{"type":"object","properties":{"passed":{"type":"boolean"},"errors":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"string"}}}}}},"profile":{"type":"string","nullable":true,"description":"Detected BIS profile (Billing, SelfBilling, ...)"}}},"UblValidationError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","rule"],"properties":{"code":{"const":"UBL_VALIDATION_ERROR"},"message":{"type":"string"},"rule":{"type":"string","enum":["BR-02","BR-05","BR-06","BR-11","BR-16","BT-1","PEPPOL-R008"]},"requestId":{"type":"string"}}}}},"PeppolParty":{"type":"object","properties":{"peppol_id":{"type":"string","nullable":true,"example":"0245:2012345678"},"name":{"type":"string","nullable":true},"country":{"type":"string","description":"ISO 3166-1 alpha-2 country code. Omitted (key absent) when the Peppol scheme is unknown.","example":"SK"}}},"InboundImportRequest":{"type":"object","required":["xml"],"properties":{"xml":{"type":"string","format":"xml","description":"Raw UBL XML. Receiver identity must match the authenticated firm's Peppol ID: AccountingCustomerParty/EndpointID for a standard invoice, AccountingSupplierParty/EndpointID for self-billing."},"source":{"type":"string","example":"email","description":"Optional caller source label, for example email, sftp, manual or migration."},"messageId":{"type":"string","example":"legacy-ap-2026-0001","description":"Optional external audit message ID. Defaults to import:{documentId}. Idempotent replay uses Idempotency-Key, not messageId."},"idempotencyKey":{"type":"string","description":"Optional idempotency key stored on the imported document row. Reusing the same key with the same XML and metadata replays the original document; changing XML or metadata returns 422."},"documentTypeId":{"type":"string","description":"Optional override for the Peppol document type URN. Defaults from the parsed invoice type."},"processId":{"type":"string","description":"Optional override for the Peppol process URN. Defaults from the parsed invoice type."}}},"InboundImportLinks":{"type":"object","properties":{"document":{"type":"string","example":"/api/v1/inbound/documents/8e4b8f0e-21d3-4d2a-9c2b-24a3f8a0c111"},"ubl":{"type":"string","example":"/api/v1/inbound/documents/8e4b8f0e-21d3-4d2a-9c2b-24a3f8a0c111/ubl"},"ack":{"type":"string","example":"/api/v1/inbound/documents/8e4b8f0e-21d3-4d2a-9c2b-24a3f8a0c111/ack"}}},"InboundImportResponse":{"type":"object","required":["documentId","submissionId","status","kind","source","links"],"properties":{"documentId":{"type":"string","format":"uuid"},"submissionId":{"type":"string","format":"uuid","description":"Alias for documentId, matching the outbound submission response shape."},"status":{"type":"string","enum":["RECEIVED"],"example":"RECEIVED"},"kind":{"type":"string","example":"invoice"},"source":{"type":"string","example":"api_import"},"links":{"$ref":"#/components/schemas/InboundImportLinks"}}},"InboundDocument":{"type":"object","required":["id","received_at","kind","sender","recipient","document_type","ubl_url","metadata","ack"],"properties":{"id":{"type":"string","format":"uuid"},"received_at":{"type":"string","format":"date-time","description":"When the document was received from Peppol (row insert time is sub-second after AS4 receive)"},"kind":{"type":"string","example":"invoice","description":"Peppol doctype key (invoice, credit_note, self_billing_invoice, etc.)"},"peppol_message_id":{"type":"string","nullable":true,"description":"AS4 Peppol message UUID"},"sender":{"$ref":"#/components/schemas/PeppolParty"},"recipient":{"$ref":"#/components/schemas/PeppolParty"},"document_type":{"type":"string","example":"BIS Billing 3.0 Invoice","description":"Human-readable document type label"},"document_type_id":{"type":"string","nullable":true,"description":"Full Peppol document type URN"},"ubl_url":{"type":"string","format":"uri","description":"Absolute URL of GET /inbound/documents/{id}/ubl"},"metadata":{"type":"object","description":"Whitelisted safe fields extracted from UBL: invoice_number, total_amount, currency, issue_date","additionalProperties":{"type":"string"}},"ack":{"type":"object","required":["acked_at","client_reference"],"properties":{"acked_at":{"type":"string","format":"date-time","nullable":true},"client_reference":{"type":"string","nullable":true,"maxLength":256}}}}},"OutboundDocumentAttempt":{"type":"object","properties":{"attempt":{"type":"integer"},"status":{"type":"string"},"http_status":{"type":"integer","nullable":true},"error_message":{"type":"string","nullable":true},"attempted_at":{"type":"string","format":"date-time"}}},"OutboundDocument":{"type":"object","required":["id","kind","document_type","sender","recipient","created_at","transport_status","attempt_count","error","ubl_url","attempt_history","metadata"],"properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","example":"invoice"},"document_type":{"type":"string","example":"BIS Billing 3.0 Invoice"},"document_type_id":{"type":"string","nullable":true},"sender":{"$ref":"#/components/schemas/PeppolParty"},"recipient":{"$ref":"#/components/schemas/PeppolParty"},"created_at":{"type":"string","format":"date-time"},"transport_status":{"type":"string","enum":["queued","sending","sent","delivered","failed","dead"],"description":"AS4 transport view, uniform across billing and non-billing outbound"},"business_status":{"type":"string","description":"Invoice lifecycle status. Present ONLY for Invoice-backed (billing) documents. Key is omitted for non-billing outbound.","example":"sent"},"attempt_count":{"type":"integer","description":"Number of AS4 send attempts so far"},"last_attempt_at":{"type":"string","format":"date-time","nullable":true},"error":{"type":"object","properties":{"message":{"type":"string","nullable":true}}},"peppol_message_id":{"type":"string","nullable":true},"sent_at":{"type":"string","format":"date-time","nullable":true,"description":"AS4-level send timestamp (billing only)"},"delivered_at":{"type":"string","format":"date-time","nullable":true,"description":"AS4 delivery (MDN) timestamp (billing only)"},"ubl_url":{"type":"string","format":"uri"},"attempt_history":{"type":"array","description":"Delivery attempts, newest first. Empty on list endpoint (populated on detail endpoint only).","items":{"$ref":"#/components/schemas/OutboundDocumentAttempt"}},"metadata":{"type":"object","description":"Business metadata (invoice_number, total_amount, currency, issue_date, due_date) — populated only for Invoice-backed rows.","additionalProperties":{"type":"string"}}}},"OutboundEvent":{"type":"object","required":["id","document_id","type","occurred_at"],"properties":{"id":{"type":"string","format":"uuid"},"document_id":{"type":"string","format":"uuid","description":"Invoice ID (billing-backed events only in v1)"},"type":{"type":"string","example":"document.delivered","description":"DocumentEvent.eventType value"},"actor":{"type":"string","nullable":true,"description":"Who triggered the event (system, api, user email)"},"detail":{"type":"string","nullable":true},"meta":{"type":"object","nullable":true,"description":"Event-specific metadata object"},"occurred_at":{"type":"string","format":"date-time"}}},"InboundDocumentsListResponse":{"type":"object","required":["documents","next_cursor","has_more"],"properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/InboundDocument"}},"next_cursor":{"type":"string","nullable":true,"description":"Opaque base64url cursor (versioned, v=1). Pass as ?since= on the next request. NULL when no more pages."},"has_more":{"type":"boolean"}}},"OutboundDocumentsListResponse":{"type":"object","required":["documents","next_cursor","has_more"],"properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/OutboundDocument"}},"next_cursor":{"type":"string","nullable":true,"description":"Opaque union-cursor (u-prefixed base64url, v=1). Tracks last-emitted id per source table (Invoice + PeppolDocument). Pass as ?since=. NULL when no more pages."},"has_more":{"type":"boolean"}}},"OutboundEventsListResponse":{"type":"object","required":["events","next_cursor","has_more"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/OutboundEvent"}},"next_cursor":{"type":"string","nullable":true,"description":"Opaque versioned cursor (v=1). Pass as ?since=."},"has_more":{"type":"boolean"}}},"InboundAckRequest":{"type":"object","properties":{"client_reference":{"type":"string","maxLength":256,"description":"Optional opaque reference stored on the document (your internal document ID, ERP reference, etc.). Latest-ack-wins: calling ack again with a new client_reference overwrites the previous one."}}},"ConnectorPreflightRequest":{"type":"object","required":["receiverPeppolId","document"],"properties":{"receiverPeppolId":{"type":"string","example":"0245:2123456789"},"document":{"type":"object","additionalProperties":true,"description":"ERP invoice JSON, mapped fields, or UBL/XML envelope metadata."}}},"ConnectorRepairItem":{"type":"object","required":["code","field","message","category","autoFixable"],"properties":{"code":{"type":"string","example":"BR-CO-10"},"field":{"type":"string","nullable":true,"example":"cac:LegalMonetaryTotal"},"message":{"type":"string","example":"Invoice total does not match line totals."},"category":{"type":"string","example":"VALIDATION"},"autoFixable":{"type":"boolean"}}},"ConnectorSafeFix":{"type":"object","required":["code","field","message","applied"],"properties":{"code":{"type":"string"},"field":{"type":"string","nullable":true},"message":{"type":"string"},"applied":{"type":"boolean"}}},"ConnectorRepairReport":{"type":"object","required":["summary","blocking","warnings"],"properties":{"summary":{"type":"string"},"blocking":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorRepairItem"}},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorRepairItem"}}}},"ConnectorPreflightResponse":{"type":"object","required":["ready","outcome","repairReport","warnings","safeFixes"],"properties":{"ready":{"type":"boolean"},"outcome":{"type":"string","enum":["ready","ready_with_warnings","blocked","retry_later"]},"repairReport":{"$ref":"#/components/schemas/ConnectorRepairReport"},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorRepairItem"}},"safeFixes":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorSafeFix"}},"recipient":{"type":"object","nullable":true,"additionalProperties":true},"documentProfile":{"type":"object","nullable":true,"additionalProperties":true},"checks":{"type":"object","additionalProperties":true}}},"ConnectorSendRequest":{"type":"object","additionalProperties":true,"properties":{"idempotencyKey":{"type":"string","description":"Optional body fallback for Idempotency-Key. The header remains preferred."}}},"ConnectorSendResponse":{"type":"object","required":["documentId","status"],"properties":{"documentId":{"type":"string","format":"uuid"},"status":{"type":"string"},"outcome":{"type":"string","example":"accepted"},"links":{"type":"object","additionalProperties":true}}},"ConnectorOutboxStageItem":{"type":"object","required":["payload"],"properties":{"externalId":{"type":"string","nullable":true,"description":"ERP-side invoice identifier. Reusing it refreshes a prepared item until it is sent."},"idempotencyKey":{"type":"string","nullable":true,"description":"Idempotency key used when this outbox item is later sent. Defaults to externalId or a Connector-generated outbox key."},"scheduledFor":{"type":"string","format":"date-time","nullable":true,"description":"Optional future send time. Due scheduled items are picked up by bulk send."},"payload":{"type":"object","additionalProperties":true,"description":"Same JSON/XML envelope accepted by Connector send."}}},"ConnectorOutboxStageRequest":{"type":"object","properties":{"items":{"type":"array","maxItems":50,"items":{"$ref":"#/components/schemas/ConnectorOutboxStageItem"}},"payload":{"type":"object","additionalProperties":true,"description":"Single-item shortcut when not using items[]."},"externalId":{"type":"string"},"scheduledFor":{"type":"string","format":"date-time"}}},"ConnectorOutboxItem":{"type":"object","required":["outboxId","status","ready"],"properties":{"outboxId":{"type":"string","format":"uuid"},"externalId":{"type":"string","nullable":true},"status":{"type":"string","enum":["ready","blocked","scheduled","sending","sent","failed","cancelled"]},"scheduledFor":{"type":"string","format":"date-time","nullable":true},"documentId":{"type":"string","format":"uuid","nullable":true},"ready":{"type":"boolean"},"repairReport":{"allOf":[{"$ref":"#/components/schemas/ConnectorRepairReport"}],"nullable":true},"safeFixes":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorSafeFix"}},"lastError":{"type":"object","nullable":true,"additionalProperties":true},"attemptCount":{"type":"integer"},"managedOutbox":{"type":"object","required":["state","label","action","primaryAction","isActionable","isOverdue"],"properties":{"state":{"type":"string","enum":["ready_to_send","needs_repair","scheduled","sending","sent","failed","cancelled"]},"label":{"type":"string"},"action":{"type":"string"},"primaryAction":{"type":"string","enum":["send","repair","wait","inspect","none"]},"isActionable":{"type":"boolean"},"isOverdue":{"type":"boolean"}}},"sentAt":{"type":"string","format":"date-time","nullable":true},"cancelledAt":{"type":"string","format":"date-time","nullable":true},"links":{"type":"object","additionalProperties":{"type":"string"}}}},"ConnectorOutboxStageResponse":{"type":"object","required":["total","items"],"properties":{"total":{"type":"integer"},"ready":{"type":"integer"},"blocked":{"type":"integer"},"staged":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorOutboxItem"}}}},"ConnectorOutboxListResponse":{"type":"object","required":["items","total","limit","offset"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorOutboxItem"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"ConnectorOutboxBatchSendRequest":{"type":"object","properties":{"ids":{"type":"array","maxItems":50,"items":{"type":"string","format":"uuid"}},"limit":{"type":"integer","minimum":1,"maximum":50,"default":50},"force":{"type":"boolean","description":"Send scheduled items before scheduledFor when true."}}},"ConnectorOutboxBatchSendResponse":{"type":"object","required":["total","sent","failed","skipped","results"],"properties":{"total":{"type":"integer"},"sent":{"type":"integer"},"failed":{"type":"integer"},"skipped":{"type":"integer"},"results":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorOutboxItem"}}}},"ConnectorStatusResponse":{"type":"object","required":["documentId","status"],"properties":{"documentId":{"type":"string","format":"uuid"},"status":{"type":"string"},"deliveredAt":{"type":"string","format":"date-time","nullable":true},"events":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorEvent"}}}},"ConnectorInboxDocument":{"type":"object","required":["documentId","status"],"properties":{"documentId":{"type":"string","format":"uuid"},"status":{"type":"string"},"direction":{"type":"string","nullable":true},"documentType":{"type":"string","nullable":true},"documentNumber":{"type":"string","nullable":true},"senderPeppolId":{"type":"string","nullable":true},"receiverPeppolId":{"type":"string","nullable":true},"acknowledgedAt":{"type":"string","format":"date-time","nullable":true},"payload":{"type":"string","nullable":true},"payloadFormat":{"type":"string","nullable":true,"example":"XML"},"links":{"type":"object","additionalProperties":{"type":"string"}}}},"ConnectorInboxListResponse":{"type":"object","required":["documents","hasMore"],"properties":{"documents":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorInboxDocument"}},"nextCursor":{"type":"string","nullable":true},"hasMore":{"type":"boolean"}}},"ConnectorAckResponse":{"type":"object","required":["documentId","status","acknowledged"],"properties":{"documentId":{"type":"string","format":"uuid"},"status":{"type":"string","example":"processed"},"acknowledged":{"type":"boolean"},"idempotent":{"type":"boolean"},"acknowledgedAt":{"type":"string","format":"date-time","nullable":true}}},"ConnectorEvent":{"type":"object","required":["id","documentId","type","occurredAt"],"properties":{"id":{"type":"string"},"documentId":{"type":"string","format":"uuid","nullable":true},"type":{"type":"string","example":"document.delivered"},"occurredAt":{"type":"string","format":"date-time","nullable":true},"status":{"type":"string"},"data":{"type":"object","additionalProperties":true}}},"ConnectorEventsResponse":{"type":"object","required":["events","hasMore"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/ConnectorEvent"}},"nextCursor":{"type":"string","nullable":true},"hasMore":{"type":"boolean"}}},"EventsPullResponse":{"type":"object","required":["events","has_more"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookQueueEvent"},"description":"Unacknowledged events returned oldest-first. Acknowledge after local commit to remove them from the queue."},"has_more":{"type":"boolean","description":"True when more unacknowledged events exist beyond this page"}}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests allowed in the current window","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Remaining requests in the current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the rate-limit window resets","schema":{"type":"integer"}}}}}