Saltar para o conteúdo

API e integrações (CRM, Make, n8n)

Liga o teu CRM ou o teu ERP ao Sattotal através de chaves de API: sincroniza clientes e fornecedores de forma automática e segura

A API do Sattotal permite que outro programa — o teu CRM, o teu ERP, o Make, o n8n, o Zapier ou um script teu — leia e crie clientes e fornecedores na tua organização sem que ninguém tenha de importar um CSV à mão. É controlada por chaves de API que o administrador cria em Definições → API, cada uma com o seu nome e com permissões por recurso, e que podem ser revogadas a qualquer momento. Aqui tens o que faz, como criar a chave, como chamar a API e como montar uma sincronização com o Make passo a passo.

Liga o teu CRM e as tuas automatizações

Qualquer ferramenta capaz de fazer um pedido HTTP (Make, n8n, Zapier, o teu próprio CRM ou ERP) pode ler, criar e atualizar clientes e fornecedores.

Chaves com nome e permissões

Uma chave por integração e, dentro de cada chave, uma permissão por recurso: podes dar leitura de fornecedores sem dar escrita de clientes. Até 10 chaves ativas por organização.

Sincronização incremental

Com o parâmetro actualizadoDesde só se vão buscar os clientes ou fornecedores que mudaram desde a última passagem: ideal para um cenário que corre de poucos em poucos minutos.

Segura por conceção

A chave é mostrada uma única vez e guardada cifrada de forma irreversível. Cada chave só acede aos dados da sua organização e é revogada de imediato.

Quem a pode usar

As chaves são criadas e revogadas pelos administradores da organização. A API está incluída nos planos pagos (Basic, Pro e Enterprise) e durante o período de experiência; no plano gratuito o ecrã mostra um cadeado com a opção de mudar de plano. Uma chave atua sempre em nome da organização, não de uma pessoa: não herda as permissões de nenhum técnico nem aparece como utilizador na equipa.

Como criar uma chave

1

Entra em Definições → API

No menu lateral, Definições, cartão «API». Vês a lista de chaves da tua organização (ativas e revogadas) e um cartão «Como ligar» com o URL base e um exemplo.

2

Carrega em «Nova chave»

Dá-lhe um nome que identifique a integração («CRM da loja», «Make», «n8n»). Assim, se um dia tiveres de a revogar, sabes qual é.

3

Escolhe as permissões

Marca os recursos de que a integração precise — Clientes, Fornecedores ou ambos — e, para cada um, escolhe «Apenas leitura» (consultar) ou «Leitura e escrita» (consultar, criar, atualizar e arquivar). Um recurso por marcar é um recurso ao qual a chave não chega. Escolhe o mínimo de que precise.

4

Copia a chave e guarda-a na tua ferramenta

A chave completa (começa por sat_) é mostrada uma única vez. Copia-a com o botão e cola-a no Make, no n8n ou no teu CRM. Se a perderes não há forma de a recuperar: revoga-se e cria-se outra.

Definições → API: lista de chaves e chave acabada de criar

CRM Make

sat_Ab3k…x9Zq

Revogar

n8n

sat_Qm7t…p2Lk

Revogada

Chave criada

sat_Ab3k9Zq2Xv8Lp1Mn4Rt7Wy0Cd5Fg6Hj3Kl8Sx9ZqCopiar

Esta é a única vez que vais ver a chave completa. Se a perderes, revoga-a e cria outra.

Permissões de uma chave

Apenas leitura

Pode listar e consultar esse recurso. Qualquer tentativa de criar, alterar ou arquivar recebe um erro 403 com o código PERMISO_DENEGADO e a permissão que lhe falta.

Leitura e escrita

Além de consultar, pode criar, atualizar e arquivar nesse recurso. É a permissão de que uma sincronização bidirecional precisa.

As permissões são por recurso

As permissões são por recurso, e isso já se notou: ao acrescentar os fornecedores, as chaves que existiam — todas de clientes — NÃO ganharam acesso a eles. Foi preciso marcá-lo. O mesmo valerá para qualquer recurso acrescentado depois: uma integração nunca vê mais do que aquilo que lhe concedeste.

Como autenticar

