Plugins: automacao, crm-ops, design-media, dev-tools, gestao, infraestrutura, marketing, negocio, perfex-dev, project-manager, wordpress + hello-plugin (existente). Totais: 83 skills, 44 agents, 12 datasets.json Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
302 lines
9.0 KiB
Markdown
302 lines
9.0 KiB
Markdown
# Moloni API v2 - Reference
|
|
|
|
## Empresa Descomplicar
|
|
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| Company ID | 69473 |
|
|
| Empresa | Evidente Despertar, Lda |
|
|
| Client ID | evidentedespertar |
|
|
| NIF | 516557498 |
|
|
| MCP Server | `/opt/moloni/` em mcp-hub |
|
|
| Service | `moloni.service` (systemd) |
|
|
| .env | `/opt/moloni/.env` |
|
|
| Token storage | `/opt/moloni/.moloni/69473/.token_metadata.json` |
|
|
|
|
## Sandbox (Desenvolvimento/Testes)
|
|
|
|
Para testar integrações sem afectar dados reais: https://www.moloni.pt/dev/sandbox/
|
|
|
|
A sandbox fornece um ambiente isolado com dados fictícios. Usar sempre que:
|
|
- Desenvolver novas integrações
|
|
- Testar criação/modificação de documentos
|
|
- Depurar erros de formato ou validação
|
|
|
|
## Autenticacao
|
|
|
|
### Password Grant (GET, nao POST!)
|
|
|
|
```python
|
|
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'
|
|
})
|
|
token = r.json()['access_token']
|
|
```
|
|
|
|
### Refresh Token
|
|
|
|
```python
|
|
r = requests.get('https://api.moloni.pt/v2/grant/', params={
|
|
'grant_type': 'refresh_token',
|
|
'client_id': 'evidentedespertar',
|
|
'client_secret': 'aa48e86bd574bf81ca2d7f624c8b5de0284fb97d',
|
|
'refresh_token': '<refresh_token>'
|
|
})
|
|
```
|
|
|
|
### Regras de Autenticacao
|
|
|
|
- Grant endpoint e **GET** (nao POST)
|
|
- Password contem `%s` - em Python usar: `'6EMVh^RHA)d5k!%s'` (string literal, sem f-string)
|
|
- Token expira em 3600 segundos (1 hora)
|
|
- Refresh token nao expira mas so pode ser usado uma vez
|
|
|
|
## Formato das Chamadas API
|
|
|
|
### Regra Fundamental
|
|
|
|
```
|
|
access_token -> QUERY STRING (params)
|
|
dados -> POST BODY (data, form-urlencoded)
|
|
```
|
|
|
|
### Exemplo Correcto
|
|
|
|
```python
|
|
r = requests.post('https://api.moloni.pt/v2/invoices/getAll/',
|
|
params={'access_token': token}, # token na query string
|
|
data={'company_id': '69473', 'qty': '50'} # dados no body
|
|
)
|
|
```
|
|
|
|
### Exemplo INCORRECTO (causa 403 Forbidden)
|
|
|
|
```python
|
|
# ERRADO - token no body causa 403!
|
|
r = requests.post('https://api.moloni.pt/v2/invoices/getAll/',
|
|
data={'company_id': '69473', 'access_token': token, 'qty': '50'}
|
|
)
|
|
```
|
|
|
|
## Endpoints Case-Sensitive
|
|
|
|
| Correcto (camelCase) | ERRADO (lowercase) |
|
|
|---------------------|---------------------|
|
|
| `creditNotes/` | `creditnotes/` |
|
|
| `invoiceReceipts/` | `invoicereceipts/` |
|
|
| `documentSets/` | `documentsets/` |
|
|
| `paymentMethods/` | `paymentmethods/` |
|
|
| `simplifiedInvoices/` | `simplifiedinvoices/` |
|
|
| `debitNotes/` | `debitnotes/` |
|
|
| `billsOfLading/` | `billsoflading/` |
|
|
| `deliveryNotes/` | `deliverynotes/` |
|
|
| `proFormaInvoices/` | `proformainvoices/` |
|
|
|
|
Endpoints simples (lowercase OK): `invoices/`, `receipts/`, `customers/`, `products/`, `taxes/`
|
|
|
|
Todos os endpoints precisam de trailing slash: `/v2/invoices/getAll/`
|
|
|
|
## Arrays Aninhados (Form-Encoded)
|
|
|
|
### Formato Correcto
|
|
|
|
```python
|
|
data = {
|
|
'company_id': '69473',
|
|
'associated_documents[0][associated_id]': '595002190',
|
|
'associated_documents[0][value]': '2361.60',
|
|
'payments[0][payment_method_id]': '400878',
|
|
'payments[0][date]': '2026-02-05',
|
|
'payments[0][value]': '2361.60',
|
|
}
|
|
```
|
|
|
|
### Multiplos Items
|
|
|
|
```python
|
|
data = {
|
|
'products[0][product_id]': '123',
|
|
'products[0][qty]': '2',
|
|
'products[0][price]': '50.00',
|
|
'products[1][product_id]': '456',
|
|
'products[1][qty]': '1',
|
|
'products[1][price]': '100.00',
|
|
}
|
|
```
|
|
|
|
### NUNCA Usar JSON.dumps()
|
|
|
|
```python
|
|
# ERRADO - Moloni nao aceita JSON strings dentro de form data
|
|
data = {
|
|
'associated_documents': json.dumps([{'associated_id': 123, 'value': 50}])
|
|
}
|
|
```
|
|
|
|
## Restricoes de Datas
|
|
|
|
- Moloni tem data minima para criacao de documentos (periodo de comunicacao AT)
|
|
- Actualmente: **>= 2025-10-28**
|
|
- Para documentos com datas antigas, usar a data actual no recibo/documento
|
|
- Erro retornado: `["12 date >= 2025-10-28"]`
|
|
|
|
## Series Documentais
|
|
|
|
| ID | Nome | Uso |
|
|
|----|------|-----|
|
|
| 630300 | D | Serie principal (facturas, recibos, NC) |
|
|
| 118898 | (antiga) | Recibos antigos KCCG |
|
|
|
|
## Metodos de Pagamento
|
|
|
|
| ID | Nome |
|
|
|----|------|
|
|
| 400868 | Numerario |
|
|
| 400873 | Cheque |
|
|
| 400878 | Transferencia Bancaria |
|
|
| 400883 | Multibanco |
|
|
| 1569000 | Paypal |
|
|
|
|
## Endpoints por Tipo de Documento
|
|
|
|
Cada tipo de documento suporta: `count`, `getAll`, `getOne`, `insert`, `update`, `delete`
|
|
|
|
### Facturas (invoices/)
|
|
|
|
```
|
|
POST /v2/invoices/getAll/ - Listar (qty, offset, document_set_id, customer_id, year)
|
|
POST /v2/invoices/getOne/ - Detalhe (document_id OU document_set_id+number)
|
|
POST /v2/invoices/insert/ - Criar
|
|
```
|
|
|
|
### Recibos (receipts/)
|
|
|
|
```
|
|
POST /v2/receipts/getAll/ - Listar
|
|
POST /v2/receipts/getOne/ - Detalhe
|
|
POST /v2/receipts/insert/ - Criar (requer: date, document_set_id, customer_id, net_value, associated_documents, payments)
|
|
```
|
|
|
|
**Insert fields:**
|
|
- `company_id` (int, required)
|
|
- `date` (YYYY-MM-DD, required)
|
|
- `document_set_id` (int, required)
|
|
- `customer_id` (int, required)
|
|
- `net_value` (float, required) - valor total do recibo
|
|
- `associated_documents[]` - array com `associated_id` e `value`
|
|
- `payments[]` - array com `payment_method_id`, `date`, `value`
|
|
- `status` (0=rascunho, 1=fechado)
|
|
- `notes` (string, opcional)
|
|
|
|
### Notas de Credito (creditNotes/)
|
|
|
|
```
|
|
POST /v2/creditNotes/getAll/
|
|
POST /v2/creditNotes/getOne/
|
|
POST /v2/creditNotes/insert/
|
|
```
|
|
|
|
### Clientes (customers/)
|
|
|
|
```
|
|
POST /v2/customers/getAll/
|
|
POST /v2/customers/getOne/
|
|
POST /v2/customers/getBySearch/
|
|
POST /v2/customers/getByVat/
|
|
```
|
|
|
|
### Produtos (products/)
|
|
|
|
```
|
|
POST /v2/products/getAll/
|
|
POST /v2/products/getBySearch/
|
|
POST /v2/products/getByReference/
|
|
```
|
|
|
|
## Codigos de Erro Comuns
|
|
|
|
| Codigo | Significado |
|
|
|--------|-------------|
|
|
| 200 + `{"valid": 1}` | Sucesso |
|
|
| 200 + `["12 date >= ..."]` | Data anterior ao periodo AT |
|
|
| 200 + `["10 associated_id"]` | Documento associado invalido ou ja reconciliado |
|
|
| 200 + `["2 value 0 null"]` | Valor invalido ou em falta |
|
|
| 401 | Token expirado ou invalido |
|
|
| 403 | App sem permissoes (access_token no body em vez de query string) |
|
|
| 404 | Endpoint nao encontrado (verificar case-sensitivity e trailing slash) |
|
|
|
|
## Campos de Resposta (Documentos)
|
|
|
|
| Campo | Tipo | Descricao |
|
|
|-------|------|-----------|
|
|
| `document_id` | int | ID unico do documento |
|
|
| `number` | int | Numero sequencial na serie |
|
|
| `net_value` | float | **Total COM IVA** (Desk total). Para base sem IVA: net_value / 1.23. ATENCAO: nome enganador, NAO e base! |
|
|
| `reconciled_value` | float | Valor ja reconciliado/pago |
|
|
| `status` | int | 0=rascunho, 1=fechado |
|
|
| `customer_id` | int | ID do cliente Moloni |
|
|
| `document_set_id` | int | ID da serie documental |
|
|
| `associated_documents` | array | Documentos associados (facturas num recibo) |
|
|
| `reverse_associated_documents` | array | Documentos que referenciam este (recibos de uma factura) |
|
|
| `payments` | array | Pagamentos registados |
|
|
| `entity_name` | string | Nome do cliente |
|
|
| `entity_vat` | string | NIF do cliente |
|
|
|
|
## MCP Tools Disponiveis
|
|
|
|
O MCP Moloni expoe todas as operacoes via ferramentas prefixadas `mcp__moloni__moloni_`:
|
|
|
|
```
|
|
mcp__moloni__moloni_documents_invoices_getall
|
|
mcp__moloni__moloni_documents_invoices_getone
|
|
mcp__moloni__moloni_documents_receipts_insert
|
|
mcp__moloni__moloni_documents_credit_notes_getall
|
|
mcp__moloni__moloni_entities_customers_getall
|
|
mcp__moloni__moloni_settings_paymentmethods_getall
|
|
mcp__moloni__moloni_settings_documentsets_getall
|
|
```
|
|
|
|
**Nota:** O MCP server ja coloca o `access_token` na query string automaticamente. Quando usar via MCP, nao e necessario gerir tokens manualmente.
|
|
|
|
## Mapeamento Clientes Moloni-Desk
|
|
|
|
| Moloni customer_id | Nome Moloni | Desk client_id | Nome Desk |
|
|
|-------------------|-------------|----------------|-----------|
|
|
| 75731733 | Missao Pertinente | 10 | MIP |
|
|
| 84748539 | KCCG - Karate Clube de Gaia | 2 | KCG |
|
|
| 90214681 | IgnitionVortex | 14 | IGV |
|
|
| 90360913 | Prestigebrokers | 176 | Prestigebrokers |
|
|
| 90861853 | Cristina Pinto Santos Lda | 17 | SNT Sintricare |
|
|
| 96914420 | Vasco Miguel Neves, Unipessoal | 21 | Solar FV |
|
|
| 97615615 | TECIRRIGATION | 22 | TECIRRIGATION |
|
|
| 98881975 | Miguel Carril | 23 | MCR |
|
|
| 99321870 | Espiral Senior | 24 | Espiral Senior |
|
|
| 99581273 | Alegria Todo o Dia | 25 | Alegria Todo o Dia |
|
|
| 100711528 | ROSSANA FERREIRA | 26 | Family Clinic |
|
|
| 105780051 | AQUISEVENDE | 28 | AQUISEVENDE |
|
|
| 128784439 | Carstuff Artigos Para Carrocaria | 139 | CTF Carstuff |
|
|
|
|
## Sincronizacao Desk-Moloni (Estado 2026-02-05)
|
|
|
|
| Tipo | Total Serie D | Sincronizados |
|
|
|------|--------------|---------------|
|
|
| Facturas | 107 | 107 importadas no Desk |
|
|
| Notas de Credito | 3 | 3 importadas no Desk |
|
|
| Recibos | 112 | 91 existentes + 21 criados |
|
|
| Pagamentos | 113 | 110 serie D + 3 serie 118898 |
|
|
| PDFs | 220 | 107 FT + 110 RC + 3 NC (330 registos: invoice+customer) |
|
|
|
|
Status facturas:
|
|
- Paid: 98 | Partially Paid: 2 (D/36, D/84) | Unpaid: 3 (D/98, D/105, D/106)
|
|
- Cancelled: 2 (D/56, D/88) | Draft: 2 (D/18, D/66)
|
|
|
|
Excluidas da sincronizacao:
|
|
- FT D/8, D/56, D/88 - anuladas por notas de credito
|
|
- FT D/98, D/105, D/106 - nao cobradas
|
|
- FT D/18, D/66 - rascunhos
|
|
- FT D/3, D/4, D/5 - recibos na serie 118898 (nao D)
|