{"openapi":"3.1.0","info":{"title":"AMAI Budget — Public API","version":"1.0.0","description":"REST API para integrar AMAI Budget en tus sistemas (Zapier, Make, n8n, ERPs, back-office). Autenticación por API key (Bearer), scopes granulares, errores RFC 9457 y paginación por limit/offset. El endpoint de escritura crea únicamente PRESUPUESTOS en BORRADOR (no fiscales): nunca facturas, numeración fiscal ni registros VeriFactu.","contact":{"name":"AMAI Solutions","url":"https://budget.amai.run/developers"}},"servers":[{"url":"https://budget.amai.run","description":"Producción"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Budgets","description":"Presupuestos (documentos no fiscales)."},{"name":"Clients","description":"Clientes guardados."},{"name":"Invoices","description":"Facturas (solo lectura)."}],"paths":{"/api/v1/budgets":{"get":{"tags":["Budgets"],"summary":"Listar presupuestos","description":"Devuelve los documentos de tipo budget de la empresa de la clave. Scope: `budgets:read`.","operationId":"listBudgets","security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"description":"Page size. Clamped to 1..100. Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"offset","in":"query","required":false,"description":"Zero-based row offset for pagination. Defaults to 0.","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Página de presupuestos.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BudgetSummary"}},"limit":{"type":"integer","example":50},"offset":{"type":"integer","example":0}},"required":["data","limit","offset"]}}}},"401":{"description":"Missing, malformed, invalid, or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key is valid but lacks the required scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"The public API is disabled (feature flag OFF) — the surface is invisible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Per-key rate limit exceeded (120 requests / minute sliding window).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal error. Never leaks internal details or another tenant’s data.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"post":{"tags":["Budgets"],"summary":"Crear un presupuesto en borrador (no fiscal)","description":"Crea un PRESUPUESTO en estado `draft`. Scope: `budgets:write`. document_type se fuerza a \"budget\" y status a \"draft\" en el servidor — este endpoint NUNCA crea facturas, notas de crédito, numeración fiscal ni registros VeriFactu. Los totales se recalculan en el servidor. Admite la cabecera opcional `Idempotency-Key` para evitar duplicados en reintentos.","operationId":"createBudget","security":[{"bearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave de idempotencia (recomendado un UUID) para deduplicar reintentos. Dos peticiones con la misma clave y empresa devuelven el mismo presupuesto en lugar de crear dos.","schema":{"type":"string","example":"11111111-1111-1111-1111-111111111111"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBudgetInput"}}}},"responses":{"201":{"description":"Presupuesto en borrador creado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedBudget"}}}},"400":{"description":"Bad request — invalid body / validation error / rejected fiscal document_type.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, invalid, or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key is valid but lacks the required scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"The public API is disabled (feature flag OFF) — the surface is invisible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Per-key rate limit exceeded (120 requests / minute sliding window).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal error. Never leaks internal details or another tenant’s data.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/clients":{"get":{"tags":["Clients"],"summary":"Listar clientes","description":"Devuelve los clientes guardados de la empresa de la clave. Scope: `clients:read`.","operationId":"listClients","security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"description":"Page size. Clamped to 1..100. Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"offset","in":"query","required":false,"description":"Zero-based row offset for pagination. Defaults to 0.","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Página de clientes.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ClientSummary"}},"limit":{"type":"integer","example":50},"offset":{"type":"integer","example":0}},"required":["data","limit","offset"]}}}},"401":{"description":"Missing, malformed, invalid, or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key is valid but lacks the required scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"The public API is disabled (feature flag OFF) — the surface is invisible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Per-key rate limit exceeded (120 requests / minute sliding window).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal error. Never leaks internal details or another tenant’s data.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/invoices":{"get":{"tags":["Invoices"],"summary":"Listar facturas (solo lectura)","description":"Devuelve los documentos de tipo invoice de la empresa de la clave. Scope: `invoices:read`. Solo lectura: nunca toca el libro fiscal ni VeriFactu.","operationId":"listInvoices","security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"description":"Page size. Clamped to 1..100. Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"offset","in":"query","required":false,"description":"Zero-based row offset for pagination. Defaults to 0.","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Página de facturas.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceSummary"}},"limit":{"type":"integer","example":50},"offset":{"type":"integer","example":0}},"required":["data","limit","offset"]}}}},"401":{"description":"Missing, malformed, invalid, or revoked API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"The key is valid but lacks the required scope.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"The public API is disabled (feature flag OFF) — the surface is invisible.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Per-key rate limit exceeded (120 requests / minute sliding window).","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Internal error. Never leaks internal details or another tenant’s data.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"amai_<env>_<hex>","description":"API key en la cabecera `Authorization: Bearer <clave>`. Genera y gestiona tus claves en Ajustes → API. Scopes disponibles: `budgets:read`, `clients:read`, `invoices:read`, `budgets:write`."}},"schemas":{"Problem":{"type":"object","description":"RFC 9457 problem details. Returned with Content-Type: application/problem+json.","properties":{"type":{"type":"string","format":"uri","example":"https://budget.amai.run/problems/forbidden","description":"A URI reference identifying the problem type."},"title":{"type":"string","example":"Forbidden","description":"Short, human-readable summary."},"status":{"type":"integer","example":403,"description":"HTTP status code."},"detail":{"type":"string","example":"API key lacks required scope 'budgets:write'.","description":"Human-readable explanation specific to this occurrence."}},"required":["type","title","status","detail"]},"BudgetSummary":{"type":"object","description":"Curated, non-sensitive columns of a budget-type document.","properties":{"id":{"type":"string","format":"uuid"},"budget_number":{"type":"string","example":"PRES-2026-0042","nullable":true},"document_type":{"type":"string","example":"budget"},"status":{"type":"string","example":"draft"},"payment_status":{"type":"string","nullable":true,"example":"unpaid"},"date":{"type":"string","format":"date","nullable":true},"validity":{"type":"string","nullable":true,"description":"Free-text validity period."},"client_name":{"type":"string","nullable":true,"example":"ACME SL"},"client_email":{"type":"string","format":"email","nullable":true},"client_phone":{"type":"string","nullable":true},"document_currency":{"type":"string","example":"EUR"},"subtotal":{"type":"number","example":1600},"iva_amount":{"type":"number","example":336},"total":{"type":"number","example":1936},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ClientSummary":{"type":"object","description":"A saved client of the calling key’s company.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"ACME SL"},"cif":{"type":"string","nullable":true,"example":"B12345678"},"email":{"type":"string","format":"email","nullable":true},"phone":{"type":"string","nullable":true},"address":{"type":"string","nullable":true},"location":{"type":"string","nullable":true},"province":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"postal_code":{"type":"string","nullable":true},"representative":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"InvoiceSummary":{"type":"object","description":"Curated columns of an invoice-type document. READ-ONLY: this surface never issues or alters a fiscal document.","properties":{"id":{"type":"string","format":"uuid"},"budget_number":{"type":"string","example":"FAC-2026-0007","nullable":true},"document_type":{"type":"string","example":"invoice"},"status":{"type":"string","example":"issued"},"payment_status":{"type":"string","nullable":true,"example":"paid"},"paid_at":{"type":"string","format":"date-time","nullable":true},"date":{"type":"string","format":"date","nullable":true},"client_name":{"type":"string","nullable":true},"client_email":{"type":"string","format":"email","nullable":true},"document_currency":{"type":"string","example":"EUR"},"subtotal":{"type":"number"},"iva_amount":{"type":"number"},"total":{"type":"number"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"CreateBudgetItem":{"type":"object","required":["concept","units","unit_price"],"properties":{"concept":{"type":"string","example":"Landing page","description":"Line-item description."},"units":{"type":"number","minimum":0,"example":1},"unit_price":{"type":"number","example":400,"description":"VAT-exclusive unit price."},"unit_type":{"type":"string","example":"proyecto","description":"Unit label (e.g. hora, mes, ud.)."},"iva_rate":{"type":"number","example":21,"description":"VAT percentage for this line. Defaults to the company setting when omitted."},"discount_type":{"type":"string","enum":["percentage","amount"],"description":"Optional per-line discount type."},"discount_value":{"type":"number","description":"Optional per-line discount value."}}},"CreateBudgetInput":{"type":"object","required":["client_name","items"],"description":"Payload to create a DRAFT, NON-FISCAL budget. document_type is always forced to \"budget\" and status to \"draft\" server-side — you cannot create an invoice, credit note, or any fiscal document through this endpoint.","properties":{"client_name":{"type":"string","example":"ACME SL"},"client_email":{"type":"string","format":"email","example":"ops@acme.example"},"items":{"type":"array","minItems":1,"items":{"type":"object","required":["concept","units","unit_price"],"properties":{"concept":{"type":"string","example":"Landing page","description":"Line-item description."},"units":{"type":"number","minimum":0,"example":1},"unit_price":{"type":"number","example":400,"description":"VAT-exclusive unit price."},"unit_type":{"type":"string","example":"proyecto","description":"Unit label (e.g. hora, mes, ud.)."},"iva_rate":{"type":"number","example":21,"description":"VAT percentage for this line. Defaults to the company setting when omitted."},"discount_type":{"type":"string","enum":["percentage","amount"],"description":"Optional per-line discount type."},"discount_value":{"type":"number","description":"Optional per-line discount value."}}}},"notes":{"type":"string","description":"Free-text notes appended to the budget."},"description":{"type":"string","description":"Budget description / intro block."},"document_currency":{"type":"string","example":"EUR","description":"ISO 4217 currency code."},"validity":{"type":"string","example":"30 días","description":"Free-text validity period."}}},"CreatedBudget":{"type":"object","description":"The created DRAFT budget. Always status=\"draft\", document_type=\"budget\".","properties":{"id":{"type":"string","format":"uuid"},"budget_number":{"type":"string","example":"PRES-2026-0043","description":"Non-fiscal draft number."},"status":{"type":"string","example":"draft"},"document_type":{"type":"string","example":"budget"},"subtotal":{"type":"number","example":1600},"iva_amount":{"type":"number","example":336},"total":{"type":"number","example":1936},"document_currency":{"type":"string","example":"EUR"},"created_at":{"type":"string","format":"date-time"}}}}},"x-scopes":{"budgets:read":"Leer presupuestos.","clients:read":"Leer clientes guardados.","invoices:read":"Leer facturas (solo lectura).","budgets:write":"Crear presupuestos en borrador (no fiscales)."},"x-rate-limit":{"requests":120,"window":"1 minuto","scope":"por clave (ventana deslizante)"}}