Envia a chave em cada pedido, de servidor para servidor, no cabeçalho Authorization: Bearer sat_…. Se a tua ferramenta não permitir cabeçalhos de autorização, também é aceite no cabeçalho x-api-key. O URL base é o do teu Sattotal seguido de /api/v1 (está pronto a copiar no ecrã de Definições → API).

GET /api/v1/me
Authorization: Bearer sat_Ab3k9…x9Zq

A API não tem CORS de propósito: foi pensada para servidores e ferramentas de automatização, não para páginas web nem apps que corram no navegador dos teus clientes. Uma chave nunca deve chegar a um navegador.

O que se pode fazer (endpoints)

Todas as respostas têm a forma success + data (e pagination nas listagens). Um cliente podes pedi-lo pelo id ou pelo código (CLI-0007); um fornecedor, só pelo id.

MétodoRotaO que fazPermissão
GET/meDevolve a tua organização e a chave com que estás a chamar. Usa-o para «testar a ligação» no Make ou no n8n.Qualquer
GET/clientesLista paginada de clientes. Filtros: busqueda, tipo, activo e actualizadoDesde. Sem activo devolve também os arquivados.Leitura
POST/clientesCria um cliente com as mesmas regras do formulário (identificador fiscal segundo o teu país, sem duplicados de identificador fiscal nem de email).Escrita
GET/clientes/{id}Devolve um cliente por id ou por código.Leitura
PATCH/clientes/{id}Atualiza apenas os campos enviados. PUT é aceite como sinónimo.Escrita
DELETE/clientes/{id}Arquiva o cliente (activo = false). Não apaga nada e pode repetir-se sem erro.Escrita
GET/proveedoresLista paginada de fornecedores. Filtros: busqueda, activo, tipoProveedor, codigo e actualizadoDesde. Sem activo devolve também os arquivados.Leitura
POST/proveedoresCria um fornecedor. Só o nome é obrigatório. Se já houver um com o mesmo identificador fiscal ou o mesmo nome, responde 409 com o id do existente.Escrita
GET/proveedores/{id}Devolve um fornecedor pelo seu id. Aqui o código NÃO serve: vê o aviso mais abaixo.Leitura
PATCH/proveedores/{id}Atualiza apenas os campos enviados. A lista de contactos é substituída por inteiro. PUT é aceite como sinónimo.Escrita
DELETE/proveedores/{id}Arquiva o fornecedor (activo = false). Não apaga nada e pode repetir-se sem erro.Escrita
GET/reparacionesLista paginada de fichas, da entrada mais recente para a mais antiga. Filtros: cliente, estado, entradaDesde, entradaHasta e actualizadoDesde.Leitura
GET/reparaciones/{id}Devolve uma ficha pelo id ou pelo número da ficha.Leitura
GET/clientes/{id}/reparacionesAs fichas de um cliente (pelo id ou código), com os mesmos filtros.Leitura
GET/clientes/{id}/resumenResumo da atividade do cliente: quantas fichas tem (no total, abertas e por estado), quanto lhe foi orçamentado e quando veio pela última vez.Leitura

Campos do cliente

Os campos são os mesmos da ficha do cliente: nombre e tipo (particular ou empresa) são obrigatórios; nif_cif, apellidos, razonSocial, email, telefono, telefonoSecundario, direccion (calle, numero, piso, codigoPostal, localidad, provincia, pais) e notas são opcionais. O identificador fiscal é guardado em maiúsculas e o email em minúsculas. Na resposta todas as chaves estão sempre presentes, com null quando não há valor, para que o mapeamento de campos na tua ferramenta não se parta. Atenção ao nome: nombre é o nome próprio (ou a designação comercial, se for uma empresa) e o apelido vai à parte, em apellidos, no plural.

Campos que a API não reconhece

Se o corpo trouxer uma chave que não existe (por exemplo firstName em vez de nombre, ou apellido no singular em vez de apellidos), o pedido não é recusado, mas esse dado não é guardado. Para não passar despercebido, a resposta ao criar e editar clientes inclui avisos.camposIgnorados com a lista dessas chaves; as da morada levam o caminho, como direccion.ciudad. Se aparecer, reveja o mapeamento de campos da sua integração. Os campos que a própria API devolve (id, codigo, createdAt…) não geram aviso, por isso pode ler um cliente, alterá-lo e devolvê-lo completo.

