Controle de Anexos — Documentação Complementar

Como listar, baixar, incluir, substituir e remover os arquivos anexados aos registros do ERP Spalla via API

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:

ConceitoNa APIO que é
Recursoid_recursoUma tela do ERP que aceita anexos, como Cadastro de Pessoas. Cada instalação tem os seus recursos, com os seus próprios códigos.
Registroid_registroO registro dono dos anexos, identificado pelos valores da sua chave, cada um seguido de ; — por exemplo, 1234; para a pessoa de código 1234.
Arquivoid_arquivoCada 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>

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".

ItemValor
Endpoint/root/anexo
AutenticaçãoHeader ou query param userToken — o mesmo token usado no /root/integrador.
OperaçãoO 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 HTTPParâmetrosOperaçãoPasso
GETacao=recursosListar os recursos que aceitam anexosPasso 2
GETacao=listar, id_recurso, id_registroListar os anexos de um registroPasso 4
GETacao=baixar, id_arquivoBaixar o conteúdo de um arquivoPasso 5
POSTcorpo JSONIncluir um arquivoPasso 6
PUTcorpo JSONSubstituir o conteúdo de um arquivoPasso 7
DELETEcorpo JSONRemover um arquivoPasso 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:

  1. Descobrir os recursos (GET acao=recursos) — quais telas aceitam anexos e quais campos formam a chave de cada uma.
  2. Montar o id_registro com os valores da chave do registro, cada um seguido de ;.
  3. Listar (GET acao=listar) os anexos do registro e obter o id_arquivo de cada um.
  4. 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:

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é-requisitoPor quê
A tela desejada aceita anexosSó 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 à telaA 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 recursoRegistroid_registro
CF_COD;Pessoa de código 12341234;
FL_COD;OC_COD;Empresa 1, orçamento 56781;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:

CampoConteúdo
id_arquivoIdentificador do arquivo, usado para baixar, substituir e remover.
arquivoNome do arquivo, com a extensão.
descricao, tagsDescrição e tags informadas na inclusão (podem vir null).
data_inclusao, usuario_inclusaoQuando e por quem o arquivo foi anexado.
data_modificacao, usuario_modificacaoQuando e por quem o conteúdo foi alterado pela última vez.
propriedadesTexto 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:

HeaderExemplo
Content-Typeapplication/pdf — conforme a extensão do arquivo.
Content-Dispositionattachment; 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:

CampoObrigatórioConteúdo
arquivoSimNome do arquivo, com a extensão. É o nome que o usuário vê na tela e no download.
id_recursoSimCódigo do recurso (Passo 2), como número.
id_registroSimChave do registro, terminada em ; (Passo 3).
binarioSimConteúdo do arquivo em Base64, sem o prefixo data:...;base64,.
descricaoNãoDescrição resumida do anexo.
tagsNãoPalavras 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çãoRespostaO que fazer
userToken ausente ou inválido401 — Usuário inválidoConferir o token no header.
GET sem acao ou com acao desconhecida204, sem corpoUsar recursos, listar ou baixar.
Parâmetro obrigatório ausente400 — Parametros não informadosConferir os campos obrigatórios do passo.
id_registro sem o ; final200 — Não existem anexos vinculados ao registroTerminar o id_registro com ; (Passo 3).
Arquivo com o mesmo nome já existe no registro500 — Erro ao manipular anexos.Usar o PUT ou outro nome (Passo 6).
id_recurso que não existe na instalação500 — Erro ao manipular anexos.Descobrir o código com acao=recursos (Passo 2).
id_arquivo que não existe, em acao=baixar404 — Não encontradoListar os anexos para obter o código atual.
DELETE de arquivo já removido200, com o id_arquivoConfirmar pela listagem (Passo 8).
Verbo HTTP diferente de GET, POST, PUT e DELETE400 — Invalid URIUsar 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.

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.