{"openapi":"3.0.3","info":{"title":"Vantane Sandbox API","version":"0.1.0","description":"Agent-native e-invoicing. Create a compliant Peppol BIS 3.0 UBL invoice from canonical JSON, or validate one for free. This is the public sandbox: delivery is always simulated and anonymous invoices are purged after 24h.","contact":{"name":"Vantane","url":"https://vantane.com","email":"support@vantane.com"},"termsOfService":"https://vantane.com/terms"},"servers":[{"url":"/"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Bearer API key. Use the public sandbox key 'vantane_sandbox_public' (IP rate-limited to 60/min) or your own key."}},"schemas":{"Invoice":{"type":"object","properties":{"id":{"type":"string","minLength":1},"invoiceTypeCode":{"type":"string","pattern":"^\\d{3}$","default":"380"},"issueDate":{"type":"string"},"dueDate":{"type":"string"},"currencyCode":{"type":"string","minLength":3,"maxLength":3},"buyerReference":{"type":"string","minLength":1},"seller":{"type":"object","properties":{"name":{"type":"string","minLength":1},"legalForm":{"type":"string","minLength":1},"vatId":{"type":"string","pattern":"^[A-Z]{2}[A-Z0-9]{2,20}$"},"registrationNumber":{"type":"string","minLength":1},"address":{"type":"object","properties":{"line1":{"type":"string","minLength":1},"line2":{"type":"string","minLength":1},"city":{"type":"string","minLength":1},"postalCode":{"type":"string","minLength":1},"countrySubdivision":{"type":"string","minLength":1},"countryCode":{"type":"string","minLength":2,"maxLength":2}},"required":["countryCode"],"additionalProperties":false},"electronicAddress":{"type":"object","properties":{"scheme":{"type":"string"},"value":{"type":"string","minLength":1}},"required":["scheme","value"],"additionalProperties":false},"contact":{"type":"object","properties":{"name":{"type":"string","minLength":1},"phone":{"type":"string","minLength":1},"email":{"type":"string","format":"email"}},"additionalProperties":false}},"required":["name","address"],"additionalProperties":false},"buyer":{"type":"object","properties":{"name":{"type":"string","minLength":1},"legalForm":{"type":"string","minLength":1},"vatId":{"type":"string","pattern":"^[A-Z]{2}[A-Z0-9]{2,20}$"},"registrationNumber":{"type":"string","minLength":1},"address":{"type":"object","properties":{"line1":{"type":"string","minLength":1},"line2":{"type":"string","minLength":1},"city":{"type":"string","minLength":1},"postalCode":{"type":"string","minLength":1},"countrySubdivision":{"type":"string","minLength":1},"countryCode":{"type":"string","minLength":2,"maxLength":2}},"required":["countryCode"],"additionalProperties":false},"electronicAddress":{"type":"object","properties":{"scheme":{"type":"string"},"value":{"type":"string","minLength":1}},"required":["scheme","value"],"additionalProperties":false},"contact":{"type":"object","properties":{"name":{"type":"string","minLength":1},"phone":{"type":"string","minLength":1},"email":{"type":"string","format":"email"}},"additionalProperties":false}},"required":["name","address"],"additionalProperties":false},"lines":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"description":{"type":"string","minLength":1},"quantity":{"type":"number","exclusiveMinimum":true,"minimum":0},"unitCode":{"type":"string","pattern":"^[A-Z0-9]{1,4}$"},"unitPrice":{"type":"number","minimum":0},"vat":{"type":"object","properties":{"categoryCode":{"type":"string","enum":["S","Z","E","AE","K","G","O"]},"rate":{"type":"number","minimum":0,"maximum":100},"exemptionReason":{"type":"string","minLength":1},"exemptionReasonCode":{"type":"string","minLength":1}},"required":["categoryCode","rate"],"additionalProperties":false}},"required":["id","description","quantity","unitCode","unitPrice","vat"],"additionalProperties":false},"minItems":1},"documentAllowances":{"type":"array","items":{"type":"object","properties":{"reason":{"type":"string","minLength":1},"amount":{"type":"number","exclusiveMinimum":true,"minimum":0},"vat":{"type":"object","properties":{"categoryCode":{"type":"string","enum":["S","Z","E","AE","K","G","O"]},"rate":{"type":"number","minimum":0,"maximum":100},"exemptionReason":{"type":"string","minLength":1},"exemptionReasonCode":{"type":"string","minLength":1}},"required":["categoryCode","rate"],"additionalProperties":false}},"required":["amount","vat"],"additionalProperties":false},"default":[]},"documentCharges":{"type":"array","items":{"type":"object","properties":{"reason":{"type":"string","minLength":1},"amount":{"type":"number","exclusiveMinimum":true,"minimum":0},"vat":{"type":"object","properties":{"categoryCode":{"type":"string","enum":["S","Z","E","AE","K","G","O"]},"rate":{"type":"number","minimum":0,"maximum":100},"exemptionReason":{"type":"string","minLength":1},"exemptionReasonCode":{"type":"string","minLength":1}},"required":["categoryCode","rate"],"additionalProperties":false}},"required":["amount","vat"],"additionalProperties":false},"default":[]},"paymentTerms":{"type":"string","minLength":1},"paymentMeans":{"type":"object","properties":{"typeCode":{"type":"string","minLength":1,"default":"30"},"iban":{"type":"string","pattern":"^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$"},"bic":{"type":"string","pattern":"^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$"},"accountName":{"type":"string","minLength":1}},"additionalProperties":false},"attachments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"description":{"type":"string","minLength":1},"filename":{"type":"string","minLength":1},"mimeCode":{"type":"string","minLength":1},"content":{"type":"string","minLength":1},"externalUrl":{"type":"string","format":"uri"}},"additionalProperties":false},"default":[]},"declaredTotals":{"type":"object","properties":{"lineExtensionAmount":{"type":"number","minimum":0},"allowanceTotalAmount":{"type":"number","minimum":0},"chargeTotalAmount":{"type":"number","minimum":0},"taxExclusiveAmount":{"type":"number","minimum":0},"totalVatAmount":{"type":"number","minimum":0},"taxInclusiveAmount":{"type":"number","minimum":0},"payableAmount":{"type":"number","minimum":0}},"additionalProperties":false}},"required":["id","issueDate","currencyCode","seller","buyer","lines"],"additionalProperties":false},"AgentError":{"type":"object","properties":{"code":{"type":"string","example":"PEPPOL-EN16931-R003"},"humanSummary":{"type":"string"},"llmFix":{"type":"string"},"docsUrl":{"type":"string"},"offendingValue":{"type":["string","null"]},"field":{"type":["string","null"]},"ruleId":{"type":"string"},"severity":{"type":"string","enum":["fatal","warning"]},"stage":{"type":"string","enum":["xsd","en16931","peppol"]},"rawMessage":{"type":"string"},"location":{"type":"string"}},"required":["code","humanSummary","llmFix","severity","stage"]},"ValidationReport":{"type":"object","properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/AgentError"}},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/AgentError"}}},"required":["errors","warnings"]},"InvoiceEnvelope":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["validated","invalid","delivered_simulated","submitted"]},"document_url":{"type":["string","null"]},"validation":{"$ref":"#/components/schemas/ValidationReport"},"preview_url":{"type":["string","null"]}},"required":["id","status","validation"]},"CreateInvoiceRequest":{"type":"object","properties":{"invoice":{"$ref":"#/components/schemas/Invoice"},"options":{"type":"object","properties":{"deliver":{"type":"boolean","default":false,"description":"Sandbox delivery is always simulated."},"format":{"type":"string","enum":["auto","ubl"],"default":"auto"}}}},"required":["invoice"]},"Capabilities":{"type":"object","description":"The current country/format/channel routing matrix. Declarative and versioned; mandates carry effective dates.","properties":{"version":{"type":"string"},"updated":{"type":"string"},"asOf":{"type":"string","description":"The date the matrix was evaluated for (YYYY-MM-DD)."},"formats":{"type":"object","additionalProperties":true},"channels":{"type":"object","additionalProperties":true},"rules":{"type":"array","description":"The full declarative rule table, including not-yet-active mandates; each flagged with its as-of active state.","items":{"type":"object","additionalProperties":true}},"countries":{"type":"array","description":"Per-country outcome for a domestic buyer not reachable on Peppol, evaluated as-of the queried date.","items":{"type":"object","additionalProperties":true}}},"required":["version","asOf","formats","channels","rules","countries"]},"WebhookResult":{"type":"object","description":"Ingestion outcome for a delivery-status webhook batch.","properties":{"received":{"type":"integer","description":"Number of status events parsed from the payload."},"applied":{"type":"integer","description":"Events matched to a known delivery and persisted."},"unmatched":{"type":"integer","description":"Events for an unknown providerRef, skipped (not an error)."}},"required":["received","applied","unmatched"]},"BillingSummary":{"type":"object","description":"Account balance and this calendar month usage. Money is integer euro cents.","properties":{"balance_cents":{"type":"integer","description":"Running ledger sum. Positive = prepaid credit; negative = owed."},"balance":{"type":"string","example":"€12.40"},"owed_cents":{"type":"integer","description":"Amount owed (0 unless a card account has accrued debt)."},"payment_mode":{"type":"string","enum":["prepaid","card_threshold"]},"delivered_this_month":{"type":"integer"},"currency":{"type":"string","example":"eur"}},"required":["balance_cents","balance","owed_cents","payment_mode","delivered_this_month","currency"]},"TopupResult":{"type":"object","properties":{"checkout_url":{"type":"string","description":"Stripe Checkout URL to complete the top-up."},"session_id":{"type":"string"},"amount_cents":{"type":"integer","enum":[1000,2500,5000,10000]}},"required":["checkout_url","session_id","amount_cents"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"llmFix":{"type":"string"}},"required":["code","message"]}}}}},"paths":{"/v1/invoices":{"post":{"operationId":"createInvoice","summary":"Create (and optionally simulate delivery of) a compliant invoice.","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"},"description":"Replays return the original invoice instead of creating a new one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvoiceRequest"}}}},"responses":{"200":{"description":"Idempotent replay of a prior create.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceEnvelope"}}}},"201":{"description":"Invoice created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceEnvelope"}}}},"400":{"description":"Malformed request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Prepaid balance exhausted; the error llmFix carries the top-up action.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Public sandbox rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/invoices/{id}":{"get":{"operationId":"getInvoice","summary":"Fetch a previously created invoice and its status history.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The invoice envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceEnvelope"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such invoice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/invoices/{id}/document.xml":{"get":{"operationId":"getInvoiceDocument","summary":"Fetch the generated UBL XML document.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The UBL XML.","content":{"application/xml":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No document for this invoice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/invoices/{id}/preview.png":{"get":{"operationId":"getInvoicePreview","summary":"Render a PNG preview of the invoice so an agent can visually inspect it.","description":"Rendered by a headless-Chromium sidecar and cached per page. Use ?page=N for multi-page invoices.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"The 1-based page to render for multi-page invoices."}],"responses":{"200":{"description":"The rendered PNG.","content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Page out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such invoice, or no document to preview.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"The rendering sidecar failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Preview rendering is not configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/capabilities":{"get":{"operationId":"getCapabilities","summary":"The current country/format/channel routing matrix. Free, no auth.","description":"Declarative, versioned routing rules with effective dates so agents can discover what Vantane supports (and which mandates are upcoming). Pass ?asOf=YYYY-MM-DD to preview a future date.","parameters":[{"name":"asOf","in":"query","required":false,"schema":{"type":"string","example":"2026-09-01"},"description":"ISO date (YYYY-MM-DD) to evaluate the matrix as-of. Defaults to today."}],"responses":{"200":{"description":"The routing capabilities matrix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Capabilities"}}}},"400":{"description":"Malformed asOf date.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing":{"get":{"operationId":"getBilling","summary":"Account balance and this month usage.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Billing summary.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillingSummary"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/billing/topup":{"post":{"operationId":"startTopup","summary":"Start a Stripe Checkout for prepaid credit (€10/25/50/100). Credit never expires.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount_cents":{"type":"integer","enum":[1000,2500,5000,10000]}},"required":["amount_cents"]}}}},"responses":{"200":{"description":"Checkout session created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopupResult"}}}},"400":{"description":"Invalid top-up amount.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Stripe is not configured on this deployment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/webhooks/stripe":{"post":{"operationId":"ingestStripeWebhook","summary":"Ingest Stripe events (signature-verified). Checkout completion credits the ledger.","description":"Unauthenticated; verified via the Stripe-Signature header against STRIPE_WEBHOOK_SECRET.","responses":{"200":{"description":"Event processed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResult"}}}},"400":{"description":"Missing/invalid signature or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Stripe is not configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/webhooks/delivery/{provider}":{"post":{"operationId":"ingestDeliveryWebhook","summary":"Ingest a delivery-status webhook from a delivery provider.","description":"Unauthenticated by design: providers cannot carry Vantane API keys. The {provider} path segment selects the parser that maps the native payload into our canonical status model. Unknown providers 404; unparseable or unmatched payloads are accepted as a no-op so providers do not hammer retries.","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","example":"storecove"},"description":"The registered provider name whose payload shape to parse."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"The webhook batch was ingested.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResult"}}}},"404":{"description":"No delivery provider by that name is registered.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/validate":{"post":{"operationId":"validateInvoice","summary":"Validate canonical invoice JSON. Free, stateless, no auth.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Invoice"}}}},"responses":{"200":{"description":"Validation report.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["validated","invalid"]},"validation":{"$ref":"#/components/schemas/ValidationReport"}},"required":["status","validation"]}}}}}}}}}