POST /api/v1/clientes
{ "firstName": "Daniel", "nombre": "Florea", "tipo": "particular" }

201 Created
{
  "success": true,
  "data": { "nombre": "Florea", "apellidos": null, … },
  "avisos": { "camposIgnorados": ["firstName"] }
}

Exemplo: criar um cliente

Pedido

POST /api/v1/clientes
Authorization: Bearer sat_Ab3k9…x9Zq
Content-Type: application/json

{
  "nombre": "Daniel",
  "apellidos": "Florea",
  "tipo": "empresa",
  "razonSocial": "Assista Tech SRL",
  "nif_cif": "RO12345678",
  "codigoPersonalizado": "801",
  "email": "daniel@example.com",
  "telefono": "+40 700 000 000",
  "direccion": { "localidad": "București", "pais": "RO" }
}

Resposta (201)

{
  "success": true,
  "data": {
    "id": "64b0…0001",
    "codigo": "CLI-0042",
    "codigoPersonalizado": "801",
    "codigoVisible": "801",
    "tipo": "empresa",
    "nombre": "Daniel",
    "apellidos": "Florea",
    "razonSocial": "Assista Tech SRL",
    "nif_cif": "RO12345678",
    "email": "daniel@example.com",
    "activo": true,
    "createdAt": "2026-09-18T10:00:00.000Z",
    "updatedAt": "2026-09-18T10:00:00.000Z"
  }
}

Fornecedores

Além dos clientes, a API expõe o catálogo de fornecedores: os mesmos cinco endpoints, os mesmos códigos de erro e a mesma sincronização incremental. É apenas o catálogo: as compras e as faturas de fornecedor ficam onde já estão, no teu ERP ou no Sattotal.

Campos do fornecedor

Só nombre é obrigatório. Opcionais: codigo, cif, email, telefono, telefonoSecundario, web, direccion (numa única linha, não é um objeto como em clientes), ciudad, provincia, codigoPostal, pais, contactos, tipoProveedor (general, producto, servicio, logistica ou otro), formaPago, plazoPago (em dias; 0 é a pronto pagamento), cuentaCliente e notas. Cada contacto leva nombre —obrigatório—, cargo, telefono, email e notas; os contactos não têm identificador próprio.

Como se atualizam os contactos

A lista que envias SUBSTITUI a que lá estava. Se enviares uma lista vazia, apagam-se todos os contactos; se não enviares a chave (ou enviares null), ficam como estavam. É isso que te permite ler um fornecedor, alterar-lhe um campo e devolvê-lo inteiro sem efeitos estranhos.

Pedido

POST /api/v1/proveedores
Authorization: Bearer sat_Ab3k9…x9Zq
Content-Type: application/json

{
  "nombre": "Distribuciones Norte",
  "cif": "B12345678",
  "tipoProveedor": "producto",
  "plazoPago": 30,
  "cuentaCliente": "C-4471",
  "contactos": [
    { "nombre": "Ana Ruiz", "cargo": "Ventas", "email": "ana@norte.es" }
  ]
}

Resposta (201)

{
  "success": true,
  "data": {
    "id": "64b0…0009",
    "codigo": "PROV-004",
    "nombre": "Distribuciones Norte",
    "cif": "B12345678",
    "tipoProveedor": "producto",
    "plazoPago": 30,
    "cuentaCliente": "C-4471",
    "contactos": [
      { "nombre": "Ana Ruiz", "cargo": "Ventas",
        "telefono": null, "email": "ana@norte.es", "notas": null }
    ],
    "excluidoRecargoEquivalencia": false,
    "activo": true,
    "createdAt": "2026-09-19T08:00:00.000Z",
    "updatedAt": "2026-09-19T08:00:00.000Z"
  }
}

Os dados bancários não saem pela API

O IBAN e as contas bancárias do fornecedor não são devolvidos nem aceites, de propósito: se uma chave se escapasse, não serviria para a fraude de troca de conta, que é a mais comum com fornecedores. Sai sim cuentaCliente, que é o TEU número de cliente nesse fornecedor e com o qual um ERP concilia as compras.

A sobretaxa de equivalência é só de leitura

