1. Introdução
Esta página é uma documentação complementar da API do ERP Spalla. Ela descreve como o integrador externo (ou um agente de IA) trabalha com os anexos: os arquivos — PDFs, imagens, planilhas, e-mails — que os usuários do ERP vinculam a um registro, como o cadastro de uma pessoa, um orçamento ou uma ordem de serviço.
Três conceitos organizam todo o fluxo:
| Conceito | Na API | O que é |
|---|---|---|
| Recurso | id_recurso | Uma tela do ERP que aceita anexos, como Cadastro de Pessoas. Cada instalação tem os seus recursos, com os seus próprios códigos. |
| Registro | id_registro | O registro dono dos anexos, identificado pelos valores da sua chave, cada um seguido de ; — por exemplo, 1234; para a pessoa de código 1234. |
| Arquivo | id_arquivo | Cada arquivo anexado, com um identificador numérico único devolvido pela API na inclusão e na listagem. |
Um endpoint próprio. Os anexos não passam pelo /root/integrador nem aparecem no dicionário oficial, porque não são um objeto do banco de dados: eles têm um endpoint dedicado, /root/anexo, descrito nesta página. Esta página é a referência desse endpoint.
2. Onde encontrar o dicionário oficial da sua API
Cada empresa que opera o ERP Spalla expõe o seu próprio dicionário automático em um endereço próprio. Para acessá-lo, abra no navegador a URL no formato abaixo, substituindo os placeholders pelos valores da sua instância:
https://<host>:<porta>/root/dicionario?userToken=<token>
<host>— endereço do servidor que hospeda a API.<porta>— porta de comunicação configurada no servidor.<token>— token de identificação (userToken) fornecido pela equipe responsável pela API.
O endpoint de anexos não consta do dicionário, mas o dicionário continua útil aqui: é nele que você encontra a tabela e os campos da chave do registro dono dos anexos — os valores que compõem o id_registro (Passo 3).
3. Como o endpoint de anexos funciona
Atenção — aqui o verbo HTTP define a operação. No /root/integrador, o verbo HTTP é sempre PATCH e a operação vem do campo "method" do corpo JSON. O /root/anexo é a exceção: a operação é o próprio verbo HTTP (GET, POST, PUT ou DELETE), e não existe o campo "method".
| Item | Valor |
|---|---|
| Endpoint | /root/anexo |
| Autenticação | Header ou query param userToken — o mesmo token usado no /root/integrador. |
| Operação | O verbo HTTP da requisição. |
Leitura (GET) | Parâmetros na query string; o parâmetro acao escolhe o que fazer. |
Gravação (POST, PUT, DELETE) | Parâmetros no corpo JSON. |
As seis operações disponíveis:
| Verbo HTTP | Parâmetros | Operação | Passo |
|---|---|---|---|
GET | acao=recursos | Listar os recursos que aceitam anexos | Passo 2 |
GET | acao=listar, id_recurso, id_registro | Listar os anexos de um registro | Passo 4 |
GET | acao=baixar, id_arquivo | Baixar o conteúdo de um arquivo | Passo 5 |
POST | corpo JSON | Incluir um arquivo | Passo 6 |
PUT | corpo JSON | Substituir o conteúdo de um arquivo | Passo 7 |
DELETE | corpo JSON | Remover um arquivo | Passo 8 |
Qualquer outro verbo HTTP é recusado com 400 (Invalid URI). A montagem da requisição — URL base, porta e o header userToken — segue a documentação geral da API; esta página mostra apenas os parâmetros e o corpo de cada operação.
4. Visão geral do fluxo
O trabalho com anexos começa sempre pela descoberta, porque os códigos dos recursos mudam de uma instalação para outra:
- Descobrir os recursos (
GET acao=recursos) — quais telas aceitam anexos e quais campos formam a chave de cada uma. - Montar o
id_registrocom os valores da chave do registro, cada um seguido de;. - Listar (
GET acao=listar) os anexos do registro e obter oid_arquivode cada um. - Conforme a necessidade: baixar (
GET acao=baixar), incluir (POST), substituir (PUT) ou remover (DELETE).
Um arquivo incluído pela API aparece para o usuário na tela do ERP, e um arquivo anexado na tela aparece na API: os dois canais trabalham sobre o mesmo cadastro de anexos, e cada operação feita pela API fica registrada no histórico com o usuário do token.
5. Diagrama de execução
Convenção visual: azul (Retaguarda do ERP) · verde (Via API).
6. Aviso sobre liberação na retaguarda
Atenção — o acesso aos anexos segue as permissões de tela.
O endpoint de anexos não usa a lista de objetos e verbos da sua chave de API. O que decide o acesso é a configuração feita na retaguarda do ERP:
- Permissão de tela do usuário do token. Cada recurso está vinculado a uma tela do ERP, e só aparece para o
userTokencujo usuário tem acesso a ela. Recurso sem acesso não é listado, e os anexos dele não podem ser lidos nem gravados. - Configuração de anexos da instalação. As telas que aceitam anexos e a pasta do servidor onde os arquivos ficam guardados são definidas pela operação responsável pelo ERP.
Se um recurso esperado não aparece no Passo 2, a liberação deve ser pedida à equipe responsável pela API.
Antes da primeira chamada, confirme com a equipe responsável pelo ERP:
| Pré-requisito | Por quê |
|---|---|
| A tela desejada aceita anexos | Só as telas configuradas para anexos viram recursos na API. |
| A pasta de anexos está configurada no servidor | É onde os arquivos incluídos pela API são guardados. Sem ela, a inclusão falha. |
O usuário do userToken tem acesso à tela | A API aplica a mesma permissão de tela do ERP: sem acesso, o recurso não é listado. |
Uma requisição GET com o parâmetro acao=recursos devolve as telas que aceitam anexos e às quais o usuário do token tem acesso:
GET /root/anexo?acao=recursos
A resposta é uma lista, um item por recurso:
[
{
// Código do recurso: usado em acao=listar e no POST
"id_recurso": 2
// Nome da tela no ERP
,"recurso": "Cadastro de Pessoas"
// Campos da chave do registro, na ordem em que compõem o id_registro
,"id_registro": "CF_COD;"
}
,{
"id_recurso": 1
,"recurso": "Orçamento para Cliente (VL)"
,"id_registro": "FL_COD;OC_COD;"
}
]
Não fixe os códigos no seu sistema. O id_recurso de uma mesma tela pode ser diferente em cada instalação do ERP. Descubra-os com esta chamada e guarde o código correspondente ao nome da tela.
Valores ilustrativos. Os códigos e nomes acima são exemplos. Os recursos reais dependem da configuração e das permissões da sua instância.
O campo id_registro devolvido no Passo 2 diz quais campos identificam o registro e em que ordem. Para montar o seu id_registro, troque cada nome de campo pelo valor dele no registro desejado, mantendo o ; depois de cada valor:
| Chave do recurso | Registro | id_registro |
|---|---|---|
CF_COD; | Pessoa de código 1234 | 1234; |
FL_COD;OC_COD; | Empresa 1, orçamento 5678 | 1;5678; |
O ; final é obrigatório. Na listagem, 1234 sem o ; não encontra os anexos de 1234;, e a resposta volta como se o registro não tivesse anexo nenhum — com 200 e sem erro. Na inclusão, a API só completa o ; quando o valor não tem nenhum: 1;5678 é gravado assim mesmo, e depois não é encontrado por 1;5678;. Termine sempre o id_registro com ;.
Os valores da chave são os do registro dono dos anexos. Para localizá-los — por exemplo, o CF_COD de uma pessoa a partir do CNPJ — use uma consulta no /root/integrador, como descrito nos guias de cada módulo.
Com o recurso e o registro, liste os arquivos anexados:
GET /root/anexo?acao=listar&id_recurso=2&id_registro=1234;
Cada item da resposta descreve um arquivo:
| Campo | Conteúdo |
|---|---|
id_arquivo | Identificador do arquivo, usado para baixar, substituir e remover. |
arquivo | Nome do arquivo, com a extensão. |
descricao, tags | Descrição e tags informadas na inclusão (podem vir null). |
data_inclusao, usuario_inclusao | Quando e por quem o arquivo foi anexado. |
data_modificacao, usuario_modificacao | Quando e por quem o conteúdo foi alterado pela última vez. |
propriedades | Texto XML com os atributos do arquivo: SZ (tamanho em bytes) e as datas do arquivo original (DT modificação, DC criação, DA acesso), no formato DD/MM/AAAA HH:MM:SS. |
[
{
"id_arquivo": 13579
,"arquivo": "contrato-social.pdf"
,"data_inclusao": "2026-04-21T10:15:02.000"
,"usuario_inclusao": "INTEGRACAO"
,"data_modificacao": "2026-04-21T10:15:02.000"
,"usuario_modificacao": "INTEGRACAO"
,"descricao": "Contrato social atualizado"
,"tags": "juridico;cadastro"
,"propriedades": "<FL ID=\"contrato-social.pdf\" SZ=\"48213\" DT=\"21/04/2026 10:15:01\" ... ></FL>"
}
]
Registro sem anexos não devolve lista vazia. A resposta é o objeto {"message": "Não existem anexos vinculados ao registro"}, com 200. Confira se o retorno é uma lista antes de percorrê-lo. A mesma resposta aparece quando o id_registro está sem o ; final (Passo 3).
Não exiba o propriedades ao usuário final. O atributo NM guarda o caminho completo do arquivo na máquina de quem o anexou, o que pode incluir nomes de pastas e de usuários. Use apenas o que interessa, como o tamanho em SZ.
As datas da resposta vêm com T entre a data e a hora, como em toda a API. Para reaproveitá-las em um filtro no /root/integrador, siga a regra de Datas, Horas e Data/Hora.
Com o id_arquivo, baixe o conteúdo:
GET /root/anexo?acao=baixar&id_arquivo=13579
A resposta é o próprio arquivo, em binário — não é JSON nem Base64. Os headers da resposta trazem o tipo e o nome:
| Header | Exemplo |
|---|---|
Content-Type | application/pdf — conforme a extensão do arquivo. |
Content-Disposition | attachment; filename="contrato-social.pdf" |
Grave o corpo da resposta como está, em modo binário. Um id_arquivo que não existe, ou de um recurso a que o usuário do token não tem acesso, devolve 404 com a mensagem Não encontrado.
Para anexar um arquivo, envie um POST com o conteúdo codificado em Base64 no corpo JSON:
| Campo | Obrigatório | Conteúdo |
|---|---|---|
arquivo | Sim | Nome do arquivo, com a extensão. É o nome que o usuário vê na tela e no download. |
id_recurso | Sim | Código do recurso (Passo 2), como número. |
id_registro | Sim | Chave do registro, terminada em ; (Passo 3). |
binario | Sim | Conteúdo do arquivo em Base64, sem o prefixo data:...;base64,. |
descricao | Não | Descrição resumida do anexo. |
tags | Não | Palavras para indexação, separadas por ;. |
{
// Nome com a extensão
"arquivo": "contrato-social.pdf"
// Recurso obtido no Passo 2
,"id_recurso": 2
// Chave do registro, terminada em ;
,"id_registro": "1234;"
// Conteúdo em Base64, sem o prefixo data:
,"binario": "JVBERi0xLjcKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2cv..."
,"descricao": "Contrato social atualizado"
,"tags": "juridico;cadastro"
}
A resposta traz o identificador do arquivo criado:
{"id_arquivo": 13579}
Um nome por registro. Não é possível incluir dois arquivos com o mesmo nome no mesmo registro: a segunda inclusão é recusada com 500 e a mensagem Erro ao manipular anexos., seguida de um detalhe técnico sobre índice duplicado. Para trocar o conteúdo de um arquivo que já existe, use o PUT (Passo 7); para guardar uma versão nova sem perder a anterior, inclua-a com outro nome.
O usuário do token fica registrado como autor da inclusão (usuario_inclusao), e o arquivo aparece imediatamente na tela do ERP.
O PUT troca o conteúdo de um arquivo que já existe, mantendo o mesmo id_arquivo:
{
// Arquivo a substituir
"id_arquivo": 13579
// Conteúdo novo em Base64, sem o prefixo data:
,"binario": "JVBERi0xLjcKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2cv..."
}
A resposta é a mesma da inclusão: {"id_arquivo": 13579}. A data e o usuário de modificação são atualizados.
Só o conteúdo muda. O nome, a descrição e as tags ficam como foram gravados na inclusão, mesmo que sejam enviados no PUT. Para renomear um anexo, inclua-o de novo com o nome certo e remova o antigo. Os dois campos, id_arquivo e binario, são obrigatórios: sem o binario, a requisição é recusada com 400.
O DELETE remove o arquivo e o seu registro de anexo:
{
// Arquivo a remover
"id_arquivo": 13579
}
A resposta repete o identificador: {"id_arquivo": 13579}.
A resposta não prova a remoção. Um DELETE de um id_arquivo que já foi removido também devolve 200 com o mesmo identificador. Quando for importante confirmar, liste os anexos do registro depois (Passo 4). A remoção não tem volta pela API.
Validações e erros
Os erros do endpoint de anexos voltam no formato padrão da API, com errorCode e uma mensagem. Situações conferidas:
| Situação | Resposta | O que fazer |
|---|---|---|
userToken ausente ou inválido | 401 — Usuário inválido | Conferir o token no header. |
GET sem acao ou com acao desconhecida | 204, sem corpo | Usar recursos, listar ou baixar. |
| Parâmetro obrigatório ausente | 400 — Parametros não informados | Conferir os campos obrigatórios do passo. |
id_registro sem o ; final | 200 — Não existem anexos vinculados ao registro | Terminar o id_registro com ; (Passo 3). |
| Arquivo com o mesmo nome já existe no registro | 500 — Erro ao manipular anexos. | Usar o PUT ou outro nome (Passo 6). |
id_recurso que não existe na instalação | 500 — Erro ao manipular anexos. | Descobrir o código com acao=recursos (Passo 2). |
id_arquivo que não existe, em acao=baixar | 404 — Não encontrado | Listar os anexos para obter o código atual. |
DELETE de arquivo já removido | 200, com o id_arquivo | Confirmar pela listagem (Passo 8). |
Verbo HTTP diferente de GET, POST, PUT e DELETE | 400 — Invalid URI | Usar o verbo da operação (seção 3). |
Note que o endpoint devolve 200 em duas situações que, para a integração, são falhas: o id_registro sem ; e o DELETE repetido. Trate o conteúdo da resposta, não só o código HTTP.
Dica — identificar os campos da chave a partir da interface do ERP
Atalho para inspeção visual. Ao operar uma tela diretamente pela interface do ERP, pressione Ctrl + Alt + Shift + H. O sistema altera o título da janela indicando que o modo de identificação está ativo. A partir daí, ao parar o mouse sobre qualquer campo da tela, aparece um hintbox mostrando o nome da tabela e da coluna do banco às quais aquele campo está vinculado. É a forma mais rápida de achar, na tela, os campos da chave que o Passo 2 lista — e os valores que formam o id_registro.
Relação com os demais guias
O endpoint de anexos complementa os fluxos dos outros módulos: o registro é criado ou localizado pelo /root/integrador, e os arquivos dele são tratados aqui.
- Cadastro de Pessoas — documentos da pessoa, como contrato social ou comprovante de endereço. Ver Cadastro de Pessoas para obter o
CF_COD. - Demais telas — qualquer tela configurada para anexos na sua instalação aparece no Passo 2, com os seus campos de chave. Os guias de cada módulo mostram como localizar os registros correspondentes.
Onde aprofundar
Esta página é a referência do endpoint /root/anexo: operações, parâmetros e respostas. Para localizar os registros donos dos anexos — tabelas, campos da chave e consultas — a fonte autoritativa é o dicionário oficial da sua instância, em https://<host>:<porta>/root/dicionario?userToken=<token>.
A montagem da requisição — URL base, porta, autenticação e o formato dos valores — está na documentação geral da API.