{
  "openapi": "3.1.0",
  "info": {
    "title": "Invovate Invoice API",
    "version": "1.0.0",
    "summary": "The agent-friendly multilingual invoice API — send JSON, get computed totals, PDF/UBL, QR, and 7-day hosted links. No signup required to try.",
    "description": "Generate invoices from a single JSON payload. The API does the line-item math server-side (per-line and global discounts, single or multi-component tax, tax-inclusive pricing, shipping, deposit, rounding) and returns the computed totals as JSON, a rendered PDF, or UBL 2.1 XML. 11 languages incl. Japanese/Arabic/Russian/Hindi, 21 currencies, 5 templates, logo + signature, payment details, and an optional scannable QR that opens a 7-day signed hosted link.\n\nUBL 2.1 export is for interoperability and archival only — it is NOT a regulated e-invoice transmission (no Peppol/SDI/SAT/clearance, no Factur-X/ZUGFeRD/XRechnung compliance claim).\n\nThe request schema documented here is canonical (snake_case, with invoice metadata nested under `invoice`). For backward compatibility the API also accepts camelCase keys and a flat layer where invoice-metadata fields may be sent at the top level — but new integrations should use the canonical form below.",
    "contact": { "name": "Invovate", "url": "https://invovate.com/api", "email": "hello@invovate.com" },
    "license": { "name": "Free tier — see pricing", "url": "https://invovate.com/pricing" }
  },
  "servers": [{ "url": "https://invovate.com", "description": "Production" }],
  "externalDocs": { "description": "API docs & agent quickstart", "url": "https://invovate.com/api" },
  "x-canonical-casing": "snake_case",
  "x-aliases-accepted": "camelCase keys and top-level (flat) invoice-metadata fields are accepted for compatibility but are not documented; prefer the canonical schema.",
  "x-agent-quickstart": "POST https://invovate.com/api/generate-invoice with Content-Type: application/json and a body of { from:{name}, to:{name}, items:[{description,quantity,unit_price}] }. No API key needed for JSON output (anonymous, IP-rate-limited). For PDF/UBL output add Authorization: Bearer inv_... and \"output\":\"pdf\". The response includes a 7-day hosted_url that renders the PDF on demand.",
  "x-rate-limit-headers": ["X-RateLimit-Limit-Hourly", "X-RateLimit-Remaining-Hourly", "X-RateLimit-Limit-Weekly", "X-RateLimit-Limit-Monthly", "X-Request-Id"],
  "tags": [
    { "name": "Invoices", "description": "Generate a single invoice (JSON, PDF, or UBL)." },
    { "name": "Batch", "description": "Generate many invoices in one call." },
    { "name": "Hosted Links", "description": "Public 7-day signed invoice links." },
    { "name": "Webhooks", "description": "Register endpoints notified on invoice events." }
  ],
  "security": [{ "bearerAuth": [] }, {}],
  "paths": {
    "/api/generate-invoice": {
      "post": {
        "operationId": "generateInvoice",
        "tags": ["Invoices"],
        "summary": "Generate an invoice",
        "description": "Compute totals and return JSON (default), a PDF, or UBL 2.1 XML. Anonymous calls (no auth) are allowed for JSON output and are IP-rate-limited; PDF/UBL output requires a free API key. Send an `Idempotency-Key` header to make retries safe.",
        "parameters": [
          { "name": "Idempotency-Key", "in": "header", "required": false, "schema": { "type": "string" }, "description": "Opaque key; a repeat with the same key replays the first response (24h)." }
        ],
        "requestBody": { "required": true, "content": { "application/json": {
          "schema": { "$ref": "#/components/schemas/InvoiceRequest" },
          "examples": {
            "minimal": { "summary": "Minimal", "value": { "from": { "name": "Acme LLC" }, "to": { "name": "Globex Corp" }, "items": [{ "description": "Consulting", "quantity": 2, "unit_price": 100 }] } },
            "indiaGst": { "summary": "India GST (CGST+SGST) + payment + PDF", "value": { "from": { "name": "Acme Studios", "tax_id": "29ABCDE1234F1Z5", "logo": "https://example.com/logo.png" }, "to": { "name": "Globex Corp", "address": "Mumbai" }, "invoice": { "number": "INV-2026-009", "currency": "INR", "language": "en", "title": "TAX INVOICE" }, "items": [{ "description": "Design", "quantity": 8, "unit": "hrs", "unit_price": 1500, "taxes": [{ "name": "CGST", "rate": 9 }, { "name": "SGST", "rate": 9 }] }], "shipping": 0, "payment": { "pay_to": "Acme Studios", "iban": "GB29NWBK60161331926819", "swift": "HDFCINBB", "method_note": "Paid by card ending **999" }, "template": "classic", "output": "pdf" } }
          }
        } } },
        "responses": {
          "200": {
            "description": "Invoice generated.",
            "headers": {
              "X-Request-Id": { "schema": { "type": "string" } },
              "X-RateLimit-Remaining-Hourly": { "schema": { "type": "integer" } }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/InvoiceJsonResponse" } },
              "application/pdf": { "schema": { "type": "string", "format": "binary" } },
              "application/xml": { "schema": { "type": "string", "description": "UBL 2.1 Invoice XML" } }
            }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/batch": {
      "post": {
        "operationId": "generateInvoiceBatch",
        "tags": ["Batch"],
        "summary": "Generate up to 50 invoices",
        "description": "Process an array of invoice requests, one credit each, with independent per-item results (a bad item fails alone). Returns JSON results; each successful item includes a `hosted_url` for the PDF. Requires an API key.",
        "security": [{ "bearerAuth": [] }],
        "requestBody": { "required": true, "content": { "application/json": {
          "schema": { "$ref": "#/components/schemas/BatchRequest" },
          "examples": { "two": { "value": { "invoices": [
            { "from": { "name": "Acme" }, "to": { "name": "A" }, "items": [{ "description": "X", "quantity": 1, "unit_price": 10 }] },
            { "from": { "name": "Acme" }, "to": { "name": "B" }, "items": [{ "description": "Y", "quantity": 2, "unit_price": 20 }] }
          ] } } }
        } } },
        "responses": {
          "200": { "description": "Batch processed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchResponse" } } } },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/i/{id}": {
      "get": {
        "operationId": "getHostedInvoice",
        "tags": ["Hosted Links"],
        "summary": "Open a hosted invoice",
        "description": "Public, signed, 7-day link. Returns the rendered PDF (default) or the invoice JSON with `?format=json`. An invalid or expired signature returns 404.",
        "security": [{}],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "t", "in": "query", "required": true, "schema": { "type": "string" }, "description": "HMAC signature." },
          { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "enum": ["json", "pdf"] } }
        ],
        "responses": {
          "200": { "description": "Invoice.", "content": { "application/pdf": { "schema": { "type": "string", "format": "binary" } }, "application/json": { "schema": { "$ref": "#/components/schemas/InvoiceJsonResponse" } } } },
          "404": { "description": "Invalid or expired link." }
        }
      }
    },
    "/api/webhooks": {
      "get": {
        "operationId": "listWebhooks", "tags": ["Webhooks"], "summary": "List webhooks", "security": [{ "bearerAuth": [] }],
        "responses": { "200": { "description": "Webhook list.", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "const": true }, "webhooks": { "type": "array", "items": { "$ref": "#/components/schemas/Webhook" } } } } } } } }
      },
      "post": {
        "operationId": "createWebhook", "tags": ["Webhooks"], "summary": "Register a webhook", "security": [{ "bearerAuth": [] }],
        "description": "The signing `secret` is returned ONCE at creation. Deliveries include header `X-Invovate-Signature: sha256=<hmac over raw body>`.",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookCreate" }, "examples": { "ex": { "value": { "url": "https://example.com/hooks/invovate", "events": ["invoice.generated"] } } } } } },
        "responses": { "201": { "description": "Created.", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "const": true }, "webhook": { "$ref": "#/components/schemas/WebhookWithSecret" } } } } } }, "400": { "$ref": "#/components/responses/Error" } }
      }
    },
    "/api/webhooks/{id}": {
      "get": {
        "operationId": "getWebhook", "tags": ["Webhooks"], "summary": "Get a webhook", "security": [{ "bearerAuth": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Webhook.", "content": { "application/json": { "schema": { "type": "object", "properties": { "success": { "const": true }, "webhook": { "$ref": "#/components/schemas/Webhook" } } } } } }, "404": { "$ref": "#/components/responses/Error" } }
      },
      "delete": {
        "operationId": "deleteWebhook", "tags": ["Webhooks"], "summary": "Delete a webhook", "security": [{ "bearerAuth": [] }],
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Deleted." }, "404": { "$ref": "#/components/responses/Error" } }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "inv_xxxxxxxx", "description": "API key from your dashboard. Optional for JSON output (anonymous tier); required for PDF/UBL/batch/webhooks." }
    },
    "responses": {
      "Error": { "description": "Error.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    },
    "schemas": {
      "InvoiceRequest": {
        "type": "object",
        "required": ["from", "to", "items"],
        "properties": {
          "from": { "$ref": "#/components/schemas/Party" },
          "to": { "$ref": "#/components/schemas/Party" },
          "ship_to": { "type": "object", "properties": { "name": { "type": "string" }, "address": { "type": "string" } } },
          "invoice": { "$ref": "#/components/schemas/InvoiceMeta" },
          "items": { "type": "array", "minItems": 1, "maxItems": 100, "items": { "$ref": "#/components/schemas/LineItem" } },
          "global_tax": { "type": "number", "description": "Single % applied when no per-item tax is set." },
          "global_taxes": { "type": "array", "items": { "$ref": "#/components/schemas/TaxComponent" } },
          "global_discount": { "type": "number" },
          "global_discount_type": { "type": "string", "enum": ["percent", "amount"], "default": "percent" },
          "shipping": { "type": "number", "minimum": 0 },
          "shipping_label": { "type": "string", "default": "Shipping" },
          "deposit": { "type": "number", "minimum": 0 },
          "rounding": { "type": "string", "enum": ["none", "nearest", "up", "down"], "default": "none" },
          "amount_paid": { "type": "number", "minimum": 0 },
          "payment": { "$ref": "#/components/schemas/Payment" },
          "template": { "type": "string", "enum": ["classic", "modern", "bold", "minimal", "navy"], "default": "classic" },
          "accent_color": { "type": "string", "pattern": "^#[0-9a-fA-F]{6}$" },
          "signature": { "type": "string", "description": "Image URL (https) or data: URI (png/jpeg)." },
          "output": { "type": "string", "enum": ["json", "pdf", "ubl"], "default": "json" },
          "features": { "$ref": "#/components/schemas/Features" },
          "notes": { "type": "string" },
          "refund_policy": { "type": "string" },
          "footer": { "type": "string" }
        }
      },
      "Party": {
        "type": "object", "required": ["name"],
        "properties": {
          "name": { "type": "string" }, "address": { "type": "string" }, "email": { "type": "string" },
          "phone": { "type": "string" }, "tax_id": { "type": "string", "description": "VAT/GST/EIN" },
          "registration_no": { "type": "string" }, "website": { "type": "string" },
          "logo": { "type": "string", "description": "Image URL (https) or data: URI (png/jpeg). ≤2.5MB. (from only)" }
        }
      },
      "InvoiceMeta": {
        "type": "object",
        "properties": {
          "number": { "type": "string" }, "date": { "type": "string", "format": "date" },
          "due_date": { "type": "string", "format": "date" }, "po_number": { "type": "string" },
          "terms": { "type": "string" }, "currency": { "type": "string", "default": "USD", "examples": ["USD", "EUR", "JPY", "INR"] },
          "language": { "type": "string", "default": "en", "enum": ["en", "nl", "de", "fr", "es", "pt", "ar", "ja", "ru", "it", "hi"] },
          "title": { "type": "string", "description": "Overrides the 'INVOICE' heading, e.g. 'QUOTE', 'TAX INVOICE'." },
          "tax_inclusive": { "type": "boolean", "default": false }
        }
      },
      "LineItem": {
        "type": "object", "required": ["description"],
        "properties": {
          "description": { "type": "string" }, "quantity": { "type": "number", "default": 1 },
          "unit": { "type": "string", "description": "e.g. hrs, pcs, kg" }, "unit_price": { "type": "number", "default": 0 },
          "discount": { "type": "number" }, "discount_type": { "type": "string", "enum": ["percent", "amount"], "default": "percent" },
          "tax_rate": { "type": "number", "description": "Single rate; OR use taxes[] for multiple components." },
          "taxes": { "type": "array", "items": { "$ref": "#/components/schemas/TaxComponent" } }
        }
      },
      "TaxComponent": { "type": "object", "properties": { "name": { "type": "string", "examples": ["VAT", "CGST", "SGST"] }, "rate": { "type": "number" } } },
      "Payment": {
        "type": "object",
        "properties": {
          "pay_to": { "type": "string" }, "bank_name": { "type": "string" }, "account_name": { "type": "string" },
          "account_number": { "type": "string" }, "routing_number": { "type": "string" }, "iban": { "type": "string" },
          "swift": { "type": "string" }, "instructions": { "type": "string" },
          "method_note": { "type": "string", "description": "e.g. 'Paid by card ending **999'" },
          "status": { "type": "string", "enum": ["paid", "partial", "unpaid"], "description": "Drives the PAID/PARTIAL stamp; auto-detected if omitted." },
          "qr": { "type": "object", "description": "Optional payment QR; overrides the default hosted-link QR.", "properties": { "type": { "type": "string", "enum": ["upi", "pix", "sepa", "promptpay", "url", "text"] }, "value": { "type": "string" } } }
        }
      },
      "Features": {
        "type": "object",
        "properties": {
          "hosted_link": { "type": "boolean", "default": true, "description": "Generate a 7-day signed link (stores the invoice snapshot). Hosted links contain invoice data and expire after 7 days." },
          "qr": { "type": "boolean", "default": true, "description": "Render a QR; encodes the hosted link by default, or payment.qr if provided." }
        }
      },
      "InvoiceJsonResponse": {
        "type": "object",
        "properties": { "success": { "const": true }, "invoice": { "$ref": "#/components/schemas/InvoiceResponse" }, "meta": { "$ref": "#/components/schemas/Meta" }, "anonymous": { "type": "boolean" } }
      },
      "InvoiceResponse": {
        "type": "object",
        "description": "Computed invoice. Money fields are rounded to 2 decimals.",
        "properties": {
          "number": { "type": "string" }, "title": { "type": "string" }, "date": { "type": "string" }, "due_date": { "type": "string" },
          "currency": { "type": "string" }, "language": { "type": "string" }, "template": { "type": "string" },
          "from": { "$ref": "#/components/schemas/Party" }, "to": { "$ref": "#/components/schemas/Party" },
          "items": { "type": "array", "items": { "type": "object", "properties": { "description": { "type": "string" }, "quantity": { "type": "number" }, "unit": { "type": "string" }, "unit_price": { "type": "number" }, "discount": { "type": "number" }, "taxes": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "rate": { "type": "number" }, "amount": { "type": "number" } } } }, "tax_amount": { "type": "number" }, "line_total": { "type": "number" } } } },
          "subtotal": { "type": "number" }, "discount_total": { "type": "number" }, "shipping": { "type": "number" },
          "tax_lines": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "amount": { "type": "number" } } } },
          "total_tax": { "type": "number" }, "rounding_adjustment": { "type": "number" }, "grand_total": { "type": "number" },
          "deposit": { "type": "number" }, "amount_paid": { "type": "number" }, "balance_due": { "type": "number" },
          "status": { "type": "string", "enum": ["paid", "partial", "unpaid"] },
          "hosted_url": { "type": "string", "description": "7-day signed PDF link (present when features.hosted_link)." },
          "hosted_expires_at": { "type": "integer", "description": "Unix epoch seconds." },
          "qr": { "type": "object", "properties": { "source": { "type": "string", "enum": ["hosted_link", "payment"] }, "type": { "type": "string" } } }
        }
      },
      "Meta": {
        "type": "object",
        "properties": {
          "request_id": { "type": "string" }, "processing_ms": { "type": "integer" },
          "credits_remaining": { "type": "object", "properties": { "hourly": { "type": "integer" }, "weekly": { "type": "integer" } } },
          "rate_limits": { "type": "object", "properties": { "monthly_equivalent": { "type": "integer" } } }
        }
      },
      "BatchRequest": { "type": "object", "required": ["invoices"], "properties": { "invoices": { "type": "array", "minItems": 1, "maxItems": 50, "items": { "$ref": "#/components/schemas/InvoiceRequest" } } } },
      "BatchResponse": {
        "type": "object",
        "properties": {
          "success": { "const": true }, "count": { "type": "integer" },
          "results": { "type": "array", "items": { "type": "object", "properties": { "index": { "type": "integer" }, "success": { "type": "boolean" }, "invoice": { "$ref": "#/components/schemas/InvoiceResponse" }, "error": { "$ref": "#/components/schemas/ErrorBody" } } } },
          "meta": { "type": "object", "properties": { "requested": { "type": "integer" }, "generated": { "type": "integer" }, "rate_limited": { "type": "boolean" } } }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": { "id": { "type": "string" }, "url": { "type": "string" }, "events": { "type": "array", "items": { "type": "string" } }, "is_active": { "type": "boolean" }, "created_at": { "type": "integer" }, "last_delivery_at": { "type": "integer" }, "last_status": { "type": "integer" }, "secret_hint": { "type": "string" } }
      },
      "WebhookWithSecret": { "allOf": [{ "$ref": "#/components/schemas/Webhook" }, { "type": "object", "properties": { "secret": { "type": "string", "description": "Returned once, at creation." } } }] },
      "WebhookCreate": { "type": "object", "required": ["url"], "properties": { "url": { "type": "string", "description": "https:// endpoint." }, "events": { "type": "array", "items": { "type": "string", "enum": ["invoice.generated", "batch.generated"] }, "default": ["invoice.generated"] } } },
      "ErrorBody": {
        "type": "object",
        "properties": {
          "code": { "type": "string", "description": "Stable machine-readable code.", "enum": ["validation_error", "invalid_currency", "invalid_language", "invalid_template", "invalid_output", "invalid_qr_type", "invalid_json", "calculation_error", "auth_required", "invalid_api_key", "unverified_account", "rate_limit_exceeded", "rate_limit_hourly", "rate_limit_weekly", "payload_too_large", "idempotency_key_conflict", "method_not_allowed", "pdf_error", "ubl_error", "not_found", "not_provisioned"] },
          "message": { "type": "string" }
        }
      },
      "Error": { "type": "object", "properties": { "success": { "const": false }, "error": { "$ref": "#/components/schemas/ErrorBody" } } }
    }
  }
}