O campo excluidoRecargoEquivalencia é devolvido e podes reenviá-lo com o mesmo valor (para poderes devolver o objeto inteiro), mas alterá-lo por API responde 400: decide se as tuas compras a esse fornecedor levam a sobretaxa, ou seja, mexe na base tributável das tuas faturas de compra. Altera-se na ficha do fornecedor. Fora de Espanha não tem qualquer efeito.

O código de fornecedor não localiza

Ao contrário do de cliente, o código do fornecedor (PROV-004) não é único: pode repetir-se mesmo dentro da tua própria oficina. Por isso GET /proveedores/{id} só aceita o id. Se o teu ERP só guarda o código, usa o filtro da listagem: GET /proveedores?codigo=PROV-004, que devolve todos os que correspondam e decides tu.

Fichas de reparação (só leitura)

A API também permite consultar as fichas de reparação: número da ficha, estado, datas, o equipamento (tipo, marca, modelo, número de série, IMEI) e o orçamento. É só de leitura: as fichas continuam a ser criadas e a mudar de estado no Sattotal, onde se assinam o comprovativo de entrada e a entrega. A chave precisa do recurso Reparações marcado; as chaves de clientes ou fornecedores não lhes chegam.

Campos da ficha

Cada ficha traz numeroFicha, estado, prioridad, ubicacion, averiaDeclarada, diagnostico, as datas do ciclo (entrada, início e fim do diagnóstico e da reparação, aviso ao cliente, entrega e ultimoCambioEstado, quando passou ao estado atual), um resumo do cliente (id, codigo, codigoVisible, nombre, apellidos, razonSocial), o equipamento (id, codigo, tipo, marca, modelo, numeroSerie, imei, color), o orçamento (numero, total, estado, fechaEnvio e fechaRespuesta, ou null se não existir), o técnico atribuído (só o nome) e plazoEntregaEstimado, o prazo indicado ao cliente no comprovativo de entrada. As notas internas, as assinaturas, as fotografias, os documentos e as palavras-passe do equipamento nunca são devolvidos.

Pedido

GET /api/v1/clientes/CLI-0042/reparaciones?estado=reparado
Authorization: Bearer sat_Ab3k9…x9Zq

Resposta (201)

{
  "success": true,
  "data": [{
    "id": "64b0…0042",
    "numeroFicha": "ORD-2026-0042",
    "estado": "reparado",
    "prioridad": "normal",
    "averiaDeclarada": "No carga",
    "diagnostico": "Conector de carga dañado",
    "fechas": {
      "entrada": "2026-09-20T09:00:00.000Z",
      "finReparacion": "2026-09-22T17:30:00.000Z",
      "entrega": null
    },
    "cliente": { "id": "64b0…0001", "codigoVisible": "801", "nombre": "Daniel" },
    "dispositivo": {
      "tipo": "movil", "marca": "Apple", "modelo": "iPhone 13",
      "numeroSerie": "F2LXX0000", "imei": "356789012345678"
    },
    "presupuesto": { "numero": "PRES-2026-0010", "total": 89.9, "estado": "aprobado" },
    "tecnico": { "nombre": "Andrei Popescu" },
    "plazoEntregaEstimado": "3 días laborables"
  }],
  "pagination": { "total": 1, "page": 1, "limit": 25, "totalPages": 1 }
}

Encontrar o cliente pelo número que está a ligar

Se o teu CRM ou a tua central telefónica abre a ficha do cliente quando entra uma chamada, usa GET /clientes?telefono=<número>. Pesquisa no telefone principal e no secundário e ignora a forma como o número está escrito: espaços, hífenes e o indicativo internacional do teu país (+351 ou 00351). Assim, «912 345 678» encontra um cliente guardado como «+351 912-345-678». São precisos pelo menos 6 dígitos.

Resumo do cliente para o teu CRM

GET /clientes/{id}/resumen devolve numa só chamada o que um CRM costuma mostrar na ficha do cliente: totalReparaciones, reparacionesAbiertas (o equipamento continua na oficina), porEstado, totalPresupuestado e totalPresupuestosAprobados (na moeda da oficina, que vem em moneda), primeraReparacion, ultimaReparacion e ultimaActividad (a última alteração em qualquer uma das suas fichas). Precisa do recurso Reparações, tal como as fichas.

Pedido

GET /api/v1/clientes?telefono=0722 123 456
→ { "data": [{ "id": "64b0…0001", "codigoVisible": "801", "telefono": "+40 722 123 456", … }] }

