--- name: moloni-api description: >- Moloni API v2 para facturacao portuguesa - autenticacao, documentos, clientes, produtos. Usar quando trabalhar com Moloni API, criar/consultar facturas, recibos, notas de credito, clientes, ou qualquer operacao de facturacao via Moloni. Triggers: moloni, factura, recibo, nota de credito, billing, invoicing, facturacao portuguesa. --- # Moloni API v2 Operações de facturação portuguesa via Moloni API. MCP server disponível em `/opt/moloni/`. ## 4 Regras Críticas 1. **`access_token` na QUERY STRING** - Nunca no POST body (causa 403) 2. **Endpoints camelCase** - `creditNotes/`, `invoiceReceipts/`, `documentSets/` 3. **Arrays form-encoded** - `payments[0][payment_method_id]`, nunca `json.dumps()` 4. **`net_value` = Total COM IVA** - Nome enganador! Desk `total` = Moloni `net_value`. Base = `net_value / 1.23` ## Autenticação ```python # Grant = GET (não POST!) r = requests.get('https://api.moloni.pt/v2/grant/', params={ 'grant_type': 'password', 'client_id': 'evidentedespertar', 'client_secret': 'aa48e86bd574bf81ca2d7f624c8b5de0284fb97d', 'username': 'contabilidade@descomplicar.pt', 'password': '6EMVh^RHA)d5k!%s' # %s literal, sem f-string! }) token = r.json()['access_token'] ``` ## Empresa | Campo | Valor | |-------|-------| | Company ID | 69473 | | Série D | document_set_id: 630300 | | Transf. Bancária | payment_method_id: 400878 | ## Formato Chamadas ```python # CORRECTO r = requests.post('https://api.moloni.pt/v2/invoices/getAll/', params={'access_token': token}, # token aqui! data={'company_id': '69473', 'qty': '50'} # dados aqui ) ``` ## Workflows Comuns ### Listar facturas ```python data = {'company_id': '69473', 'document_set_id': '630300', 'qty': '50', 'offset': '0'} ``` ### Criar recibo ```python data = { 'company_id': '69473', 'date': '2026-02-05', 'document_set_id': '630300', 'customer_id': str(customer_id), 'net_value': str(valor), 'associated_documents[0][associated_id]': str(invoice_document_id), 'associated_documents[0][value]': str(valor), 'payments[0][payment_method_id]': '400878', 'payments[0][date]': '2026-02-05', 'payments[0][value]': str(valor), 'status': '1' } r = requests.post('.../receipts/insert/', params={'access_token': token}, data=data) ``` ### Verificar reconciliação Antes de criar recibo, verificar `reconciled_value` e `reverse_associated_documents` da factura. ## Restrições - Data mínima documentos: **>= 2025-10-28** (período AT) - Para facturas antigas: usar data actual no recibo ## Erros Comuns | Erro | Causa | Solução | |------|-------|---------| | 403 Forbidden | Token no body | Mover para `params=` | | 404 Not Found | Case errado ou sem `/` | Verificar camelCase + trailing slash | | `["12 date >= ..."]` | Data antiga | Usar data actual | | `["10 associated_id"]` | Factura já reconciliada | Verificar `reconciled_value` | ## MCP vs API Directa O MCP Moloni (`mcp__moloni__*`) gere tokens automaticamente. Para operações pontuais ou scripts batch, usar API directa via SSH no mcp-hub. ## Sandbox (Desenvolvimento) Para testes sem afectar dados reais: https://www.moloni.pt/dev/sandbox/ A sandbox fornece um ambiente isolado com dados fictícios para desenvolvimento e testes de integração. ## Referências - **[references/api-reference.md](references/api-reference.md)** - Credenciais, formatos, mapeamento clientes, erros - **[references/endpoints.md](references/endpoints.md)** - Catálogo completo de endpoints - **Docs oficiais:** https://www.moloni.pt/dev/endpoints/ - **Sandbox:** https://www.moloni.pt/dev/sandbox/