{"openapi":"3.1.0","info":{"title":"Grupo Los Roques ERP API","version":"0.4.0","description":"Carril 2 S0 + Fase A–D (M1–M5). FEL production emission is disabled. module.purchasing, module.sales, module.receivables and module.payables are OFF by default."},"servers":[{"url":"/api/v1","description":"Versioned REST"}],"tags":[{"name":"Health"},{"name":"Drafts"},{"name":"Maestros"},{"name":"Inventario"},{"name":"Compras"},{"name":"Ventas"},{"name":"Cartera"},{"name":"CxP"},{"name":"Reportes"},{"name":"Aprobaciones"},{"name":"Org"},{"name":"FEL"}],"components":{"securitySchemes":{"AuthStub":{"type":"apiKey","in":"header","name":"x-user-email","description":"Auth stub. Seeded emails: gabriela@, patricia@, victor@, admin@, aprobador@, operador@, visor@ grupolosroques.local"}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Required on draft create/approve/reject. Same key + payload replays the stored response."}},"schemas":{"Health":{"type":"object","properties":{"ok":{"type":"boolean"},"felEmit":{"type":"boolean","enum":[false]},"flags":{"type":"object","properties":{"fel.emit":{"type":"boolean"},"inventory.sor":{"type":"boolean"},"module.purchasing":{"type":"boolean"},"module.sales":{"type":"boolean"},"module.receivables":{"type":"boolean"},"module.payables":{"type":"boolean"}}}}},"PurchaseOrder":{"type":"object","properties":{"id":{"type":"string"},"number":{"type":"string"},"status":{"type":"string","enum":["DRAFT","PENDING_APPROVAL","APPROVED","REJECTED"]},"source":{"type":"string","enum":["ROP_ALERT","MANUAL"]}}},"Draft":{"type":"object","properties":{"id":{"type":"string"},"entityType":{"type":"string","enum":["PRODUCT","SKU"]},"action":{"type":"string","enum":["CREATE","UPDATE","DELETE"]},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED"]},"payload":{"type":"object"}}}}},"security":[{"AuthStub":[]}],"paths":{"/health":{"get":{"tags":["Health"],"summary":"Liveness + flags (felEmit always false in S0)","security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"},"example":{"ok":true,"service":"grupo-los-roques-erp","version":"0.4.0","phase":"S0+FaseA+FaseB+FaseC+FaseD","carril":2,"felEmit":false,"flags":{"fel.emit":false,"inventory.sor":false,"module.purchasing":false,"module.sales":false},"constants":{"leadTimeWeeks":[9,12],"ropCoverTriggerWeeks":{"min":16,"max":18},"bodegas":["Central","Kemik","Circle K","MASS"]}}}}}}}},"/openapi":{"get":{"tags":["Health"],"summary":"OpenAPI 3.1 document","security":[],"responses":{"200":{"description":"OpenAPI JSON"}}}},"/flags":{"get":{"tags":["Health"],"summary":"Feature flags","security":[],"responses":{"200":{"description":"Flags"}}}},"/me":{"get":{"tags":["Org"],"summary":"Current auth-stub user","responses":{"200":{"description":"User"},"401":{"description":"Unauthenticated"}}}},"/drafts":{"get":{"tags":["Drafts"],"summary":"List drafts (optional ?status=PENDING)","responses":{"200":{"description":"Draft list"}}},"post":{"tags":["Drafts"],"summary":"Create a maestro draft","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Draft"},"example":{"entityType":"PRODUCT","action":"CREATE","payload":{"code":"MASKKING","name":"Maskking","brand":"Maskking","category":"Vape"}}}}},"responses":{"201":{"description":"Created"},"400":{"description":"Validation or missing Idempotency-Key"}}}},"/drafts/{id}/approve":{"post":{"tags":["Drafts"],"summary":"Approve and apply a pending draft","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Approved"},"403":{"description":"Role"},"409":{"description":"Not pending"}}}},"/drafts/{id}/reject":{"post":{"tags":["Drafts"],"summary":"Reject a pending draft","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Rejected"}}}},"/products":{"get":{"tags":["Maestros"],"summary":"List products","responses":{"200":{"description":"Products"}}},"post":{"tags":["Maestros"],"summary":"Create PRODUCT draft","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Draft created"}}}},"/products/{id}":{"patch":{"tags":["Maestros"],"summary":"Create PRODUCT UPDATE draft","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Draft created"}}},"delete":{"tags":["Maestros"],"summary":"Create PRODUCT DELETE draft","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Draft created"}}}},"/skus":{"get":{"tags":["Maestros"],"summary":"List SKUs","responses":{"200":{"description":"SKUs"}}},"post":{"tags":["Maestros"],"summary":"Create SKU draft","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Draft created"}}}},"/skus/{id}":{"patch":{"tags":["Maestros"],"summary":"Create SKU UPDATE draft","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Draft created"}}},"delete":{"tags":["Maestros"],"summary":"Create SKU DELETE draft","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Draft created"}}}},"/org":{"get":{"tags":["Org"],"summary":"Organization stub","responses":{"200":{"description":"Org"}}}},"/users":{"get":{"tags":["Org"],"summary":"Users stub","responses":{"200":{"description":"Users"}}}},"/roles":{"get":{"tags":["Org"],"summary":"Roles stub","responses":{"200":{"description":"Roles"}}}},"/bodegas":{"get":{"tags":["Inventario"],"summary":"Bodegas (Central, Kemik, Circle K, MASS)","responses":{"200":{"description":"Bodegas"}}}},"/inventory/balances":{"get":{"tags":["Inventario"],"summary":"Multi-bodega balances + ROP decision","responses":{"200":{"description":"Balances"}}}},"/inventory/movements":{"get":{"tags":["Inventario"],"summary":"List movements","responses":{"200":{"description":"Movements"}}},"post":{"tags":["Inventario"],"summary":"Record a movement (slice; inventory.sor OFF)","responses":{"201":{"description":"Created"}}}},"/inventory/rop":{"get":{"tags":["Inventario"],"summary":"ROP decision layer (16–18 week cover trigger)","responses":{"200":{"description":"ROP"}}}},"/purchase-orders":{"get":{"tags":["Compras"],"summary":"List OCs (requires module.purchasing)","responses":{"200":{"description":"OC list"},"403":{"description":"Flag off"}}},"post":{"tags":["Compras"],"summary":"Create OC draft from ROP alerts or manual lines","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Draft created"},"403":{"description":"Flag off"}}}},"/purchase-orders/pending":{"get":{"tags":["Compras"],"summary":"Victor queue (pending_approval)","responses":{"200":{"description":"Pending OCs"}}}},"/purchase-orders/rop-preview":{"get":{"tags":["Compras"],"summary":"Effective pipeline + suggested Maskking qty","responses":{"200":{"description":"Preview"}}}},"/purchase-orders/{id}":{"get":{"tags":["Compras"],"summary":"OC detail + lines + receipts","responses":{"200":{"description":"OC"}}}},"/purchase-orders/{id}/submit":{"post":{"tags":["Compras"],"summary":"draft → pending_approval","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Submitted"}}}},"/purchase-orders/{id}/approve":{"post":{"tags":["Compras"],"summary":"Victor approve (no self-approve) → confirmed OC","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Approved"},"403":{"description":"Victor gate"}}}},"/purchase-orders/{id}/reject":{"post":{"tags":["Compras"],"summary":"Victor reject (no self-reject)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Rejected"}}}},"/purchase-orders/{id}/export":{"get":{"tags":["Compras"],"summary":"Optional CSV/XLSX for human WhatsApp. Zero auto-message.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","schema":{"type":"string","enum":["csv","xlsx"]}}],"responses":{"200":{"description":"File"},"409":{"description":"Not approved"}}}},"/purchase-orders/{id}/receive":{"post":{"tags":["Compras"],"summary":"Receive full 5_000 batches → inventory movement (default Central)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Receipt posted"}}}},"/customers":{"get":{"tags":["Ventas"],"summary":"DMART + MERCADOWEB (requires module.sales)","responses":{"200":{"description":"Customers"},"403":{"description":"Flag off"}}}},"/sales-orders":{"get":{"tags":["Ventas"],"summary":"List Pedidos","responses":{"200":{"description":"List"},"403":{"description":"Flag off"}}},"post":{"tags":["Ventas"],"summary":"Create Pedido draft (Idempotency-Key)","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Draft"},"409":{"description":"Anti-duplicado PO/periodo"}}}},"/sales-orders/ingest":{"post":{"tags":["Ventas"],"summary":"CSV/JSON ingest stub PeYa PO or Kemik sold report → Pedido draft. No live PeYa API.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Draft"},"403":{"description":"Flag off"}}}},"/aprobaciones":{"get":{"tags":["Aprobaciones"],"summary":"Bandeja de aprobaciones filtrada por la persona actual (Gabriela: ventas, Victor: compras)","responses":{"200":{"description":"Inbox + count"}}}},"/sales-orders/pending":{"get":{"tags":["Ventas"],"summary":"Pedidos pendientes de aprobación","responses":{"200":{"description":"Queue"}}}},"/sales-orders/queue":{"get":{"tags":["Ventas"],"summary":"Cola Pedido + Factura prep + NC","responses":{"200":{"description":"Queue"}}}},"/sales-orders/{id}":{"get":{"tags":["Ventas"],"summary":"Pedido detail","responses":{"200":{"description":"Pedido"}}}},"/sales-orders/{id}/submit":{"post":{"tags":["Ventas"],"summary":"draft → pending_approval","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Submitted"}}}},"/sales-orders/{id}/approve":{"post":{"tags":["Ventas"],"summary":"salesApproverCapable approve (no self-approve, no Gabriela hardcode)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Approved"},"403":{"description":"Gate"}}}},"/sales-orders/{id}/reject":{"post":{"tags":["Ventas"],"summary":"Reject pending Pedido (clears dedupe key)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Rejected"}}}},"/sales-orders/{id}/invoice-prep":{"post":{"tags":["Ventas"],"summary":"Convert approved Pedido → Factura prep draft (internal, not DTE)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Factura prep"},"409":{"description":"Anti-duplicado"}}}},"/invoice-preps":{"get":{"tags":["Ventas"],"summary":"List Factura prep","responses":{"200":{"description":"List"}}}},"/invoice-preps/pending":{"get":{"tags":["Ventas"],"summary":"Factura prep pending_approval","responses":{"200":{"description":"Queue"}}}},"/invoice-preps/{id}":{"get":{"tags":["Ventas"],"summary":"Factura prep detail + NC + anulación","responses":{"200":{"description":"Detail"}}}},"/invoice-preps/{id}/submit":{"post":{"tags":["Ventas"],"summary":"Factura prep draft → pending_approval","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Submitted"}}}},"/invoice-preps/{id}/approve":{"post":{"tags":["Ventas"],"summary":"Approve Factura prep (salesApproverCapable)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Approved"}}}},"/invoice-preps/{id}/reject":{"post":{"tags":["Ventas"],"summary":"Reject Factura prep","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Rejected"}}}},"/invoice-preps/{id}/credit-notes":{"post":{"tags":["Ventas"],"summary":"Create NC linked to approved Factura prep (internal)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"NC"},"409":{"description":"Not linked / not approved"}}}},"/invoice-preps/{id}/annul":{"post":{"tags":["Ventas"],"summary":"Anulación interna. Requires annulmentCapable.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Annulled"},"403":{"description":"Permission"}}}},"/credit-notes/{id}":{"get":{"tags":["Ventas"],"summary":"NC detail","responses":{"200":{"description":"NC"}}}},"/credit-notes/{id}/submit":{"post":{"tags":["Ventas"],"summary":"NC draft → pending_approval","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Submitted"}}}},"/credit-notes/{id}/approve":{"post":{"tags":["Ventas"],"summary":"Approve NC (salesApproverCapable)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Approved"}}}},"/credit-notes/{id}/reject":{"post":{"tags":["Ventas"],"summary":"Reject NC","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Rejected"}}}},"/receivables":{"get":{"tags":["Cartera"],"summary":"List CxC (403 if module.receivables off)","responses":{"200":{"description":"Receivables + aging"},"403":{"description":"Flag off"}}}},"/payment-receipts":{"get":{"tags":["Cartera"],"summary":"List Pagos Recibidos prep","responses":{"200":{"description":"Payment receipts"}}}},"/payment-receipts/ingest":{"post":{"tags":["Cartera"],"summary":"Ingest PeYa/Kemik payment notice stub → PR draft","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"201":{"description":"Draft created"},"403":{"description":"Flag off"}}}},"/payment-receipts/{id}/approve":{"post":{"tags":["Cartera"],"summary":"Patricia (receivablesCapable) or Victor gate; no self-approve","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Approved"}}}},"/payables":{"get":{"tags":["CxP"],"summary":"List lightweight CxP from approved OC/recepciones","responses":{"200":{"description":"Payables"},"403":{"description":"Flag off"}}}},"/reports":{"get":{"tags":["Reportes"],"summary":"Available core reports","responses":{"200":{"description":"Report catalog"}}}},"/reports/{kind}":{"get":{"tags":["Reportes"],"summary":"Download Excel (ventas | inventario | cartera)","parameters":[{"name":"kind","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"XLSX"},"403":{"description":"Flag off"}}}},"/fel/emit":{"post":{"tags":["FEL"],"summary":"Blocked FEL emission (StubCertifier)","responses":{"403":{"description":"Never emits in S0"}}}},"/inngest/events":{"get":{"tags":["Health"],"summary":"Local stub log of draft.created events","responses":{"200":{"description":"Event log"}}}}}}