GET /api/v1/clientes/801/resumen
{
  "success": true,
  "data": {
    "cliente": { "id": "64b0…0001", "codigoVisible": "801" },
    "moneda": "RON",
    "totalReparaciones": 7,
    "reparacionesAbiertas": 1,
    "porEstado": { "entregado": 6, "en_reparacion": 1 },
    "totalPresupuestosAprobados": 1240.5,
    "ultimaReparacion": "2026-10-02T09:15:00.000Z",
    "ultimaActividad": "2026-10-06T16:40:00.000Z",
    …
  }
}

Sincronizar só o que mudou

Não é preciso ir buscar tudo em cada passagem. Guarda na tua ferramenta a data e a hora da última execução e pede apenas os clientes ou fornecedores modificados desde então com o parâmetro actualizadoDesde. A resposta vem ordenada por data de modificação ascendente e com um desempate estável, por isso podes paginá-la sem saltar registos. Os arquivados também aparecem (com activo = false), para que o teu CRM possa refletir o arquivo.

GET /api/v1/clientes?actualizadoDesde=2026-09-18T10:00:00Z&limit=100&page=1
Authorization: Bearer sat_Ab3k9…x9Zq
1

Primeira passagem

Percorre GET /clientes com limit=100 e page=1, 2, 3… até totalPages se esgotar. Guarda a hora de início.

2

Passagens seguintes

Pede GET /clientes?actualizadoDesde=<hora guardada> e processa só o que chegar. Volta a guardar a hora de início desta passagem.

3

Associa, não dupliques

Guarda o id do Sattotal junto ao registo do teu CRM. Se ao criar receberes um 409 DUPLICADO, a resposta traz existenteId: associa esse em vez de criares outro.

Paginação e pesquisa

As listagens aceitam page (a partir de 1) e limit (25 por omissão, 100 no máximo; se pedires mais, é cortado para 100). O campo busqueda pesquisa em nome, apelidos, razão social, identificador fiscal, email, código e telefone.

Códigos de erro e o que fazer

Todas as respostas de erro trazem success: false, um texto orientativo e um code estável pensado para decidir por programa. Estes são os que podes receber:

NO_AUTORIZADO

Falta a chave, tem um formato que não é o nosso ou não existe. Verifica o cabeçalho Authorization.

CLAVE_REVOCADA

A chave era válida, mas um administrador revogou-a. Cria uma nova em Definições → API e atualiza-a na tua ferramenta.

PLAN_REQUERIDO

A organização está no plano gratuito. A API volta a funcionar ao mudares para um plano pago.

PERMISO_DENEGADO

A chave não tem a permissão necessária para essa operação. A resposta indica em ambitoRequerido qual falta: cria uma chave com essa permissão.

NO_ENCONTRADO

Não há nenhum cliente nem fornecedor com esse id na tua organização. Os de outras organizações nunca são visíveis, e não se distingue «não existe» de «não é teu».

DUPLICADO

Já existe um registo com esse dado: identificador fiscal ou email em clientes; identificador fiscal, nome ou código em fornecedores. A resposta traz campo e existenteId para que o possas associar em vez de criar outro.

VALIDACION

Algum campo não passa a validação (ou o JSON está mal formado). Em details vai o campo e o motivo, tal como no formulário.

IDENTIFICADOR_FISCAL_REQUERIDO

Esse cliente precisa de identificador fiscal: no teu país é obrigatório para o tipo de cliente enviado (por exemplo, sempre para empresas).

RATE_LIMIT

Pedidos a mais. Espera os segundos indicados no cabeçalho Retry-After e tenta outra vez.

API_DESACTIVADA

A API está temporariamente desativada para manutenção. Tenta mais tarde.

Limites

120 pedidos por minuto e por chave (de sobra para uma sincronização periódica; trava um ciclo acidental). 10 chaves ativas por organização. As listagens devolvem no máximo 100 registos por página. Se a organização estiver no plano gratuito com a quota mensal esgotada, a criação de clientes é cortada tal como na aplicação.

Passo a passo: sincronizar clientes com o Make

Um cenário típico: de 15 em 15 minutos, trazer para o teu CRM os clientes e fornecedores novos ou modificados no Sattotal. No n8n é equivalente com o nó HTTP Request e um nó Schedule.

