API e integrações (CRM, Make, n8n)
Conecte seu CRM ou seu ERP ao Sattotal por meio de chaves de API: sincronize clientes e fornecedores de forma automática e segura
A API do Sattotal permite que outro programa — seu CRM, seu ERP, Make, n8n, Zapier ou um script seu — leia e crie clientes e fornecedores na sua organização sem que ninguém precise importar um CSV à mão. Ela é controlada por chaves de API que o administrador cria em Configurações → API, cada uma com nome próprio e com permissões por recurso, e que podem ser revogadas a qualquer momento. Aqui você encontra o que ela faz, como criar a chave, como chamar a API e como montar uma sincronização com o Make passo a passo.
Conecte seu CRM e suas automações
Qualquer ferramenta capaz de fazer uma requisição HTTP (Make, n8n, Zapier, seu 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: você pode 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ó são trazidos os clientes ou fornecedores que mudaram desde a última execução: ideal para um cenário que roda a cada poucos minutos.
Segura por padrão
A chave é mostrada uma única vez e guardada criptografada de forma irreversível. Cada chave só acessa os dados da própria organização e é revogada na hora.
Quem pode usá-la
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 teste; no plano gratuito a tela mostra um cadeado com a opção de mudar de plano. Uma chave sempre age em nome da organização, não de uma pessoa: ela não herda as permissões de nenhum técnico nem aparece como usuário na equipe.
Como criar uma chave
Entre em Configurações → API
No menu lateral, Configurações, cartão «API». Você verá a lista de chaves da sua organização (ativas e revogadas) e um cartão «Como conectar» com a URL base e um exemplo.
Clique em «Nova chave»
Dê a ela um nome que identifique a integração («CRM da loja», «Make», «n8n»). Assim, se um dia precisar revogá-la, você saberá qual é.
Escolha as permissões
Marque os recursos de que a integração precisar — Clientes, Fornecedores ou os dois — e, para cada um, escolha «Somente leitura» (consultar) ou «Leitura e escrita» (consultar, criar, atualizar e arquivar). Um recurso não marcado é um recurso ao qual a chave não chega. Escolha o mínimo necessário.
Copie a chave e guarde na sua ferramenta
A chave completa (começa com sat_) é mostrada uma única vez. Copie com o botão e cole no Make, no n8n ou no seu CRM. Se você a perder, não dá para recuperar: revogue e crie outra.
Configurações → API: lista de chaves e chave recém-criada
CRM Make
sat_Ab3k…x9Zq
n8n
sat_Qm7t…p2Lk
Chave criada
sat_Ab3k9Zq2Xv8Lp1Mn4Rt7Wy0Cd5Fg6Hj3Kl8Sx9ZqCopiarEsta é a única vez que você verá a chave completa. Se perdê-la, revogue e crie outra.
Permissões de uma chave
Somente 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 está faltando.
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á apareceu na prática: ao acrescentar os fornecedores, as chaves que já existiam — todas de clientes — NÃO ganharam acesso a eles. Foi preciso marcar. O mesmo valerá para qualquer recurso acrescentado depois: uma integração nunca vê mais do que você concedeu.
Como se autenticar
Envie a chave em cada requisição, de servidor para servidor, no cabeçalho Authorization: Bearer sat_…. Se a sua ferramenta não permitir cabeçalhos de autorização, ela também é aceita no cabeçalho x-api-key. A URL base é a do seu Sattotal seguida de /api/v1 (ela está pronta para copiar na tela de Configurações → API).
GET /api/v1/me Authorization: Bearer sat_Ab3k9…x9Zq
A API não tem CORS de propósito: ela foi pensada para servidores e ferramentas de automação, não para páginas web nem apps que rodem no navegador dos seus clientes. Uma chave nunca deve chegar a um navegador.
O que dá para fazer (endpoints)
Todas as respostas têm o formato success + data (e pagination nas listagens). Um cliente você pode pedir pelo id ou pelo código (CLI-0007); um fornecedor, só pelo id.
| Método | Rota | O que faz | Permissão |
|---|---|---|---|
| GET | /me | Devolve a sua organização e a chave com a qual você está chamando. Use para «testar a conexão» no Make ou no n8n. | Qualquer |
| GET | /clientes | Lista paginada de clientes. Filtros: busqueda, tipo, activo e actualizadoDesde. Sem activo, devolve também os arquivados. | Leitura |
| POST | /clientes | Cria um cliente com as mesmas regras do formulário (identificador fiscal conforme o seu país, sem duplicar identificador fiscal nem e-mail). | Escrita |
| GET | /clientes/{id} | Devolve um cliente pelo id ou pelo código. | Leitura |
| PATCH | /clientes/{id} | Atualiza somente os campos enviados. PUT é aceito como sinônimo. | Escrita |
| DELETE | /clientes/{id} | Arquiva o cliente (activo = false). Não apaga nada e pode ser repetido sem erro. | Escrita |
| GET | /proveedores | Lista paginada de fornecedores. Filtros: busqueda, activo, tipoProveedor, codigo e actualizadoDesde. Sem activo, devolve também os arquivados. | Leitura |
| POST | /proveedores | Cria um fornecedor. Só o nome é obrigatório. Se já existir 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 id. Aqui o código NÃO serve: veja o aviso mais abaixo. | Leitura |
| PATCH | /proveedores/{id} | Atualiza somente os campos enviados. A lista de contatos é substituída por inteiro. PUT é aceito como sinônimo. | Escrita |
| DELETE | /proveedores/{id} | Arquiva o fornecedor (activo = false). Não apaga nada e pode ser repetido sem erro. | Escrita |
| GET | /reparaciones | Lista paginada de ordens, da entrada mais recente para a mais antiga. Filtros: cliente, estado, entradaDesde, entradaHasta e actualizadoDesde. | Leitura |
| GET | /reparaciones/{id} | Retorna uma ordem pelo id ou pelo número da ordem. | Leitura |
| GET | /clientes/{id}/reparaciones | As ordens de um cliente (pelo id ou código dele), com os mesmos filtros. | Leitura |
| GET | /clientes/{id}/resumen | Resumo da atividade do cliente: quantas ordens ele tem (no total, abertas e por status), quanto já foi orçado para ele 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 é salvo em maiúsculas e o e-mail 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 sua ferramenta não quebre. Atenção ao nome: nombre é o primeiro nome (ou o nome fantasia, se for empresa) e o sobrenome 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), a requisição não é recusada, mas esse dado não é salvo. Para não passar despercebido, a resposta ao criar e editar clientes inclui avisos.camposIgnorados com a lista dessas chaves; as do endereço levam o caminho, como direccion.ciudad. Se aparecer, revise o mapeamento de campos da sua integração. Os campos que a própria API devolve (id, codigo, createdAt…) não geram aviso, então você pode ler um cliente, alterá-lo e enviá-lo de volta inteiro.
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
Requisição
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. É só o catálogo: as compras e as notas fiscais de fornecedor continuam onde já estão, no seu ERP ou no Sattotal.
Campos do fornecedor
Só nombre é obrigatório. Opcionais: codigo, cif, email, telefono, telefonoSecundario, web, direccion (em uma ú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 é à vista), cuentaCliente e notas. Cada contato leva nombre —obrigatório—, cargo, telefono, email e notas; os contatos não têm identificador próprio.
Como os contatos são atualizados
A lista que você envia SUBSTITUI a que havia. Se enviar uma lista vazia, todos os contatos são apagados; se não enviar a chave (ou enviar null), eles ficam como estavam. É o que permite ler um fornecedor, mudar um campo e devolvê-lo inteiro sem efeitos estranhos.
Requisição
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 aceitos, de propósito: se uma chave vazasse, não serviria para a fraude de troca de conta, a mais comum com fornecedores. O que sai é cuentaCliente, que é o SEU número de cliente naquele fornecedor e com o qual um ERP concilia as compras.
O acréscimo de equivalência é somente de leitura
O campo excluidoRecargoEquivalencia é devolvido e você pode reenviá-lo com o mesmo valor (para poder devolver o objeto inteiro), mas alterá-lo pela API responde 400: ele decide se as suas compras naquele fornecedor levam o acréscimo, ou seja, mexe na base de cálculo das suas notas fiscais de compra. Muda-se na ficha do fornecedor. Fora da Espanha não tem nenhum 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 se repetir até dentro da sua própria oficina. Por isso GET /proveedores/{id} só aceita o id. Se o seu ERP guarda apenas o código, use o filtro da listagem: GET /proveedores?codigo=PROV-004, que devolve todos os que combinarem e você decide.
Ordens de serviço (somente leitura)
A API também permite consultar as ordens de serviço: número da ordem, status, datas, o aparelho (tipo, marca, modelo, número de série, IMEI) e o orçamento. É somente leitura: as ordens continuam sendo criadas e mudando de status no Sattotal, onde se assinam o comprovante de entrada e a entrega. A chave precisa do recurso Reparos marcado; chaves de clientes ou fornecedores não chegam a elas.
Campos da ordem
Cada ordem traz numeroFicha, estado, prioridad, ubicacion, averiaDeclarada, diagnostico, as datas do ciclo (entrada, início e fim do diagnóstico e do reparo, aviso ao cliente, entrega e ultimoCambioEstado, quando passou para o status atual), um resumo do cliente (id, codigo, codigoVisible, nombre, apellidos, razonSocial), o aparelho (id, codigo, tipo, marca, modelo, numeroSerie, imei, color), o orçamento (numero, total, estado, fechaEnvio e fechaRespuesta, ou null se não houver), o técnico responsável (só o nome) e plazoEntregaEstimado, o prazo informado ao cliente no comprovante de entrada. Notas internas, assinaturas, fotos, documentos e senhas do aparelho nunca são retornados.
Requisição
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á ligando
Se o seu CRM ou o seu PABX abre a ficha do cliente quando entra uma ligação, use GET /clientes?telefono=<número>. A busca é feita no telefone principal e no secundário e ignora como o número está escrito: espaços, hífens, parênteses, o código internacional do seu país (+55 ou 0055) e o 0 inicial. Assim, “(11) 91234-5678” encontra um cliente salvo como “+55 11 91234 5678”. São necessários pelo menos 6 dígitos.
Resumo do cliente para o seu CRM
GET /clientes/{id}/resumen retorna em uma única chamada o que um CRM costuma mostrar na ficha do cliente: totalReparaciones, reparacionesAbiertas (o aparelho ainda está na assistência), porEstado, totalPresupuestado e totalPresupuestosAprobados (na moeda da assistência, que vem em moneda), primeraReparacion, ultimaReparacion e ultimaActividad (a última alteração em qualquer uma das ordens dele). Precisa do recurso Reparos, assim como as ordens.
Requisição
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 trazer tudo em cada execução. Guarde na sua ferramenta a data e a hora da última execução e peça apenas os clientes ou fornecedores modificados desde então com o parâmetro actualizadoDesde. A resposta vem ordenada por data de modificação crescente e com um desempate estável, então você pode paginá-la sem pular registros. Os arquivados também aparecem (com activo = false), para que seu CRM possa refletir o arquivamento.
GET /api/v1/clientes?actualizadoDesde=2026-09-18T10:00:00Z&limit=100&page=1 Authorization: Bearer sat_Ab3k9…x9Zq
Primeira execução
Percorra GET /clientes com limit=100 e page=1, 2, 3… até totalPages se esgotar. Guarde a hora de início.
Execuções seguintes
Peça GET /clientes?actualizadoDesde=<hora guardada> e processe só o que chegar. Guarde de novo a hora de início desta execução.
Vincule, não duplique
Guarde o id do Sattotal junto ao registro do seu CRM. Se ao criar você receber um 409 DUPLICADO, a resposta traz existenteId: vincule esse em vez de criar outro.
Paginação e busca
As listagens aceitam page (a partir de 1) e limit (25 por padrão, 100 no máximo; se pedir mais, é cortado para 100). O campo busqueda procura em nome, sobrenome, razão social, identificador fiscal, e-mail, código e telefone.
Códigos de erro e o que fazer
Todas as respostas de erro trazem success: false, um texto explicativo e um code estável, pensado para decidir por programa. Estes são os que você pode receber:
NO_AUTORIZADOA chave está faltando, tem um formato que não é o nosso ou não existe. Confira o cabeçalho Authorization.
CLAVE_REVOCADAA chave era válida, mas um administrador a revogou. Crie uma nova em Configurações → API e atualize na sua ferramenta.
PLAN_REQUERIDOA organização está no plano gratuito. A API volta a funcionar ao mudar para um plano pago.
PERMISO_DENEGADOA chave não tem a permissão necessária para essa operação. A resposta indica em ambitoRequerido qual está faltando: crie uma chave com essa permissão.
NO_ENCONTRADONão há nenhum cliente nem fornecedor com esse id na sua organização. Os de outras organizações nunca ficam visíveis, e não se distingue «não existe» de «não é seu».
DUPLICADOJá existe um registro com esse dado: identificador fiscal ou e-mail em clientes; identificador fiscal, nome ou código em fornecedores. A resposta traz campo e existenteId para que você possa vinculá-lo em vez de criar outro.
VALIDACIONAlgum campo não passa na validação (ou o JSON está mal formado). Em details vêm o campo e o motivo, igual ao formulário.
IDENTIFICADOR_FISCAL_REQUERIDOEsse cliente precisa de identificador fiscal: no seu país ele é obrigatório para o tipo de cliente enviado (por exemplo, sempre para empresas).
RATE_LIMITRequisições demais. Aguarde os segundos indicados no cabeçalho Retry-After e tente de novo.
API_DESACTIVADAA API está desativada temporariamente para manutenção. Tente de novo mais tarde.
Limites
120 requisições por minuto por chave (mais do que suficiente para uma sincronização periódica; freia um loop acidental). 10 chaves ativas por organização. As listagens devolvem no máximo 100 registros por página. Se a organização estiver no plano gratuito com a cota mensal esgotada, o cadastro de clientes é bloqueado, igual ao aplicativo.
Passo a passo: sincronizar clientes com o Make
Um cenário típico: a cada 15 minutos, trazer para o seu CRM os clientes e fornecedores novos ou modificados no Sattotal. No n8n o equivalente é com o nó HTTP Request e um nó Schedule.
Crie a chave no Sattotal
Configurações → API → Nova chave, permissão «Somente leitura» se você só vai ler, «Leitura e escrita» se também vai criar clientes a partir do CRM. Copie a chave.
Módulo HTTP «Make a request»
URL: sua URL base + /clientes. Método GET. Cabeçalho Authorization com o valor Bearer e a sua chave. Marque «Parse response» para trabalhar com o JSON.
Teste a conexão
Antes de tudo, execute uma vez uma requisição a /me: se ela devolver a sua organização e o nome da chave, a autenticação está certa.
Adicione o filtro incremental
Guarde a data da última execução em um Data store ou em uma variável e passe-a como actualizadoDesde na URL. Agende o cenário a cada 15 minutos.
Mapeie os campos para o seu CRM
Itere data[] e mapeie id, codigo, nombre, apellidos, email, telefono, nif_cif e direccion. Guarde o id do Sattotal no seu CRM para atualizar em vez de duplicar.
Para criar clientes a partir do CRM, use outro módulo HTTP com método POST para /clientes e o corpo JSON do cliente. Se receber 409, use existenteId para vincular.
Boas práticas de segurança
Uma chave por integração
Assim você pode revogar uma sem quebrar as outras, e na lista vê quando cada uma foi usada pela última vez.
Nunca no navegador nem em um repositório público
Guarde-a no cofre de credenciais da sua ferramenta (conexões do Make, credenciais do n8n, variáveis de ambiente). Se ela for parar em um repositório ou em um site, considere-a vazada.
Se vazar, revogue e crie outra
A revogação é imediata: a chave antiga passa a receber 401 CLAVE_REVOCADA. Atualize a nova na sua ferramenta e pronto.
Especificação API
A referência técnica completa (rotas, parâmetros, esquemas e códigos de erro) está publicada no formato aberto em /api/v1/openapi.json, sem precisar de chave. Por padrão ela vem em espanhol; adicione ?lang= com o seu idioma para tê-la traduzida (por exemplo /api/v1/openapi.json?lang=pt, ?lang=en ou ?lang=ro). Você pode importá-la no Postman, Insomnia, Make ou n8n para ter todas as chamadas prontas.
Perguntas frequentes
Perdi a chave, posso vê-la de novo?
Não. Ela só é mostrada ao ser criada e depois é guardada de forma irreversível. Revogue-a em Configurações → API e crie outra.
Existem webhooks para o Sattotal avisar meu CRM quando algo muda?
Ainda não. A forma recomendada é consultar periodicamente com o parâmetro actualizadoDesde, que devolve só o que mudou.
Quais dados a API expõe?
Clientes e fornecedores: listar, criar, consultar, atualizar e arquivar. As permissões são por recurso, então uma chave criada antes de os fornecedores existirem não acessa esses dados até que um administrador marque o recurso. Além disso, as ordens de serviço em somente leitura (status, datas, aparelho e orçamento), com permissão própria.
Posso excluir um cliente pela API?
Não, só arquivá-lo (activo = false), igual ao aplicativo. Vale tanto para clientes quanto para fornecedores. Um registro arquivado continua aparecendo na sincronização para que seu CRM o reflita.
A API está no plano gratuito?
Não. Ela está incluída no Basic, Pro e Enterprise e durante o período de teste. No plano gratuito você continua podendo ver e revogar as chaves que criou.
Só chega o sobrenome do cliente. Por que o primeiro nome não é salvo?
Quase sempre é o mapeamento de campos: o primeiro nome vai em nombre e o sobrenome em apellidos. Se a sua ferramenta envia o nome com outra chave (firstName, name, apellido…), a API a descarta e avisa em avisos.camposIgnorados na resposta. Corrija o mapeamento e envie o cliente de novo com um PATCH.
Consigo encontrar o cliente pelo número que está me ligando?
Sim. Chame GET /api/v1/clientes?telefono= com o número do jeito que ele chega: não importa se vem com código internacional, espaços ou hífens, e a busca inclui também o telefone secundário. Com o id dele você pode depois pedir as ordens (/clientes/{id}/reparaciones) e o resumo (/clientes/{id}/resumen).
