Introducao
A API REST do LOJEXA ERP permite que sistemas externos — como seu proprio site, e-commerce customizado ou outro ERP — integrem-se diretamente ao estoque centralizado do LOJEXA.
Com ela e possivel consultar produtos disponivos, registrar vendas e manter o estoque sincronizado automaticamente em todos os canais (Shopee, Mercado Livre, Amazon) sem nenhum esforco manual.
Casos de uso tipicos
- Site proprio ou e-commerce customizado: exibe estoque em tempo real e registra vendas diretamente no LOJEXA.
- Integracao com outro ERP: sincroniza dados de produtos e estoque entre sistemas.
- Aplicativo mobile: app de vendas externo que consume o estoque do LOJEXA.
- Automacoes e scripts: pipelines de dados, relatorios customizados, bots de precificacao.
Informacoes gerais
Autenticacao
Toda requisicao deve incluir uma API key valida. Voce pode envia-la de duas formas:
Opcao 1 — Header Authorization (recomendado)
Authorization: Bearer lj_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Opcao 2 — Header X-Api-Key
X-Api-Key: lj_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Onde obter sua chave
- Acesse o Painel LOJEXA
- Va em Configuracoes → API
- Clique em Criar Nova Chave
- Copie a chave — ela e exibida apenas uma vez no momento da criacao
Escopos
Ao criar uma chave, voce define quais escopos ela possui:
| Escopo | Permissao | Endpoints liberados |
|---|---|---|
read:products |
Leitura de produtos, estoque e mapeamentos | GET /ping, GET /produtos, GET /produtos/{sku}, GET /mapeamentos |
write:sales |
Registrar e cancelar vendas | POST /vendas, POST /vendas/{ref}/cancelar |
write:stock |
Ajuste manual de estoque | POST /estoque/{sku}/ajuste |
manage:mappings |
Criar e remover mapeamentos SKU | POST /mapeamentos, DELETE /mapeamentos/{id} |
Exemplo rapido — cURL
curl -H "Authorization: Bearer lj_live_SUA_CHAVE" \
https://lojexa.com/api/v1/ping
Rate Limits
A API limita o numero de requisicoes por chave para garantir estabilidade a todos os tenants.
- Padrao: 60 requisicoes por minuto por chave
- Contador: reseta a cada minuto (janela deslizante)
- Plano Enterprise: limites customizados por negociacao
Quando o limite e excedido, a API retorna HTTP 429:
{
"success": false,
"error": {
"code": "RATE_LIMIT",
"message": "Rate limit excedido. Tente novamente em 60 segundos."
}
}
Tabela de codigos de erro
| HTTP | Codigo | Descricao |
|---|---|---|
| 401 | MISSING_API_KEY | API key nao fornecida nos headers |
| 401 | INVALID_API_KEY | API key invalida (nao encontrada no banco) |
| 401 | API_KEY_REVOKED | API key foi revogada pelo administrador |
| 401 | API_KEY_EXPIRED | API key expirada (data de expiração no passado) |
| 403 | INSUFFICIENT_SCOPE | Escopo obrigatorio ausente para este endpoint |
| 404 | PRODUCT_NOT_FOUND | Produto nao encontrado para o SKU informado |
| 404 | SALE_NOT_FOUND | Venda com a referencia informada nao encontrada |
| 404 | SKU_NOT_FOUND | SKU nao encontrado para ajuste de estoque ou mapeamento |
| 404 | MAPPING_NOT_FOUND | Mapeamento nao encontrado ou nao pertence a esta empresa |
| 409 | INVALID_STATUS_FOR_CANCEL | Venda nao pode ser cancelada — status atual nao permite |
| 409 | STOCK_RACE_CONDITION | Estoque mudou durante o processamento — tente novamente |
| 422 | MISSING_REFERENCE | Campo "reference" e obrigatorio |
| 422 | MISSING_ITEMS | Campo "items" deve ser um array nao vazio |
| 422 | INSUFFICIENT_STOCK | Estoque insuficiente para um ou mais SKUs |
| 422 | INVALID_TYPE | Campo "type" deve ser "in" ou "out" (ajuste estoque) |
| 429 | RATE_LIMIT_EXCEEDED | Rate limit excedido — maximo de requisicoes por minuto atingido |
| 500 | TRANSACTION_FAILED | Erro interno ao processar transacao — abrir chamado de suporte |
Formato de Resposta
Todas as respostas sao JSON (Content-Type: application/json; charset=UTF-8) com a estrutura padrao abaixo.
Sucesso
{
"success": true,
"data": { ... },
"meta": {
"total": 100,
"page": 1,
"per_page": 50,
"last_page": 2
}
}
O campo meta so esta presente em endpoints paginados. Para endpoints que retornam um objeto unico, so data esta presente.
Erro
{
"success": false,
"error": {
"code": "INSUFFICIENT_STOCK",
"message": "Estoque insuficiente para o SKU CAMISETA-M."
}
}
Endpoints
5.1 Ping — testar autenticacao
Verifica se a API key e valida e retorna informacoes basicas da empresa autenticada.
curl -H "Authorization: Bearer lj_live_SEU_TOKEN" \
https://lojexa.com/api/v1/ping
{
"success": true,
"data": {
"status": "ok",
"company": "Loja da Maria",
"scopes": ["read:products", "write:sales"]
}
}
5.2 Listar produtos
Retorna a lista paginada de produtos com estoque, imagem principal, galeria, cores, tamanhos e a variacao correspondente ao SKU. Use include_variations=1 para carregar todas as variacoes do anuncio.
Parametros de query
| Parametro | Tipo | Padrao | Descricao |
|---|---|---|---|
page | integer | 1 | Pagina atual |
per_page | integer | 50 | Itens por pagina (max 100) |
search | string | — | Busca em nome e SKU |
category | string | — | Filtra por nome de categoria |
curl -H "Authorization: Bearer lj_live_SEU_TOKEN" \
"https://lojexa.com/api/v1/produtos?per_page=20&search=camiseta"
{
"success": true,
"data": [
{
"sku_code": "CAMISETA-M-AZUL",
"name": "Camiseta Basica Azul M",
"description": "100% algodao",
"category_name": "Camisetas",
"barcode": "7891234567890",
"cost_price": "29.90",
"sale_price": "49.90",
"stock_available": 15,
"stock_reserved": 2,
"unit": "un",
"image_url": "https://cdn.exemplo.com/camiseta.jpg",
"images": ["https://cdn.exemplo.com/camiseta.jpg"],
"colors": ["Azul"],
"sizes": ["M"],
"variation_count": 3,
"variation": {
"sku": "CAMISETA-M-AZUL",
"name": "Azul,M",
"price": 49.90,
"stock": 15,
"attributes": {"color": "Azul", "size": "M"}
}
}
],
"meta": {
"total": 142,
"page": 1,
"per_page": 50,
"last_page": 3
}
}
5.3 Detalhe de produto por SKU
Retorna os dados completos de um unico produto pelo sku_code.
Parametros de path
| Parametro | Descricao |
|---|---|
sku | sku_code exato do produto |
curl -H "Authorization: Bearer lj_live_SEU_TOKEN" \
https://lojexa.com/api/v1/produtos/CAMISETA-M-AZUL
HTTP 404 com "code": "NOT_FOUND" se o SKU nao existir no tenant.
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Produto nao encontrado."
}
}
5.4 Registrar venda
Registra uma venda, decrementa o estoque central e sincroniza automaticamente com Shopee, Mercado Livre e Amazon.
Campos do body (JSON)
| Campo | Tipo | Obrig. | Descricao |
|---|---|---|---|
reference | string | Sim | ID unico do pedido no seu sistema. Usado para idempotencia. |
items | array | Sim | Lista de itens (min 1, max 50) |
items[].sku | string | Sim | sku_code do produto |
items[].quantity | integer | Sim | Quantidade vendida (deve ser > 0) |
items[].unit_price | decimal | Nao | Preco unitario para fins de registro (nao afeta estoque) |
channel | string | Nao | Canal da venda. Padrao: "website" |
customer_name | string | Nao | Nome do cliente |
customer_email | string | Nao | E-mail do cliente |
reference for enviado novamente (ex: retry), a API retorna o resultado original sem processar a venda duas vezes. Trate o codigo 409 ALREADY_PROCESSED como sucesso.
curl -X POST \
-H "Authorization: Bearer lj_live_SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reference": "PEDIDO-123",
"channel": "website",
"customer_name": "Joao Silva",
"customer_email": "joao@email.com",
"items": [
{ "sku": "CAMISETA-M-AZUL", "quantity": 2, "unit_price": 49.90 }
]
}' \
https://lojexa.com/api/v1/vendas
{
"success": true,
"data": {
"sale_id": 456,
"reference": "PEDIDO-123",
"status": "confirmed",
"items_processed": [
{
"sku": "CAMISETA-M-AZUL",
"quantity": 2,
"stock_after": 13
}
]
}
}
5.5 Cancelar venda
Cancela uma venda registrada, restaura o estoque e re-sincroniza todos os canais.
Parametros de path
| Parametro | Descricao |
|---|---|
reference | O mesmo reference usado ao criar a venda |
curl -X POST \
-H "Authorization: Bearer lj_live_SEU_TOKEN" \
https://lojexa.com/api/v1/vendas/PEDIDO-123/cancelar
{
"success": true,
"data": {
"reference": "PEDIDO-123",
"status": "reversed"
}
}
5.6 Estatisticas de uso
Retorna estatisticas de uso da chave autenticada: vendas hoje, no mes, consumo de rate limit e configuracao de webhook. Requer autenticacao valida — funciona com qualquer escopo.
curl -H "Authorization: Bearer lj_live_SEU_TOKEN" \
https://lojexa.com/api/v1/uso
{
"success": true,
"data": {
"key_name": "Meu Site",
"key_prefix": "lj_live_xxxx",
"scopes": ["read:products", "write:sales"],
"rate_limit": {
"per_minute": 60,
"used": 3,
"remaining": 57
},
"usage": {
"sales_today": 12,
"sales_this_month": 287,
"reversed_this_month": 4,
"last_used_at": "2026-05-08T14:23:11"
},
"webhook_configured": true,
"expires_at": null
}
}
5.7 Ajuste de estoque
Registra uma entrada ("in") ou saida ("out") de estoque para um SKU. Apos o ajuste, o novo saldo e propagado automaticamente para Shopee, Mercado Livre e Amazon.
Parametros de path
| Parametro | Descricao |
|---|---|
sku | sku_code exato do produto |
Campos do body (JSON)
| Campo | Tipo | Obrig. | Descricao |
|---|---|---|---|
type | string | Sim | "in" = entrada de estoque / "out" = saida de estoque |
quantity | integer | Sim | Quantidade a ajustar (deve ser > 0) |
reason | string | Sim | Motivo do ajuste — max 255 caracteres (ex: "Compra NF 123", "Perda avaria") |
curl -X POST \
-H "Authorization: Bearer lj_live_SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "in",
"quantity": 10,
"reason": "Compra NF 123"
}' \
https://lojexa.com/api/v1/estoque/CAMISETA-M-AZUL/ajuste
{
"success": true,
"data": {
"sku_code": "CAMISETA-M-AZUL",
"type": "in",
"quantity": 10,
"stock_after": 25
}
}
GET /produtos/{sku} para consultar stock_available antes de registrar uma saida.
5.8 Listar mapeamentos SKU
Lista os mapeamentos entre SKUs centrais do LOJEXA e produtos em plataformas externas (Shopee, Mercado Livre, Amazon, etc). Esses mapeamentos sao usados para sincronizar estoque automaticamente.
Parametros de query
| Parametro | Tipo | Padrao | Descricao |
|---|---|---|---|
platform | string | — | Filtrar por plataforma: shopee, mercadolivre, amazon, api, fisica, outro |
sku | string | — | Filtrar por sku_code do SKU master |
page | integer | 1 | Pagina atual |
per_page | integer | 50 | Itens por pagina (max 100) |
curl -H "Authorization: Bearer lj_live_SEU_TOKEN" \
"https://lojexa.com/api/v1/mapeamentos?platform=shopee"
{
"success": true,
"data": [
{
"id": 17,
"platform": "shopee",
"platform_sku": "prod_001",
"platform_product_id": "12345",
"store_id": 3,
"quantity_factor": 1,
"master_sku": "CAMISETA-M-AZUL",
"master_name": "Camiseta Basica Azul M",
"stock_available": 23,
"created_at": "2026-05-01 10:00:00"
}
],
"meta": {
"current_page": 1,
"per_page": 50,
"total": 1,
"last_page": 1
}
}
5.9 Criar mapeamento SKU
Cria ou atualiza um mapeamento entre um SKU master e um produto em uma plataforma externa. Se ja existir um mapeamento com os mesmos sku_master_id + platform + platform_sku, ele sera atualizado (upsert).
Campos do body (JSON)
| Campo | Tipo | Obrig. | Descricao |
|---|---|---|---|
sku | string | Sim | sku_code do SKU master no LOJEXA |
platform | string | Sim | shopee, mercadolivre, amazon, shein, api, fisica, outro |
platform_sku | string | Sim | Codigo do produto na plataforma externa |
platform_product_id | string | Nao | ID do produto na plataforma (quando disponivel) |
store_id | integer | Nao | ID da loja (obrigatorio para Shopee/ML/Amazon com multiplas lojas) |
quantity_factor | integer | Nao | Fator de conversao de quantidade. Default: 1 |
curl -X POST \
-H "Authorization: Bearer lj_live_SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sku": "CAMISETA-M-AZUL",
"platform": "shopee",
"platform_sku": "prod_001",
"platform_product_id": "12345",
"store_id": 3,
"quantity_factor": 1
}' \
https://lojexa.com/api/v1/mapeamentos
{
"success": true,
"data": {
"id": 17,
"master_sku": "CAMISETA-M-AZUL",
"platform": "shopee",
"platform_sku": "prod_001",
"platform_product_id": "12345",
"store_id": 3,
"quantity_factor": 1
}
}
5.10 Remover mapeamento
Remove um mapeamento pelo ID. O LOJEXA valida que o mapeamento pertence a empresa autenticada (isolamento multi-tenant).
Parametros de path
| Parametro | Tipo | Descricao |
|---|---|---|
id | integer | ID do mapeamento (retornado em GET /mapeamentos ou POST /mapeamentos) |
curl -X DELETE \
-H "Authorization: Bearer lj_live_SEU_TOKEN" \
https://lojexa.com/api/v1/mapeamentos/17
{
"success": true,
"data": {
"deleted_id": 17
}
}
5.11 Especificacao OpenAPI
Retorna a especificacao completa da API no formato OpenAPI 3.0.3. Endpoint publico — nao requer autenticacao. Pode ser importado em ferramentas como Postman, Insomnia ou Swagger UI.
curl https://lojexa.com/api/v1/openapi.json
https://lojexa.com/api/v1/openapi.json diretamente no Postman (File → Import → URL) para gerar uma colecao completa de requests automaticamente.
Exemplos de Integracao
PHP — cURL nativo
<?php
$apiKey = 'lj_live_SUA_CHAVE_AQUI';
$baseUrl = 'https://lojexa.com/api/v1';
// Buscar produtos
$ch = curl_init("$baseUrl/produtos?per_page=100");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $apiKey",
'Accept: application/json',
],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
foreach ($response['data'] as $produto) {
echo "{$produto['name']}: {$produto['stock_available']} em estoque\n";
}
// Registrar venda
$venda = [
'reference' => 'PEDIDO-' . uniqid(),
'channel' => 'loja-virtual',
'items' => [
['sku' => 'CAMISETA-M-AZUL', 'quantity' => 2, 'unit_price' => 49.90],
],
];
$ch = curl_init("$baseUrl/vendas");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($venda),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $apiKey",
'Content-Type: application/json',
],
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
PHP — Guzzle
use GuzzleHttp\Client;
$client = new Client([
'base_uri' => 'https://lojexa.com/api/v1/',
'headers' => ['Authorization' => 'Bearer lj_live_SUA_CHAVE'],
]);
// Listar produtos
$response = $client->get('produtos', [
'query' => ['per_page' => 100, 'search' => 'camiseta'],
]);
$data = json_decode($response->getBody(), true);
// Registrar venda
$response = $client->post('vendas', [
'json' => [
'reference' => 'PEDIDO-123',
'items' => [
['sku' => 'CAMISETA-M', 'quantity' => 1, 'unit_price' => 49.90],
],
],
]);
$result = json_decode($response->getBody(), true);
JavaScript — fetch
const API_KEY = 'lj_live_SUA_CHAVE_AQUI';
const BASE_URL = 'https://lojexa.com/api/v1';
async function getProdutos(search = '') {
const url = new URL(`${BASE_URL}/produtos`);
if (search) url.searchParams.set('search', search);
url.searchParams.set('per_page', '100');
const res = await fetch(url.toString(), {
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Accept': 'application/json',
}
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
return data.data;
}
async function registrarVenda(pedidoId, itens) {
const res = await fetch(`${BASE_URL}/vendas`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
reference: pedidoId,
channel: 'website',
items: itens,
}),
});
const data = await res.json();
// 409 = ja processado, tratar como sucesso
if (!data.success && data.error?.code !== 'ALREADY_PROCESSED') {
throw new Error(data.error?.message || 'Erro desconhecido');
}
return data;
}
// Uso:
const produtos = await getProdutos('camiseta');
console.log(produtos);
const resultado = await registrarVenda('PEDIDO-001', [
{ sku: 'CAMISETA-M-AZUL', quantity: 2, unit_price: 49.90 }
]);
Python — requests
import requests
API_KEY = 'lj_live_SUA_CHAVE_AQUI'
BASE_URL = 'https://lojexa.com/api/v1'
HEADERS = {
'Authorization': f'Bearer {API_KEY}',
'Accept': 'application/json',
}
# Buscar todos os produtos
response = requests.get(
f'{BASE_URL}/produtos',
headers=HEADERS,
params={'per_page': 100},
)
response.raise_for_status()
produtos = response.json()['data']
for p in produtos:
print(f"{p['name']}: {p['stock_available']} unidades")
# Registrar venda
venda = requests.post(
f'{BASE_URL}/vendas',
headers=HEADERS,
json={
'reference': 'PEDIDO-123',
'channel': 'loja-virtual',
'items': [
{'sku': 'CAMISETA-M', 'quantity': 1, 'unit_price': 49.90}
],
},
)
print(venda.json())
Sincronizacao Automatica de Canais
Ao registrar ou cancelar uma venda via API, o LOJEXA atualiza automaticamente o estoque em todos os canais conectados:
POST /vendas
Estoque Central
- O estoque e decrementado/restaurado no estoque central imediatamente.
- A sincronizacao com Shopee, ML e Amazon acontece em segundo plano (fire-and-forget).
- Se um SKU nao tiver mapeamento em determinado canal, aquele canal e ignorado silenciosamente.
- Falhas de sincronizacao sao logadas internamente e nao propagam erro para a sua aplicacao.
Webhooks
Webhooks permitem que o LOJEXA notifique seu sistema automaticamente quando eventos relevantes ocorrem,
sem necessidade de polling. Ao registrar uma URL de webhook na API Key, o LOJEXA fara um
POST para esse endpoint sempre que um evento for disparado.
Eventos disponiveis
| Evento | Quando e disparado |
|---|---|
sale.confirmed |
Apos POST /api/v1/vendas ser processado com sucesso. O estoque ja foi decrementado. |
sale.reversed |
Apos POST /api/v1/vendas/{ref}/cancelar. O estoque ja foi restaurado. |
Estrutura do payload
{
"event": "sale.confirmed",
"company_id": 42,
"timestamp": "2026-05-08T14:30:00Z",
"data": {
"sale_id": 9934,
"reference": "PEDIDO-9934",
"status": "confirmed",
"items_processed": [
{ "sku": "CAMISETA-P", "quantity": 2, "stock_after": 13 }
]
}
}
Seguranca — verificar assinatura HMAC
Toda requisicao de webhook inclui o header X-Lojexa-Signature com o formato
sha256={hmac}. Sempre verifique essa assinatura antes de processar o evento
para garantir que a requisicao veio do LOJEXA.
<?php
$webhookSecret = $_ENV['LOJEXA_WEBHOOK_SECRET'];
$sig = $_SERVER['HTTP_X_LOJEXA_SIGNATURE'] ?? '';
$payload = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $payload, $webhookSecret);
// hash_equals() previne timing attacks
if (!hash_equals($expected, $sig)) {
http_response_code(401);
exit;
}
$event = json_decode($payload, true);
switch ($event['event']) {
case 'sale.confirmed':
// Venda confirmada — atualizar seu sistema
processarVenda($event['data']);
break;
case 'sale.reversed':
// Venda cancelada — reverter no seu sistema
reverterVenda($event['data']);
break;
}
http_response_code(200); // Sempre responder 200
Como configurar
- Acesse o painel em Configuracoes → API Keys
- Crie uma nova chave ou edite uma existente
- Preencha o campo Webhook URL com o endpoint HTTPS do seu sistema
- Opcionalmente informe um Webhook Secret — se deixar em branco, um secret sera gerado automaticamente
- O secret exibido na criacao nao sera mostrado novamente — salve-o como variavel de ambiente
Boas Praticas
-
Use um
referenceunico por pedido. Utilize o ID do pedido no seu sistema, um UUID (recomendado) ou qualquer string que identifique inequivocamente aquela transacao. -
Verifique estoque antes de confirmar ao cliente.
Consulte
GET /produtos/{sku}e verifiquestock_availableantes de exibir o botao "Comprar" ou confirmar o checkout. -
Trate
HTTP 409como sucesso. O codigoALREADY_PROCESSEDindica idempotencia — o pedido ja foi registrado. Nao tente processar novamente. - Implemente retry com backoff exponencial para erros 5xx. Erros 500 sao transitorios. Espere 1s, 2s, 4s antes de tentar novamente (maximo 3 tentativas).
- Armazene a API key em variaveis de ambiente. Nunca coloque a chave diretamente no codigo-fonte ou em repositorios Git.
- Use HTTPS em todas as requisicoes. Nao ha suporte para HTTP simples.
- Respeite os rate limits. Distribua as requisicoes ao longo do tempo. Para sincronizacoes em massa, use paginacao e adicione delay entre paginas.
Changelog
| Versao | Data | Mudancas |
|---|---|---|
| v1.1 | 2026-05-08 |
Novos recursos:GET /uso — estatisticas de uso da chave •
GET /openapi.json — especificacao OpenAPI 3.0 •
Webhooks: sale.confirmed, sale.reversed •
Campo webhook_url e webhook_secret nas API Keys
|
| v1.0 | Maio/2026 |
Lancamento da API publica:GET /ping •
GET /produtos •
GET /produtos/{sku} •
POST /vendas •
POST /vendas/{ref}/cancelar
|