1

Cria a chave no Sattotal

Definições → API → Nova chave, permissão «Apenas leitura» se só vais ler, «Leitura e escrita» se também vais criar clientes a partir do CRM. Copia a chave.

2

Módulo HTTP «Make a request»

URL: o teu URL base + /clientes. Método GET. Cabeçalho Authorization com o valor Bearer e a tua chave. Marca «Parse response» para trabalhar com o JSON.

3

Testa a ligação

Antes de mais, executa uma vez um pedido a /me: se devolver a tua organização e o nome da chave, a autenticação está bem.

4

Acrescenta o filtro incremental

Guarda a data da última execução num Data store ou numa variável e passa-a como actualizadoDesde no URL. Agenda o cenário de 15 em 15 minutos.

5

Mapeia os campos para o teu CRM

Itera data[] e mapeia id, codigo, nombre, apellidos, email, telefono, nif_cif e direccion. Guarda o id do Sattotal no teu CRM para atualizar em vez de duplicar.

Para criar clientes a partir do CRM, outro módulo HTTP com método POST para /clientes e o corpo JSON do cliente. Se receberes 409, usa existenteId para associar.

Boas práticas de segurança

Uma chave por integração

Assim podes revogar uma sem partir as outras, e na lista vês quando cada uma foi usada pela última vez.

Nunca no navegador nem num repositório público

Guarda-a no cofre de credenciais da tua ferramenta (ligações do Make, credenciais do n8n, variáveis de ambiente). Se a puseres num repositório ou num site, considera-a comprometida.

Se for comprometida, revoga e cria outra

A revogação é imediata: a chave antiga começa a receber 401 CLAVE_REVOCADA. Atualiza a nova na tua ferramenta e está feito.

Especificação API

A referência técnica completa (rotas, parâmetros, esquemas e códigos de erro) está publicada em formato aberto em /api/v1/openapi.json, sem necessidade de chave. Por omissão sai em espanhol; acrescenta ?lang= com o teu idioma para a teres traduzida (por exemplo /api/v1/openapi.json?lang=pt-PT, ?lang=en ou ?lang=ro). Podes importá-la no Postman, Insomnia, Make ou n8n para teres todas as chamadas preparadas.

Perguntas frequentes

Perdi a chave, posso voltar a vê-la?

Não. Só é mostrada ao criá-la e depois é guardada de forma irreversível. Revoga-a em Definições → API e cria outra.

Há webhooks para o Sattotal avisar o meu CRM quando algo muda?

Ainda não. A forma recomendada é consultar periodicamente com o parâmetro actualizadoDesde, que só devolve o que mudou.

Que dados expõe a API?

Clientes e fornecedores: listar, criar, consultar, atualizar e arquivar. As permissões são por recurso, por isso uma chave criada antes de existirem os fornecedores não lhes acede enquanto um administrador não a marcar. Além disso, as fichas de reparação só de leitura (estado, datas, equipamento e orçamento), com permissão própria.

Posso apagar um cliente pela API?

Não, só arquivá-lo (activo = false), tal como na aplicação. Vale tanto para clientes como para fornecedores. Um registo arquivado continua a aparecer na sincronização para que o teu CRM o reflita.

A API está no plano gratuito?

Não. Está incluída no Basic, Pro e Enterprise e durante o período de experiência. No plano gratuito podes continuar a ver e a revogar as chaves que criaste.

Só chega o apelido do cliente. Porque é que o nome próprio não fica guardado?

Quase sempre é o mapeamento de campos: o nome próprio vai em nombre e o apelido em apellidos. Se a sua ferramenta envia o nome com outra chave (firstName, name, apellido…), a API descarta-a e indica-o em avisos.camposIgnorados na resposta. Corrija o mapeamento e volte a enviar o cliente com um PATCH.

Posso encontrar o cliente pelo número que me está a ligar?

Sim. Pede GET /api/v1/clientes?telefono= com o número tal como te chega: não importa se traz indicativo internacional, espaços ou hífenes, e também pesquisa no telefone secundário. Com o id dele podes depois pedir as fichas (/clientes/{id}/reparaciones) e o resumo (/clientes/{id}/resumen).

Queres experimentar tu mesmo?

Experimenta a Sattotal grátis com dados de exemplo, sem cartão de crédito.