CadastroCliente
CRUD de cliente (tabela SA1) via MVC do CRMA980
— substituto moderno do antigo MATA030. Identificador
externo é CNPJ (14 dígitos) ou CPF (11 dígitos); a chave técnica
(A1_COD/A1_LOJA) é gerada pelo Protheus no POST
via GetSXENum.
Endpoint OAuth2
Sem credenciais? Você pode pegar o token rodando
./src/scripts/get-token.sh na biblioteca e
colar o access_token aqui no campo de refresh
(ou clique em "Logout" para limpar e voltar ao fake).
Vinculação com o ERP
Convenções
Identificador externo. Todas as rotas /WsSA1/{cgc}
aceitam apenas dígitos — 14 (CNPJ) ou 11 (CPF). Pontuação
(., /, -) é rejeitada com 400. A chave
interna A1_COD/A1_LOJA não é exposta como
identificador externo; use /_byid?tipo=recno|msuid&valor=…
quando precisar buscar por ela.
Bloqueio TOTVS (A1_MSBLQL / A1_MSBLQD).
Em registro bloqueado, o PUT só aceita payload que toque
exclusivamente os campos de bloqueio (caminho de desbloqueio).
Qualquer outro campo no payload retorna 422 com motivo explícito.
DELETE em cliente bloqueado também é rejeitado pelo
MsExecAuto do CRMA980.
Polaridade do par MSBLQL/MSBLQD varia por tabela. Na
SA1, A1_MSBLQL="1" é Inativo (bloqueado)
e "2" é Ativo (liberado, default). Outras
tabelas TOTVS podem inverter — consultar SX3 antes de replicar
este padrão em outro endpoint.
Formato de datas. A1_MSBLQD no payload aceita
string ISO YYYY-MM-DD ou string vazia (limpa a data); a
conversão interna usa sToD(StrTran(…, "-", "")). No GET o
campo é serializado por U_RestSerializa (Date-aware, rev3).
Paginação e delta-sync. /_list usa
page/pageSize (default 50, máx
500). Para sincronização incremental, alterne para
orderBy=recno e use since/cursor
conforme o nextCursor retornado.
Cliente
CRUD por CNPJ/CPFDescrição
Retorna o cliente pesquisado pelo CGC (CNPJ 14 dígitos ou CPF 11 dígitos).
Aplica filtro de filial (xFilial("SA1")) e respeita o whitelist
de CAMPOS_GET definido no .prw. O parâmetro
opcional fields reduz o conjunto de campos retornados.
Path parameter
^\d{11}$|^\d{14}$.Query parameters
CAMPOS_GET.Cenarios
Exemplo da requisicao (cenario ativo)
GET https://erpapi.jetme.com.br/api/99/01/WsSA1/99999999000199 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Accept: application/json
GET https://erpapi.jetme.com.br/api/99/01/WsSA1/99999999000199?fields=A1_COD,A1_NOME,A1_CGC,A1_MSBLQL Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Accept: application/json
Respostas
{ success: true, data: Cliente }.Descrição
Inclui um cliente novo via CRMA980 em modo 3
(MODEL_OPERATION_INSERT). A chave técnica
A1_COD/A1_LOJA é gerada pelo Protheus
(GetSXENum + Soma1 + ConfirmSX8) —
o cliente passa apenas o CGC. Em ambientes com localização Brasil,
CRMA980BRA é disparado automaticamente quando o payload
contém A1_INSCR + A1_EST.
- Whitelist de campos: ver
ClientePayload. - Complemento CRM (
AI0) não é exposto nesta versão; o endpoint passa{}.
Path parameter
^\d{11}$|^\d{14}$.Request body
CAMPOS_ALLOW. Schema completo em
ClientePayload.
F = Consumidor Final, R = Revenda, S = Solidário, X = Exportação.J = Jurídica (CGC 14), F = Física (CGC 11).ISENTO.POST https://erpapi.jetme.com.br/api/99/01/WsSA1/99999999000199 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Content-Type: application/json Accept: application/json { "A1_NOME": "TESTE_REST CLIENTE LTDA", "A1_NREDUZ": "TESTE_REST", "A1_END": "RUA TESTE 100", "A1_BAIRRO": "CENTRO", "A1_MUN": "SAO PAULO", "A1_EST": "SP", "A1_CEP": "01001000", "A1_DDD": "011", "A1_TEL": "999990000", "A1_EMAIL": "teste_rest@example.com", "A1_TIPO": "F", "A1_PFISICA": "J", "A1_INSCR": "ISENTO" }
POST https://erpapi.jetme.com.br/api/99/01/WsSA1/12345678901 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Content-Type: application/json Accept: application/json { "A1_NOME": "TESTE_REST CLIENTE PF", "A1_NREDUZ": "TESTE_PF", "A1_END": "RUA TESTE PF 100", "A1_BAIRRO": "CENTRO", "A1_MUN": "SAO PAULO", "A1_EST": "SP", "A1_CEP": "01001000", "A1_DDD": "011", "A1_TEL": "999990001", "A1_EMAIL": "teste_pf@example.com", "A1_TIPO": "F", "A1_PFISICA": "F", "A1_INSCR": "ISENTO" }
Respostas
CrudResponse com data = chave técnica gerada (A1_COD/A1_LOJA).MsExecAuto do CRMA980 rejeitou (campos fora do whitelist, enums inválidos, IE incompatível com UF, etc). Tier: business-error.Descrição
Altera campos do cliente via CRMA980 em modo
4 (MODEL_OPERATION_UPDATE). Aceita qualquer
subconjunto do whitelist CAMPOS_ALLOW.
Bloqueio TOTVS. Em registro bloqueado por
A1_MSBLQL="1" ou dDataBase > A1_MSBLQD,
o PUT retorna 422 a menos que o payload toque
exclusivamente A1_MSBLQL/A1_MSBLQD
(caminho de desbloqueio).
A1_MSBLQL:"1"= Inativo,"2"= Ativo (default).A1_MSBLQD: string ISOYYYY-MM-DDou vazia (limpa).
Path parameter
Request body
"1" = Inativo, "2" = Ativo. Em registro bloqueado, só este campo (e/ou A1_MSBLQD) é aceito no payload.YYYY-MM-DD) ou string vazia para limpar.PUT https://erpapi.jetme.com.br/api/99/01/WsSA1/99999999000199 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Content-Type: application/json Accept: application/json { "A1_NOME": "TESTE_REST CLIENTE LTDA ALTERADO", "A1_NREDUZ": "TESTE_ALT", "A1_END": "RUA TESTE 200", "A1_BAIRRO": "VILA TESTE", "A1_EMAIL": "teste_rest_alt@example.com" }
PUT https://erpapi.jetme.com.br/api/99/01/WsSA1/99999999000199 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Content-Type: application/json Accept: application/json { "A1_MSBLQL": "2" }
PUT https://erpapi.jetme.com.br/api/99/01/WsSA1/99999999000199 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Content-Type: application/json Accept: application/json { "A1_MSBLQL": "1", "A1_MSBLQD": "2026-12-31" }
PUT https://erpapi.jetme.com.br/api/99/01/WsSA1/99999999000199 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Content-Type: application/json Accept: application/json { "A1_MSBLQL": "2", "A1_MSBLQD": "" }
Respostas
CrudResponse.A1_MSBLQL/A1_MSBLQD. Tier: business-error.Descrição
Exclui o cliente via CRMA980 em modo 5
(MODEL_OPERATION_DELETE). O MsExecAuto do
CRMA980 rejeita exclusão de registros bloqueados.
Path parameter
Cenario
Exemplo da requisicao (cenario ativo)
DELETE https://erpapi.jetme.com.br/api/99/01/WsSA1/99999999000199 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Accept: application/json
Respostas
CrudResponse.Descrição
Busca o cliente por id técnico — útil para integrações que persistem
a chave interna (recno) ou o identificador universal
(msuid) e querem reconfirmar o registro sem reconstruir o CGC.
Query parameters
recnomsuidtipo=recno, string quando tipo=msuid).Cenarios
Exemplo da requisicao (cenario ativo)
GET https://erpapi.jetme.com.br/api/99/01/WsSA1/_byid?tipo=recno&valor=1234 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Accept: application/json
GET https://erpapi.jetme.com.br/api/99/01/WsSA1/_byid?tipo=msuid&valor=9f7a3e2c4b8d1a0e Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Accept: application/json
Respostas
{ success: true, data: Cliente }.tipo/valor ausentes ou tipo fora do enum.msuid requer índice/coluna não disponível no ambiente.Listagem
Listagem paginada e typeaheadDescrição
Lista clientes com filtros por cod, nome
(prefix normalizado, sem acento) ou cgc (prefix). Suporta
dois modos de ordenação:
orderBy=chave(default) — paginação porpage/pageSize.orderBy=recno— delta-sync, usasince/cursorcomnextCursorretornado.
Query parameters
A1_COD exato (índice 1).CAMPOS_GET.1, mínimo 1).50, máx 500).chave.chaverecnoorderBy=recno).nextCursor de página anterior.Cenarios
Exemplo da requisicao (cenario ativo)
GET https://erpapi.jetme.com.br/api/99/01/WsSA1/_list?nome=TESTE&page=1&pageSize=50 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Accept: application/json
GET https://erpapi.jetme.com.br/api/99/01/WsSA1/_list?orderBy=recno&since=0&pageSize=200 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Accept: application/json
Respostas
data (array de Cliente), page, pageSize, count, opcionalmente nextCursor.orderBy inválido, pageSize > 500).Descrição
Busca rápida (typeahead) para autocomplete de UI. Retorna uma lista
enxuta (cod, loja, cgc,
nome, recno, msuid,
msuidt) — não devolve o schema completo de
Cliente.
Query parameters
prefix.prefixcontains10, máx 25).Cenarios
Exemplo da requisicao (cenario ativo)
GET https://erpapi.jetme.com.br/api/99/01/WsSA1/_search?q=teste&match=prefix&limit=10 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Accept: application/json
GET https://erpapi.jetme.com.br/api/99/01/WsSA1/_search?q=cliente&match=contains&limit=25 Authorization: Bearer eyJhbGciOiJIUzI1NiIs… Accept: application/json
Respostas
success, count, data[] com cod/loja/cgc/nome/recno/msuid/msuidt.q ausente ou < 2 caracteres, match fora do enum.Schemas
Definições canônicas — campos com origemSX3 rastreável
/{cgc}, /_list,
/_byid). Inclui chave técnica (A1_COD/A1_LOJA),
dados cadastrais e flags de bloqueio. Campos efetivamente retornados
dependem de CAMPOS_GET e do filtro fields.
GetSXENum)."01").FRSLXF) ou Jurídica (J).FJ"ISENTO".pertence("12"), default "2". "1"=Inativo (bloqueado), "2"=Ativo (liberado).12msuid.POST e PUT. Whitelist
definida em CAMPOS_ALLOW no .prw. Em
PUT sobre cliente bloqueado, o payload deve conter
apenas A1_MSBLQL e/ou A1_MSBLQD —
qualquer outro campo provoca 422.
"105" = Brasil).FJF=Cons.Final, R=Revendedor, S=Solidário, L=Produtor Rural, X=Exportação.FRSLX"ISENTO". CRMA980BRA pode rejeitar IE inválida combinada com UF.pertence("12"), default "2"): "1"=Inativo, "2"=Ativo. MsExecAuto do CRMA980 rejeita valores fora do domínio.12YYYY-MM-DD ou vazia (limpa a data). Bloqueio fica ativo enquanto dDataBase > A1_MSBLQD.data traz
a chave técnica gerada (POST) ou string vazia (PUT/DELETE).
true em respostas de sucesso.A1_COD/A1_LOJA). Em PUT/DELETE pode ser string vazia ou objeto auxiliar.data pode conter o token interno
da causa (ex: mensagem do NomeAutoLog) para tratamento programático,
quando aplicável.
false em erros.MsExecAuto).Cenarios
Combinacoes documentadas (1 por example doopenapi.yaml)
CAMPOS_GET.fields=; util em mobile / typeahead avancado.A1_PFISICA="J", A1_TIPO="F" (Cons.Final), endereco basico e A1_INSCR="ISENTO". A1_COD/A1_LOJA sao gerados pelo Protheus (GetSXENum). Tier happy-path-minimal.A1_PFISICA="F". Validacao de DV do CPF e feita pelo X3_VALID customizado da base (quirk: usa A1_TIPO em vez de A1_PFISICA — ver Pendencias). Tier happy-path-realistic.A1_MSBLQL="2" e/ou A1_MSBLQD="" e aceito. Helper U_C980Blq.A1_MSBLQL="1" + A1_MSBLQD ISO futura.A1_MSBLQD="" para zerar a vigencia. Combinavel com mudanca de A1_MSBLQL.CRMA980 op=5. MsExecAuto rejeita registros bloqueados ou com dependencias (titulos abertos, contatos).recno da SA1 — caminho recomendado.A1_MSUID (presente nesta base — validado 2026-05-08).cod, nome prefix normalizado, cgc prefix). Default 50, max 500.recno; cliente itera via nextCursor.A1_NOME. Limit max 25.Pendências conhecidas (rev4)
SX3 quirk em A1_CGC nesta base. O X3_VALID customizado da empresa usa A1_TIPO em vez do esperado A1_PFISICA para decidir se valida CPF ou CNPJ. Resultado: CNPJ 14d com A1_TIPO="F" pode falhar CPFINVALID. Workaround: usar CPF 11d ou ajustar A1_TIPO conforme o tipo de documento. Memo: feedback_sa2_cgc_x3_customizado.
CPF 00874109159 proibido em fixtures. Instrucao 2026-05-11. Use CGCs sentinel (99999999000191) ou CPFs ja listados como aceitos.
PUT em cliente bloqueado: caminho restrito. Quando A1_MSBLQL="1" ou dDataBase > A1_MSBLQD, PUT so aceita payload tocando exclusivamente A1_MSBLQL/A1_MSBLQD — qualquer outro campo retorna 422 com motivo. Helper canonico: U_C980Blq("SA1").
Polaridade MSBLQL varia entre tabelas. Na SA1 confirmou-se "1"=Inativo / "2"=Ativo (default SX3). Outras tabelas TOTVS podem inverter — sempre consultar SX3 antes de replicar este padrao.
Localizacao Brasil condicional. CRMA980BRA e disparado quando o payload tem A1_INSCR + A1_EST; pode rejeitar IE incompativel com UF. Em ambiente sem localizacao BR, o fluxo silenciosamente nao roda.
AI0 (CRM) nao exposto. Complemento CRM nao e enviavel via REST nesta versao — o endpoint passa {} para FwLoadBy* de AI0. Adicionar quando houver demanda.