Introdução
Esta API permite criar documentos de vendas / compras no XD ERP.
✅ Funcionalidades:
- Criação automática de clientes (com NIF)
- Suporte a "Consumidor Final" (sem NIF)
- Idempotência através de
externalRefúnico - Validação completa de dados antes do processamento
- Suporte a múltiplas linhas de produtos por documento
Endpoint Principal
POST
/api/v1/orders
Content-Type: application/json
Autenticação: API Key via header X-API-Key
Como Obter API Key
A API Key é fornecida pela equipa Brainit após configuração inicial. Entre em contacto através de:
- Email: webmaster@brainit.pt
Campos do Documento
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
docTypeId | integer | Obrigatório | ID do tipo de documento (ver tabela abaixo) |
serieId | integer | Obrigatório | ID da série do documento. Solicitar à equipa Brainit o ID correto. |
userId | integer | Obrigatório | ID do utilizador/vendedor no XD. Fornecido pela equipa Brainit. |
paymentType | integer | Obrigatório | ID do tipo de pagamento (1=Numerário, 2=MB, 3=Cartão, etc.) |
externalRef | string | Opcional | Referência externa ÚNICA do pedido. Usado para idempotência. Máximo: 50 caracteres |
observations | string | Opcional | Observações do documento (aparece no PDF). Máximo: 4000 caracteres |
dueDate | datetime | Opcional | Data de vencimento (ISO 8601: YYYY-MM-DDTHH:mm:ss) |
integrationTag | string | Opcional | Tag de identificação da integração (ex: "WOOCOMMERCE", "AUTO21"). Necessário para criação automática de clientes/artigos. |
⚠️ Importante sobre externalRef:
- Deve ser único para cada pedido
- Se enviar a mesma
externalRefduas vezes, o sistema retorna 409 Conflict - Recomendado usar:
[SISTEMA]-[ID](ex: "WC-12345", "AUTO21-5678")
Objeto Cliente
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
keyId | string | Opcional | KeyId do cliente existente no XD. Se fornecido, ignora todos os outros campos. |
vat | string | Opcional | Se vazio/null: usa "Consumidor Final" (KeyId=0) Se preenchido: procura cliente ou cria novo (com integrationTag) |
name | string | Obrigatório | Nome do cliente (aparece no documento PDF) |
contactEmail | string | Opcional | Email do cliente |
phone | string | Opcional | Telefone do cliente |
address | string | Opcional | Morada completa |
city | string | Opcional | Cidade |
postalCode | string | Opcional | Código postal (formato: 4700-123) |
country | string | Opcional | Código do país (ISO 2 letras, padrão: PT) |
Consumidor Final (sem NIF):
- Usa o cliente especial "Consumidor Final" (KeyId=0)
- Preserva os dados fornecidos (nome, email, morada) no documento
- Não cria um novo cliente na base de dados
Linhas do Documento
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
reference | string | Obrigatório | Referência/KeyId do artigo no XD |
description | string | Opcional | Descrição personalizada (substitui a descrição padrão do artigo) |
quantity | decimal | Obrigatório | Quantidade (deve ser > 0) |
unitPrice | decimal | Obrigatório | Preço unitário (deve ser >= 0) |
taxId | integer | Opcional | ID da taxa de IVA. Se omitido, usa a taxa padrão do artigo (Tax1) |
discountPercentage | decimal | Opcional | Percentagem de desconto (0-100) |
Exemplos de Utilização
Cliente COM NIF - Cria/Atualiza Cliente
{
"cliente": {
"vat": "PT123456789",
"name": "João Silva",
"contactEmail": "joao@example.com",
"phone": "912345678",
"address": "Rua das Flores, 123",
"city": "Braga",
"postalCode": "4700-123",
"country": "PT"
},
"lines": [
{
"reference": "CAR001",
"description": "Mercedes Classe A 180d",
"quantity": 1,
"unitPrice": 28500.00,
"taxId": 1
}
],
"document": {
"docTypeId": 64,
"serieId": 1,
"userId": 1,
"paymentType": 1,
"observations": "Veículo com garantia de 2 anos.",
"dueDate": "2026-12-31T23:59:59"
},
"externalRef": "AUTO21-12345",
"integrationTag": "AUTO21"
}
Consumidor Final - SEM NIF
{
"cliente": {
"vat": null,
"name": "Maria Costa",
"contactEmail": "maria@example.com",
"phone": "933444555",
"address": "Av. Central, 45",
"city": "Porto",
"postalCode": "4000-123"
},
"lines": [
{
"reference": "PROD001",
"quantity": 2,
"unitPrice": 15.50
}
],
"document": {
"docTypeId": 12,
"serieId": 1,
"userId": 1,
"paymentType": 1
},
"externalRef": "WC-67890"
}
Cliente Existente - Usar KeyId
{
"cliente": {
"keyId": "CLI001"
},
"lines": [
{
"reference": "SERV001",
"description": "Revisão Completa",
"quantity": 1,
"unitPrice": 120.00,
"taxId": 3
}
],
"document": {
"docTypeId": 1,
"serieId": 1,
"userId": 1,
"paymentType": 2,
"dueDate": "2026-12-31T23:59:59"
},
"externalRef": "SRV-2024-001"
}
Exemplo Mínimo
{
"cliente": {
"name": "Cliente Teste"
},
"lines": [
{
"reference": "PROD001",
"quantity": 1,
"unitPrice": 10.00
}
],
"document": {
"docTypeId": 12,
"serieId": 1,
"userId": 1,
"paymentType": 1
}
}
✅ Respostas da API
Sucesso (HTTP 200)
{
"success": true,
"document": "NE A/1",
"message": "Pedido criado com sucesso",
"clientId": "auto21-integration",
"integrationTag": "AUTO21"
}Documento Duplicado (HTTP 409)
{
"success": false,
"message": "Já existe um documento com a referência 'AUTO21-12345'.",
"errorCode": "DuplicateDocument"
}Erro de Validação (HTTP 400)
{
"success": false,
"message": "Validação falhou",
"errors": [
"Campo 'cliente' é obrigatório",
"Linha 1: quantidade deve ser maior que 0"
]
}Erro de Autenticação (HTTP 401)
{
"error": "unauthorized",
"message": "API Key obrigatória no header X-API-Key"
}Erro Interno (HTTP 500)
{
"success": false,
"error": "Artigo 'PROD999' não existe no XD"
}Códigos de Erro Comuns
| HTTP | Erro | Solução |
|---|---|---|
| 401 | API Key missing / inválida | Verificar se o header X-API-Key está presente e correto |
| 400 | Documento sem linhas | Incluir pelo menos 1 linha no array lines |
| 400 | Campo 'cliente.name' é obrigatório | Preencher o campo name do cliente |
| 400 | Artigo 'XXX' não existe | Verificar se a reference existe no XD |
| 400 | Cliente com VAT 'XXX' não existe | Adicionar integrationTag para permitir criação automática |
| 409 | Documento duplicado | O externalRef já foi usado. Cada documento deve ter referência única. |
| 500 | Erro ao gravar documento | Erro interno. Contactar suporte com o externalRef do pedido |
Tipos de Documento
| ID | Tipo | Descrição | Uso Recomendado |
|---|---|---|---|
| 1 | Fatura | Documento fiscal com IVA | Vendas com exigência de fatura |
| 12 | Nota de Encomenda | Documento pré-venda (não fiscal) | Orçamentos, encomendas pendentes |
| 64 | Encomenda | Encomenda de cliente | Pedidos de produtos/serviços |
| 15 | Fatura Fornecedor | Documento de compra padrão | Compras a fornecedores |
| 65 | Fatura Fornecedor Auto21 | Documento de compra Auto21 | Compras específicas Auto21 |
Nota: Os IDs podem variar conforme a configuração do XD para a sua empresa. A equipa Brainit fornecerá os IDs corretos durante a integração.
Endpoint de Compras
POST
/api/v1/purchases
Content-Type: application/json
Autenticação: API Key via header X-API-Key
Diferenças em relação a Orders:
- O
docTypeIdaceita 15 (Fatura Fornecedor) ou 65 (Fatura Fornecedor Auto21) - O fornecedor é procurado por
keyId,vatoucontactEmail— e criado automaticamente se tiverintegrationTag - Os artigos são procurados por
reference— e criados automaticamente se tiverintegrationTag - O campo raiz é
fornecedorem vez decliente - Documentos duplicados retornam 409 Conflict
Objeto Fornecedor
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
keyId | string | Opcional | KeyId do fornecedor existente no XD. Se fornecido, ignora todos os outros campos. |
vat | string | Opcional | NIF/NIPC do fornecedor. Procura o fornecedor existente. Se não encontrar e tiver integrationTag, cria automaticamente. |
name | string | Opcional* | Nome do fornecedor. Obrigatório apenas na criação automática. |
contactEmail | string | Opcional | Email do fornecedor. Usado também como critério de pesquisa. |
phone | string | Opcional | Telefone do fornecedor |
address | string | Opcional | Morada completa |
city | string | Opcional | Cidade |
postalCode | string | Opcional | Código postal (formato: 4700-123) |
country | string | Opcional | Código do país (ISO 2 letras, padrão: PT) |
Lógica de procura do Fornecedor (por ordem):
- Se
keyIdpreenchido → procura diretamente por KeyId - Se
vatpreenchido → procura por NIF (memória → base de dados) - Se
contactEmailpreenchido → procura por email na base de dados - Se não encontrar + tem
integrationTag→ cria automaticamente com EntityType=1 (Fornecedor) - Se não encontrar + sem
integrationTag→ retorna erro 500
Campos do Documento (Compra)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
docTypeId | integer | Obrigatório | 15 = Fatura Fornecedor | 65 = Fatura Fornecedor Auto21. Qualquer outro valor será rejeitado. |
serieId | integer | Obrigatório | ID da série do documento de compra. Fornecido pela equipa Brainit. |
userId | integer | Obrigatório | ID do utilizador no XD que registará a compra. |
paymentType | integer | Obrigatório | ID do tipo de pagamento (1=Numerário, 2=MB, 3=Cartão, etc.) |
dueDate | datetime | Opcional | Data de vencimento da fatura do fornecedor (ISO 8601: YYYY-MM-DDTHH:mm:ss) |
observations | string | Opcional | Observações internas do documento. Máximo: 4000 caracteres |
externalRef | string | Opcional | Referência externa única (ex: número da fatura do fornecedor). Documentos duplicados retornam 409 Conflict. |
integrationTag | string | Opcional | Tag da integração (ex: "AUTO21"). Necessário para criação automática de fornecedores e artigos. |
Linhas do Documento (Compra)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
reference | string | Obrigatório | KeyId do artigo no XD. Se não existir e tiver integrationTag, é criado automaticamente. |
description | string | Opcional | Descrição personalizada da linha (substitui a descrição padrão do artigo no documento) |
quantity | decimal | Obrigatório | Quantidade (deve ser > 0) |
unitPrice | decimal | Obrigatório | Preço de custo unitário (deve ser >= 0) |
taxId | integer | Opcional | ID da taxa de IVA. Se omitido, usa a taxa padrão do artigo (Tax1) |
Exemplos de Utilização — Purchases
Compra Auto21 — Fornecedor criado automaticamente (docTypeId: 65)
Se o fornecedor não existir no XD, é criado automaticamente graças ao integrationTag. O artigo também é criado se não existir.
{
"fornecedor": {
"name": "AUTO 21 LDA",
"vat": "506776352",
"contactEmail": "auto21@auto21.pt",
"address": "Rua de Portugal",
"postalCode": "4100-020",
"city": "PORTO",
"country": "PT",
"phone": "253999888"
},
"lines": [
{
"reference": "CAR001",
"description": "Renault Coupe 1.5 Blue dCi Limited J17",
"quantity": 1,
"unitPrice": 3922.00,
"taxId": 1
}
],
"document": {
"docTypeId": 65,
"serieId": 1,
"userId": 1,
"paymentType": 7,
"observations": "RENAULT MEGANE – Sedan de 2019. Primeiro registo: Agosto 2019. 4 portas, 5 lugares.",
"dueDate": "2026-03-31T23:59:59"
},
"externalRef": "AUTO21-1262226",
"integrationTag": "AUTO21"
}
Fornecedor por KeyId (docTypeId: 15)
Quando já conhece o KeyId do fornecedor no XD, use apenas esse campo.
{
"fornecedor": {
"keyId": "123"
},
"lines": [
{
"reference": "CAR001",
"description": "Mercedes Classe C180d",
"quantity": 1,
"unitPrice": 7500.00,
"taxId": 2
}
],
"document": {
"docTypeId": 15,
"serieId": 1,
"userId": 1,
"paymentType": 9,
"observations": "Fatura referente a compra de viatura.",
"dueDate": "2026-03-31T23:59:59"
},
"externalRef": "AUTO215-20260101"
}
Resposta de Sucesso (HTTP 200)
{
"success": true,
"document": "VFC 1/8",
"message": "Purchase criada com sucesso",
"clientId": "auto21-integration",
"integrationTag": "AUTO21"
}Documento Duplicado (HTTP 409)
{
"success": false,
"message": "Já existe um documento com a referência 'AUTO21-1262226'.",
"errorCode": "DuplicateDocument"
}Erros Específicos de Compras
DocTypeId inválido (HTTP 400):
{
"success": false,
"message": "DocTypeId '51' inválido para purchases. Valor permitido: (Fatura Fornecedor)."
}Fornecedor não existe sem integrationTag (HTTP 500):
{
"success": false,
"error": "Fornecedor com VAT '506776352' não existe. Para criar automaticamente, defina 'integrationTag'."
}Artigo não existe sem integrationTag (HTTP 500):
{
"success": false,
"error": "Artigo 'CAR999' não existe e criação automática não permitida."
}Códigos de Erro Específicos de Compras
| HTTP | Erro | Solução |
|---|---|---|
| 400 | DocTypeId inválido para purchases | Usar docTypeId: 15 (Fatura Fornecedor) ou docTypeId: 65 (Fatura Fornecedor Auto21) |
| 409 | Documento duplicado | O externalRef já foi usado. Cada compra deve ter referência única. |
| 500 | Fornecedor com VAT 'XXX' não existe | Adicionar integrationTag para criação automática, ou usar keyId existente. |
| 500 | Artigo 'XXX' não existe | Adicionar integrationTag para criação automática, ou verificar a reference. |
| 500 | Erro ao gravar compra | Contactar suporte com o externalRef e timestamp da requisição. |
Configuração Inicial
Dados Fornecidos pela Brainit
- API Key - Chave de autenticação única para sua integração
- userId - ID do utilizador XD que criará os documentos
- serieId - ID da série de documentos a utilizar
- Lista de Artigos - Referências (KeyIds) dos produtos/serviços disponíveis
- Tipos de Documento - IDs dos tipos de documento configurados
- URL Base - Endereço do servidor da API
Segurança:
- Nunca partilhe sua API Key publicamente
- Armazene a API Key de forma segura (variáveis de ambiente, cofres de segredos)
- Use HTTPS em todas as requisições
- Implemente rate limiting no seu lado para evitar sobrecarga
📞 Suporte
- 📧 Email: webmaster@brainit.pt
- 🕐 Horário: Segunda a Sexta, 9h00 - 18h00
Ao contactar o suporte, forneça sempre:
- O valor do campo
externalRefdo pedido problemático - Código de erro HTTP recebido
- Timestamp aproximado da requisição
- Mensagem de erro completa