Integração via API REST
Endereço da API: https://distsys.com — nos exemplos ele aparece como
{{baseUrl}}, a mesma variável da collection do Postman.
Como funciona
A API permite que os sistemas da sua corporação (ERP, PDV, WMS, BI) conversem com a Distsys sem intervenção manual. Os dados são organizados assim:
- Corporação — a empresa dona da conta. Cada credencial de API pertence a uma corporação e só enxerga os dados dela.
- Lojas (stores) — as unidades (CNPJs) da corporação. Cada loja conecta as suas contas nos marketplaces.
- Itens (items) — o cadastro de produtos da corporação, identificado pelo código do seu ERP e compartilhado por todas as lojas.
- Preço e estoque — são de cada loja: o mesmo item pode ter preço e estoque diferentes em cada unidade.
- Anúncios (offers) — os anúncios da loja em cada marketplace, importados automaticamente das contas conectadas ou cadastrados pela API, e vinculados aos itens.
- Vendas (sales) — os pedidos da loja, importados dos marketplaces ou enviados pela API (vendas de outros canais, nota fiscal e andamento da entrega).
Início rápido
- Um administrador da corporação entra na Distsys, abre a página da corporação e cria uma credencial de API no card Credenciais de API, escolhendo os escopos (permissões) e, se quiser, as lojas permitidas.
- Copie o
client_ide oclient_secret. O segredo aparece uma única vez. - O seu sistema troca a credencial por um token em
POST /oauth2/token. - Use o token no cabeçalho
Authorization: Bearer <token>em todas as chamadas a/v1. Ele vale 15 minutos: peça um novo quando expirar.
Collection do Postman
Autenticação, lojas, itens, preços e estoques, anúncios e vendas.
- No Postman, clique em Import e escolha o arquivo baixado.
- Na aba Variables da collection, preencha
clientIdeclientSecret(e ajustebaseUrl, se necessário). - Execute 1. Autenticação › Obter token: o token é salvo em
accessTokene usado automaticamente pelas demais requisições. - As requisições de criação gravam os ids retornados (
storeId,offerId,saleId) para as seguintes. Você também pode rodar a pasta inteira no Runner.
1. Autenticação (OAuth 2.0 Client Credentials)
Envie o client_id e o client_secret em HTTP Basic (recomendado) ou no corpo do
formulário. O parâmetro opcional scope pede só parte dos escopos da credencial.
curl -X POST {{baseUrl}}/oauth2/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=client_credentials
{
"access_token": "eyJraWQiOi...",
"token_type": "Bearer",
"expires_in": 900,
"scope": "stores:read items:read items:write stock:write"
}
O token é um JWT assinado (RS256). A chave pública está em GET /oauth2/jwks. Se a credencial
for revogada, os tokens dela deixam de valer na hora.
Escopos
| Escopo | Permite |
|---|---|
stores:read | Ler lojas |
stores:write | Cadastrar e alterar lojas |
items:read | Ler itens, preços e estoques |
items:write | Cadastrar e alterar itens |
offers:read | Ler anúncios |
offers:write | Cadastrar e alterar anúncios |
prices:write | Atualizar preços por loja |
stock:write | Atualizar estoques por loja |
sales:read | Ler vendas |
sales:write | Cadastrar e alterar vendas |
Convenções e erros
- JSON em UTF-8. Envie
Content-Type: application/jsonnos corpos. - Valores monetários com ponto e até 2 casas:
59.90. - Datas em ISO-8601 com fuso:
2026-10-22T10:15:30-03:00. - Listas paginadas:
page(a partir de 0) esize(padrão 100, máximo 500). Resposta:{"data": [...], "page": 0, "size": 100, "total": 250}. POSTcria (resposta201com o cabeçalhoLocation);PATCHaltera só os campos enviados;PUTem itens cria ou atualiza pelo código.- Operações em lote aceitam até 500 entradas e processam cada uma separadamente
(
succeeded,failede o erro de cada código).
Erros seguem o formato application/problem+json (RFC 7807) com um code estável:
{
"status": 403,
"title": "Forbidden",
"detail": "O token não tem o escopo items:write.",
"code": "insufficient_scope"
}
| HTTP | code | Quando |
|---|---|---|
| 400 | invalid_request | Campo obrigatório ausente ou valor inválido. |
| 401 | invalid_token | Token ausente, expirado ou de credencial revogada. |
| 403 | insufficient_scope | O token não tem o escopo exigido. |
| 403 | store_restricted | Credencial restrita a lojas tentando cadastrar loja. |
| 404 | not_found | Recurso inexistente ou de outra corporação/loja não permitida. |
| 409 | conflict | CNPJ, anúncio (externalId) ou pedido já cadastrado. |
2. Lojas (stores)
| Método | Caminho | Escopo | Descrição |
|---|---|---|---|
| GET | /v1/stores | stores:read | Lista as lojas permitidas à credencial. |
| GET | /v1/stores/{storeId} | stores:read | Detalha uma loja. |
| POST | /v1/stores | stores:write | Cadastra uma loja na corporação (credenciais sem restrição de lojas). |
| PATCH | /v1/stores/{storeId} | stores:write | Altera os campos enviados. |
POST {{baseUrl}}/v1/stores
{
"name": "Loja Centro",
"taxNumber": "12.345.678/0001-90",
"zipCode": "01001-000",
"state": "SP",
"city": "São Paulo",
"address": "Praça da Sé, 100",
"phone": "(11) 3333-4444",
"stateTaxNumber": "123.456.789.000"
}
201 Created
{
"id": "6ada1f7f8b57d20833b729ea",
"name": "Loja Centro",
"taxNumber": "12.345.678/0001-90",
"city": "São Paulo",
"state": "SP",
"connectedMarketplaces": [],
"zipCode": "01001-000",
"address": "Praça da Sé, 100",
"phone": "(11) 3333-4444",
"site": null,
"stateTaxNumber": "123.456.789.000",
"cityTaxNumber": null
}
3. Itens (items)
Os itens são da corporação e identificados pelo código do seu ERP ({code}, até 60 caracteres;
codifique na URL caracteres especiais).
| Método | Caminho | Escopo | Descrição |
|---|---|---|---|
| GET | /v1/items?updatedSince=&page=&size= | items:read | Lista os itens (filtro opcional por data de alteração). |
| GET | /v1/items/{code} | items:read | Detalha um item. |
| PUT | /v1/items/{code} | items:write | Cadastra ou atualiza o item (idempotente). |
| POST | /v1/items/batch | items:write | Cadastra ou atualiza até 500 itens. |
PUT {{baseUrl}}/v1/items/CAM-001
{
"description": "Camiseta básica algodão",
"ean13": "7891234567895",
"brand": "Marca X",
"enabled": true
}
POST {{baseUrl}}/v1/items/batch
{
"items": [
{ "code": "CAM-002", "description": "Camiseta gola V" },
{ "code": "CAM-003", "description": "Camiseta manga longa", "ean13": "7891234567802" }
]
}
200 OK
{ "succeeded": 2, "failed": 0, "results": [ { "code": "CAM-002", "success": true, "error": null }, ... ] }
Dados para criar anúncios (listing)
Para publicar um item nos marketplaces, o cadastro precisa de mais que descrição e EAN: título, descrição completa,
imagens, peso e medidas da embalagem, dados fiscais, categoria e ficha técnica. Envie esses dados no objeto
listing do PUT /v1/items/{code} (ou de cada item do lote).
listingausente: os dados de anúncio do item são mantidos.- Dentro de
listing, campo ausente é mantido e campo presente substitui o valor (listas e mapas inteiros; lista vazia limpa;""limpa um texto;{}limpa um grupo comotax). - O GTIN é validado (8, 12, 13 ou 14 dígitos e dígito verificador). Ao enviar
gtin, o campoean13acompanha quando for EAN-13. - Imagens: URLs públicas (
https); a primeira semrolevira a principal (MAIN).
PUT {{baseUrl}}/v1/items/PF-N1234
{
"description": "PAST FREIO DIANT N1234",
"brand": "Cobreq",
"listing": {
"title": "Pastilha de Freio Dianteira Cobreq N-1234 Gol Voyage Fox",
"longDescription": "Pastilha de freio dianteira em composto cerâmico...",
"bulletPoints": ["Composto cerâmico", "Baixo ruído"],
"gtin": "7891234567895",
"model": "N-1234",
"manufacturer": "Cobreq",
"condition": "NEW",
"originCountry": "BR",
"categoryId": "6ae4a1c2...",
"attributes": { "posicao": "Dianteira", "material": "Cerâmica" },
"images": [
{ "url": "https://cdn.exemplo.com.br/pf-n1234-1.jpg", "role": "MAIN" },
{ "url": "https://cdn.exemplo.com.br/pf-n1234-2.jpg" }
],
"packageDimensions": { "weightKg": 0.8, "heightCm": 6, "widthCm": 12, "lengthCm": 15 },
"handlingTimeDays": 1,
"tax": { "ncm": "68132090", "origin": "0", "unit": "UN" },
"warranty": { "type": "MANUFACTURER", "months": 3 }
}
}
Campo de listing | Tipo | Observação |
|---|---|---|
title, longDescription | texto | Título (até 255; cortado conforme o marketplace) e descrição completa. Sem título, vale description. |
bulletPoints, keywords | lista de textos | Destaques (até 6) e palavras-chave. |
gtin, gtinType, gtinExemptionReason | texto | Tipo EAN8, EAN13, EAN14 ou UPC (deduzido se ausente); motivo quando não há GTIN. |
model, mpn, manufacturer | texto | Modelo, código do fabricante e fabricante. |
condition | NEW, USED, REFURBISHED | Padrão NEW. |
originCountry | texto (2 letras) | ISO 3166-1, ex.: BR. |
categoryId | texto | Id de GET /v1/categories. |
attributes | mapa texto → texto | Ficha técnica com nomes internos (cor, tamanho, voltagem...). |
groupCode, variationValues | texto, mapa | Grade: código do grupo e os valores desta variação ({"cor": "Azul", "tamanho": "M"}). |
images[] | {url, role, variationValue} | role: MAIN, DETAIL, SWATCH ou SIZE_CHART. Até 20. |
videoUrl | texto | URL do vídeo. |
packageDimensions, productDimensions | {weightKg, heightCm, widthCm, lengthCm} | Embalagem (frete) e produto. |
handlingTimeDays | inteiro | Prazo de despacho (0 a 90 dias). |
tax | {ncm, cest, origin, unit, cfopSameState, cfopOtherState} | NCM 8 dígitos, origem 0 a 8, CEST 7 dígitos, CFOP 4 dígitos. |
warranty | {type, months} | NONE, SELLER ou MANUFACTURER; meses de 1 a 120. |
certifications[] | {type, number, fileUrl} | INMETRO, ANATEL, ANVISA... |
Categorias, grupos e o que falta para anunciar
| Método | Caminho | Escopo | Descrição |
|---|---|---|---|
| GET | /v1/categories | items:read | Categorias da corporação (cadastradas na tela Categorias e mapeamentos) e a categoria de cada marketplace. |
| GET | /v1/item-groups/{code} | items:read | Grupo (grade) e os códigos dos itens dele. |
| PUT | /v1/item-groups/{code} | items:write | Cria ou altera o grupo: title, longDescription, brand, categoryId, variationAxes, images. Campos vazios dos itens herdam do grupo. |
| GET | /v1/stores/{storeId}/items/{code}/listing-readiness | items:read | Para cada marketplace: se o item já pode ser anunciado na loja e o que falta. |
GET {{baseUrl}}/v1/stores/{storeId}/items/PF-N1234/listing-readiness
200 OK
{
"data": [
{
"marketplace": "mercadolivre",
"ready": false,
"missing": [
{ "field": "CATEGORY", "label": "Categoria do marketplace", "detail": "categoria sem equivalente neste marketplace",
"source": "Item.categoryId → Category.marketplaces" },
{ "field": "LISTING_TYPE", "label": "Tipo de anúncio", "detail": "configuração da loja", "source": "ListingSettings.listingTypeId" }
],
"recommended": [],
"warnings": ["Título com 66 caracteres: o limite é 60. ..."]
},
...
]
}
Preços e estoques por loja
O item precisa estar cadastrado antes. Preço e estoque são gravados na loja informada.
| Método | Caminho | Escopo | Descrição |
|---|---|---|---|
| GET | /v1/stores/{storeId}/items | items:read | Itens com o preço e o estoque da loja. |
| GET | /v1/stores/{storeId}/items/{code} | items:read | Preço e estoque de um item na loja. |
| PUT | /v1/stores/{storeId}/items/{code}/price | prices:write | {"price": 59.90}; opcionais listPrice (preço "de") e
marketplacePrices ({"amazon": 64.90}). Ausentes são mantidos. |
| PUT | /v1/stores/{storeId}/items/{code}/stock | stock:write | {"quantity": 12} |
| POST | /v1/stores/{storeId}/prices/batch | prices:write | {"items": [{"code": "CAM-001", "price": 59.90}]} |
| POST | /v1/stores/{storeId}/stock/batch | stock:write | {"items": [{"code": "CAM-001", "quantity": 12}]} |
4. Anúncios (offers)
Os anúncios das contas conectadas são importados automaticamente. Pela API você também pode cadastrar e
alterar anúncios da loja e vinculá-los aos itens (itemCode; envie "" para
desvincular).
| Método | Caminho | Escopo | Descrição |
|---|---|---|---|
| GET | /v1/stores/{storeId}/offers?marketplace=&itemCode= | offers:read | Lista os anúncios da loja. |
| GET | /v1/stores/{storeId}/offers/{offerId} | offers:read | Detalha um anúncio. |
| POST | /v1/stores/{storeId}/offers | offers:write | Cadastra um anúncio. |
| PATCH | /v1/stores/{storeId}/offers/{offerId} | offers:write | Altera os campos enviados. |
POST {{baseUrl}}/v1/stores/{storeId}/offers
{
"marketplace": "mercadolivre",
"externalId": "MLB1234567890",
"sku": "CAM-001",
"title": "Camiseta básica algodão",
"price": 59.90,
"stock": 10,
"status": "ACTIVE",
"url": "https://produto.mercadolivre.com.br/MLB-1234567890",
"itemCode": "CAM-001"
}
Marketplaces: mercadolivre, amazon, magalu, shopee,
shein, casasbahia, tiktokshop, temu. Status: ACTIVE,
PAUSED, INACTIVE, CLOSED.
5. Vendas (sales)
As vendas dos marketplaces conectados são importadas automaticamente. Pela API você também pode lançar vendas de outros canais e atualizar status, nota fiscal e datas de pagamento e envio.
| Método | Caminho | Escopo | Descrição |
|---|---|---|---|
| GET | /v1/stores/{storeId}/sales?status=&marketplace=&createdFrom=&createdTo= | sales:read | Lista as vendas (mais recentes primeiro). |
| GET | /v1/stores/{storeId}/sales/{saleId} | sales:read | Detalha uma venda. |
| POST | /v1/stores/{storeId}/sales | sales:write | Cadastra uma venda (única por marketplace + número do pedido). |
| PATCH | /v1/stores/{storeId}/sales/{saleId} | sales:write | Altera status, nota fiscal, datas, comprador ou valor. |
POST {{baseUrl}}/v1/stores/{storeId}/sales
{
"marketplace": "mercadolivre",
"externalOrderId": "2000001234567890",
"buyerName": "Maria Silva",
"totalAmount": 119.80,
"status": "PAID",
"createdAt": "2026-10-22T09:30:00-03:00",
"paidAt": "2026-10-22T09:31:00-03:00"
}
PATCH {{baseUrl}}/v1/stores/{storeId}/sales/{saleId}
{
"status": "SHIPPED",
"invoiceKey": "35261012345678000190550010000012341000012345",
"invoiceNumber": "1234",
"shippedAt": "2026-10-23T14:00:00-03:00"
}
Status aceitos: NEW, PAID, INVOICED, SHIPPED, DELIVERED, CANCELLED, REFUNDED.
A chave da nota fiscal (invoiceKey) tem 44 dígitos.