{"openapi":"3.0.3","info":{"title":"Tekovate Public API","version":"1.0.0","description":"Read-only REST API for external integrations. All responses are JSON.\n\n## Authentication\n\nEvery request must include the `X-API-Key` header:\n\n```\nX-API-Key: pk_live_xxxxxxxxxxxxxxxxxxxxxxxx\n```\n\nCreate keys in your admin console: **Settings → API Keys**. Keys are shown\nexactly once on creation — store yours in a secret manager.\n\nKeys are tenant-scoped: every response is automatically filtered to the tenant\nthat owns the key.\n\n## Rate limiting\n\nEach key has a per-minute limit (default **60 requests/minute**, configurable\non creation). Exceeding the limit returns **HTTP 429**. The limiter uses a\nrolling window so short bursts don't starve subsequent calls.\n\n## Errors\n\n| Status | When |\n|--------|------|\n| 200 | Success |\n| 401 | Missing / invalid / revoked / expired API key |\n| 404 | Resource not found (or doesn't belong to your tenant) |\n| 429 | Rate limit exceeded |\n| 500 | Internal server error — please retry with backoff |\n\nError bodies are always `{ \"error\": \"<human-readable message>\" }`.\n\n## Base URL\n\n```\nhttps://akwfiwpnjneylmeaiulk.supabase.co/functions/v1/public-api\n```","contact":{"name":"Tekovate Support","url":"https://tekovatedev.cloud"}},"servers":[{"url":"https://akwfiwpnjneylmeaiulk.supabase.co/functions/v1/public-api","description":"Production"}],"tags":[{"name":"Orders","description":"Query orders placed through the e-shop, POS, or imported. Orders are returned ordered by `created_at` descending. Detail response includes line items."},{"name":"Products","description":"Browse the tenant catalog. Only active products are returned (`is_active = true`). Detail response includes per-warehouse inventory, variants, and volume pricing."},{"name":"Customers","description":"Access B2B customer records linked to your tenant."},{"name":"Catalog","description":"Categories and brands that organise your products."},{"name":"Inventory","description":"Stock levels by product/warehouse/lot. Useful for ERP/marketplace sync."},{"name":"Finance","description":"Invoices issued to customers. Detail response includes line items + legal seller/buyer snapshot."}],"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"API key created in admin console → Settings → API Keys. Format: `pk_live_` + 32 random chars."}},"schemas":{"Order":{"type":"object","description":"Order (list view — headers only). Use `GET /orders/{id}` for line items.","properties":{"id":{"type":"string","format":"uuid","description":"Immutable order UUID."},"order_no":{"type":"string","description":"Human-readable sequential number, e.g. ORD-000123."},"customer_id":{"type":"string","format":"uuid","nullable":true,"description":"Linked customer. Null for anonymous POS walk-in sales."},"status":{"type":"string","enum":["draft","pending_review","approved","picking","staged","ready_for_delivery","out_for_delivery","completed","rejected","cancelled"]},"payment_status":{"type":"string","enum":["unpaid","partially_paid","paid"]},"fulfillment_status":{"type":"string","enum":["unallocated","reserved","picking","staged","fulfilled"]},"grand_total":{"type":"string","description":"Monetary value as decimal string (4 decimal places).","example":"2420.0000"},"currency_code":{"type":"string","example":"CZK"},"created_at":{"type":"string","format":"date-time"}},"example":{"id":"a3bf1e2c-5d7e-4f01-b2a8-0e9c4f5b1d3a","order_no":"ORD-000123","customer_id":"d1e2f3a4-5b6c-7d8e-9f01-2a3b4c5d6e7f","status":"completed","payment_status":"paid","fulfillment_status":"fulfilled","grand_total":"2420.0000","currency_code":"CZK","created_at":"2026-04-16T08:12:43.521Z"}},"OrderItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"product_id":{"type":"string","format":"uuid"},"product_name":{"type":"string","nullable":true},"product_sku":{"type":"string","nullable":true},"qty":{"type":"string","example":"10.0000"},"unit_price":{"type":"string","example":"100.0000"},"tax_rate":{"type":"string","example":"0.2100"},"line_subtotal":{"type":"string","example":"1000.0000"},"line_tax_total":{"type":"string","example":"210.0000"},"line_total":{"type":"string","example":"1210.0000"}}},"OrderDetail":{"allOf":[{"$ref":"#/components/schemas/Order"},{"type":"object","properties":{"subtotal":{"type":"string"},"tax_total":{"type":"string"},"order_channel":{"type":"string","example":"eshop"},"delivery_method":{"type":"string","nullable":true},"notes":{"type":"string","nullable":true},"items":{"type":"array","items":{"$ref":"#/components/schemas/OrderItem"}}}}]},"OrderList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}}},"example":{"data":[{"id":"a3bf1e2c-5d7e-4f01-b2a8-0e9c4f5b1d3a","order_no":"ORD-000123","customer_id":"d1e2f3a4-5b6c-7d8e-9f01-2a3b4c5d6e7f","status":"completed","payment_status":"paid","fulfillment_status":"fulfilled","grand_total":"2420.0000","currency_code":"CZK","created_at":"2026-04-16T08:12:43.521Z"}]}},"Product":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sku":{"type":"string","description":"Unique product SKU within the tenant."},"name":{"type":"string"},"description":{"type":"string","nullable":true},"is_active":{"type":"boolean"},"category_id":{"type":"string","format":"uuid","nullable":true},"brand_id":{"type":"string","format":"uuid","nullable":true}},"example":{"id":"7f1a2b3c-4d5e-6f70-8192-a3b4c5d6e7f0","sku":"BEER-PILSNER-500","name":"Pilsner Urquell 500ml","description":"Classic Czech lager, 500ml bottle, 4.4% ABV.","is_active":true,"category_id":"c0b1a2d3-4e5f-6071-8293-a4b5c6d7e8f9","brand_id":"b0a1c2d3-4e5f-6071-8293-a4b5c6d7e8f9"}},"ProductDetail":{"allOf":[{"$ref":"#/components/schemas/Product"},{"type":"object","properties":{"min_order_qty":{"type":"number","example":1},"track_inventory":{"type":"boolean"},"track_lots":{"type":"boolean"},"slug":{"type":"string","nullable":true},"inventory":{"type":"array","description":"Per-warehouse stock levels.","items":{"type":"object","properties":{"warehouse_id":{"type":"string","format":"uuid"},"qty_on_hand":{"type":"string"},"qty_reserved":{"type":"string"},"qty_staged":{"type":"string"},"qty_available":{"type":"string","description":"on_hand − reserved − staged."}}}},"variants":{"type":"array","items":{"$ref":"#/components/schemas/Variant"}},"pricing":{"type":"array","description":"Volume pricing tiers.","items":{"type":"object","properties":{"unit_price":{"type":"string"},"min_qty":{"type":"string"},"currency_code":{"type":"string"}}}}}}]},"ProductList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Product"}}},"example":{"data":[{"id":"7f1a2b3c-4d5e-6f70-8192-a3b4c5d6e7f0","sku":"BEER-PILSNER-500","name":"Pilsner Urquell 500ml","description":"Classic Czech lager, 500ml bottle, 4.4% ABV.","is_active":true,"category_id":"c0b1a2d3-4e5f-6071-8293-a4b5c6d7e8f9","brand_id":"b0a1c2d3-4e5f-6071-8293-a4b5c6d7e8f9"}]}},"Variant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sku":{"type":"string"},"name":{"type":"string","nullable":true},"attributes":{"type":"object","additionalProperties":{"type":"string"},"example":{"size":"M","color":"red"}},"price_override":{"type":"string","nullable":true},"is_active":{"type":"boolean"}}},"Category":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","nullable":true},"name":{"type":"string"},"parent_id":{"type":"string","format":"uuid","nullable":true},"sort_order":{"type":"integer"},"icon":{"type":"string","nullable":true,"description":"Emoji icon."}}},"Brand":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","nullable":true},"name":{"type":"string"},"logo_url":{"type":"string","nullable":true}}},"InventoryBalance":{"type":"object","properties":{"product_id":{"type":"string","format":"uuid"},"warehouse_id":{"type":"string","format":"uuid"},"lot_id":{"type":"string","format":"uuid","nullable":true},"qty_on_hand":{"type":"string"},"qty_reserved":{"type":"string"},"qty_staged":{"type":"string"},"qty_available":{"type":"string"}}},"Invoice":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"invoice_no":{"type":"string","example":"INV-000001"},"invoice_date":{"type":"string","format":"date"},"currency_code":{"type":"string"},"customer_id":{"type":"string","format":"uuid"},"grand_total":{"type":"string"},"status":{"type":"string","enum":["draft","issued","partially_paid","paid","overdue","cancelled","voided"]}}},"InvoiceItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"description":{"type":"string"},"qty":{"type":"string"},"unit_price":{"type":"string"},"tax_rate":{"type":"string"},"line_subtotal":{"type":"string"},"line_tax_total":{"type":"string"},"line_total":{"type":"string"},"product_id":{"type":"string","format":"uuid","nullable":true}}},"InvoiceDetail":{"allOf":[{"$ref":"#/components/schemas/Invoice"},{"type":"object","properties":{"subtotal":{"type":"string"},"tax_total":{"type":"string"},"seller_legal_name":{"type":"string","nullable":true},"seller_vat_no":{"type":"string","nullable":true},"buyer_legal_name":{"type":"string","nullable":true},"buyer_vat_no":{"type":"string","nullable":true},"issued_at":{"type":"string","format":"date-time","nullable":true},"items":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceItem"}}}}]},"Customer":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","nullable":true,"description":"Short internal customer code."},"company_name":{"type":"string"},"email":{"type":"string","format":"email","nullable":true},"phone":{"type":"string","nullable":true},"status":{"type":"string","enum":["active","prospect","blocked","archived"]}},"example":{"id":"d1e2f3a4-5b6c-7d8e-9f01-2a3b4c5d6e7f","code":"CUS-00042","company_name":"Restaurace U Fleku s.r.o.","email":"pokladna@ufleku.cz","phone":"+420 224 934 019","status":"active"}},"CustomerList":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Customer"}}},"example":{"data":[{"id":"d1e2f3a4-5b6c-7d8e-9f01-2a3b4c5d6e7f","code":"CUS-00042","company_name":"Restaurace U Fleku s.r.o.","email":"pokladna@ufleku.cz","phone":"+420 224 934 019","status":"active"}]}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message."}}}},"responses":{"Unauthorized":{"description":"Missing, invalid, revoked, or expired API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"value":{"error":"Missing X-API-Key header"}},"invalid":{"value":{"error":"Key not found"}},"revoked":{"value":{"error":"Key revoked"}}}}}},"NotFound":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Not found"}}}},"RateLimited":{"description":"Too many requests — exceeded this key's per-minute quota. Wait and retry with exponential backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Rate limit exceeded"}}}}}},"security":[{"apiKey":[]}],"paths":{"/orders":{"get":{"tags":["Orders"],"summary":"List orders","description":"Returns the most recent orders for your tenant, newest first. Filter by `status` to narrow down (e.g. only completed orders).","parameters":[{"name":"limit","in":"query","required":false,"description":"Max rows to return. Capped at 200.","schema":{"type":"integer","default":50,"minimum":1,"maximum":200},"example":10},{"name":"status","in":"query","required":false,"description":"Filter by exact order status.","schema":{"type":"string","enum":["draft","pending_review","approved","picking","staged","ready_for_delivery","out_for_delivery","completed","rejected","cancelled"]},"example":"completed"}],"responses":{"200":{"description":"List of orders.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/orders/{id}":{"get":{"tags":["Orders"],"summary":"Get order by ID (with line items)","description":"Returns an order with its `items[]`, totals, channel, and delivery method. 404 if it doesn't belong to your tenant.","parameters":[{"name":"id","in":"path","required":true,"description":"Order UUID.","schema":{"type":"string","format":"uuid"},"example":"a3bf1e2c-5d7e-4f01-b2a8-0e9c4f5b1d3a"}],"responses":{"200":{"description":"The order with items.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderDetail"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/products":{"get":{"tags":["Products"],"summary":"List products","description":"Returns active catalog products. Optionally filter by category UUID.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":200}},{"name":"category","in":"query","required":false,"description":"Filter products by category UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"List of products.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/products/{id}":{"get":{"tags":["Products"],"summary":"Get product by ID (with inventory, variants, pricing)","description":"Enriched product detail: per-warehouse stock (`inventory[]`), active `variants[]`, and volume `pricing[]` tiers. Useful for external product pages and marketplace sync.","parameters":[{"name":"id","in":"path","required":true,"description":"Product UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The product with inventory/variants/pricing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductDetail"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/categories":{"get":{"tags":["Catalog"],"summary":"List categories","description":"Returns all categories (flat list) ordered by `sort_order`. Use `parent_id` to build a tree.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":200}}],"responses":{"200":{"description":"List of categories.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Category"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/brands":{"get":{"tags":["Catalog"],"summary":"List brands","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":200}}],"responses":{"200":{"description":"List of brands.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Brand"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/inventory":{"get":{"tags":["Inventory"],"summary":"List stock balances","description":"Per product / warehouse / lot stock. Filter by `product_id` or `warehouse_id`. Response adds a computed `qty_available = qty_on_hand − qty_reserved − qty_staged`.","parameters":[{"name":"product_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"warehouse_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":200}}],"responses":{"200":{"description":"Stock balances.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InventoryBalance"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/invoices":{"get":{"tags":["Finance"],"summary":"List invoices","description":"Filter by `status` or `customer_id`. Ordered by invoice_date descending.","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["draft","issued","partially_paid","paid","overdue","cancelled","voided"]}},{"name":"customer_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":200}}],"responses":{"200":{"description":"List of invoices.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/invoices/{id}":{"get":{"tags":["Finance"],"summary":"Get invoice by ID (with line items)","description":"Returns legal snapshot (seller / buyer), totals, and `items[]`. Invoices are immutable after issue — use credit notes to reverse.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Invoice with items.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceDetail"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/customers":{"get":{"tags":["Customers"],"summary":"List customers","description":"Returns customers linked to your tenant.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":200}}],"responses":{"200":{"description":"List of customers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/customers/{id}":{"get":{"tags":["Customers"],"summary":"Get customer by ID","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The customer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}}}}