Primeiros passos
Do token à primeira resposta em cinco minutos.
1. Tenha um token em mãos
Quem cria o token é o parceiro, no painel dele, em Integrações → Nova integração. Ele escolhe o nome, as permissões e a validade, e recebe o token uma única vez. O passo a passo com as telas está em Para o parceiro: criar uma integração.
O token começa com otl_prod_…otl_sbx_…. Use o seletor Produção / Sandbox no topo desta página
para ver os exemplos no ambiente em que você está trabalhando.
Para começar, peça ao parceiro um token de sandbox. O catálogo é o mesmo, e você pode errar à vontade.
2. Confirme que o token funciona
A primeira chamada de toda integração é o /v1/eu: ela não exige permissão nenhuma e mostra o que
o seu token pode fazer.
curl "https://api.otlshoes.com.br/v1/eu" \
-H "Authorization: Bearer otl_prod_SEU_TOKEN"curl "https://api-sandbox.otlshoes.com.br/v1/eu" \
-H "Authorization: Bearer otl_sbx_SEU_TOKEN"const resposta = await fetch('https://api.otlshoes.com.br/v1/eu', {
headers: {
Authorization: 'Bearer otl_prod_SEU_TOKEN',
},
});
if (!resposta.ok) {
const { erro } = await resposta.json();
throw new Error(`${erro.codigo}: ${erro.mensagem} (${erro.requestId})`);
}
const dados = await resposta.json();const resposta = await fetch('https://api-sandbox.otlshoes.com.br/v1/eu', {
headers: {
Authorization: 'Bearer otl_sbx_SEU_TOKEN',
},
});
if (!resposta.ok) {
const { erro } = await resposta.json();
throw new Error(`${erro.codigo}: ${erro.mensagem} (${erro.requestId})`);
}
const dados = await resposta.json();<?php
$ch = curl_init('https://api.otlshoes.com.br/v1/eu');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer otl_prod_SEU_TOKEN',
]);
$corpo = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 400) {
throw new Exception($corpo['erro']['codigo'] . ': ' . $corpo['erro']['mensagem']);
}<?php
$ch = curl_init('https://api-sandbox.otlshoes.com.br/v1/eu');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer otl_sbx_SEU_TOKEN',
]);
$corpo = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 400) {
throw new Exception($corpo['erro']['codigo'] . ': ' . $corpo['erro']['mensagem']);
}import requests
resposta = requests.get(
"https://api.otlshoes.com.br/v1/eu",
headers={
"Authorization": "Bearer otl_prod_SEU_TOKEN",
},
timeout=30,
)
if not resposta.ok:
erro = resposta.json()["erro"]
raise RuntimeError(f'{erro["codigo"]}: {erro["mensagem"]} ({erro["requestId"]})')
dados = resposta.json()import requests
resposta = requests.get(
"https://api-sandbox.otlshoes.com.br/v1/eu",
headers={
"Authorization": "Bearer otl_sbx_SEU_TOKEN",
},
timeout=30,
)
if not resposta.ok:
erro = resposta.json()["erro"]
raise RuntimeError(f'{erro["codigo"]}: {erro["mensagem"]} ({erro["requestId"]})')
dados = resposta.json()Testar agora no ambiente de testes
A chamada é feita de verdade, do seu navegador para a API de testes (https://api-sandbox.otlshoes.com.br/v1). Use um token otl_sbx_…: ele fica só nesta aba, e some ao fechá-la. Token de produção não é aceito aqui.
Resposta:
{
"parceiro": {
"nome": "Loja do João",
"loja": "João Calçados"
},
"integracao": {
"id": "cmuq5txm9000510arvq62c497",
"nome": "Bling – João Dev",
"criadaEm": "2026-10-01T20:23:15-03:00",
"expiraEm": "2026-10-31T20:23:15-03:00"
},
"permissoes": [
"conta:ler",
"produtos:ler"
],
"limite": {
"porMinuto": 60,
"restante": 59
},
"ambiente": "producao"
}
Confira três coisas:
ambienteé o que você esperava;permissoestem o que a sua integração vai usar — se faltar algo, o parceiro edita a integração;integracao.expiraEm— se houver data, anote: depois dela o token para de funcionar.
3. Busque o catálogo
curl "https://api.otlshoes.com.br/v1/produtos?limite=50" \
-H "Authorization: Bearer otl_prod_SEU_TOKEN"curl "https://api-sandbox.otlshoes.com.br/v1/produtos?limite=50" \
-H "Authorization: Bearer otl_sbx_SEU_TOKEN"const resposta = await fetch('https://api.otlshoes.com.br/v1/produtos?limite=50', {
headers: {
Authorization: 'Bearer otl_prod_SEU_TOKEN',
},
});
if (!resposta.ok) {
const { erro } = await resposta.json();
throw new Error(`${erro.codigo}: ${erro.mensagem} (${erro.requestId})`);
}
const dados = await resposta.json();const resposta = await fetch('https://api-sandbox.otlshoes.com.br/v1/produtos?limite=50', {
headers: {
Authorization: 'Bearer otl_sbx_SEU_TOKEN',
},
});
if (!resposta.ok) {
const { erro } = await resposta.json();
throw new Error(`${erro.codigo}: ${erro.mensagem} (${erro.requestId})`);
}
const dados = await resposta.json();<?php
$ch = curl_init('https://api.otlshoes.com.br/v1/produtos?limite=50');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer otl_prod_SEU_TOKEN',
]);
$corpo = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 400) {
throw new Exception($corpo['erro']['codigo'] . ': ' . $corpo['erro']['mensagem']);
}<?php
$ch = curl_init('https://api-sandbox.otlshoes.com.br/v1/produtos?limite=50');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer otl_sbx_SEU_TOKEN',
]);
$corpo = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status >= 400) {
throw new Exception($corpo['erro']['codigo'] . ': ' . $corpo['erro']['mensagem']);
}import requests
resposta = requests.get(
"https://api.otlshoes.com.br/v1/produtos",
headers={
"Authorization": "Bearer otl_prod_SEU_TOKEN",
},
params={
"limite": 50
},
timeout=30,
)
if not resposta.ok:
erro = resposta.json()["erro"]
raise RuntimeError(f'{erro["codigo"]}: {erro["mensagem"]} ({erro["requestId"]})')
dados = resposta.json()import requests
resposta = requests.get(
"https://api-sandbox.otlshoes.com.br/v1/produtos",
headers={
"Authorization": "Bearer otl_sbx_SEU_TOKEN",
},
params={
"limite": 50
},
timeout=30,
)
if not resposta.ok:
erro = resposta.json()["erro"]
raise RuntimeError(f'{erro["codigo"]}: {erro["mensagem"]} ({erro["requestId"]})')
dados = resposta.json()Testar agora no ambiente de testes
A chamada é feita de verdade, do seu navegador para a API de testes (https://api-sandbox.otlshoes.com.br/v1). Use um token otl_sbx_…: ele fica só nesta aba, e some ao fechá-la. Token de produção não é aceito aqui.
A resposta traz até 50 produtos em dados e, em paginacao.proximoCursor, o que mandar na próxima
chamada para continuar. Quando temMais for false, você chegou ao fim. O detalhe está em
Listar produtos, e a receita completa em
Sincronizar catálogo e estoque.
4. Trate os erros pelo código
Toda resposta de erro tem o mesmo formato:
{
"erro": {
"codigo": "ESCOPO_INSUFICIENTE",
"mensagem": "Esta integração não tem a permissão pedidos:ler.",
"escopoNecessario": "pedidos:ler",
"detalhes": [],
"requestId": "req_87da1622e9de4dd9b63e6cb2",
"doc": "https://docs.otlshoes.com.br/erros#ESCOPO_INSUFICIENTE"
}
}
O seu sistema deve decidir o que fazer pelo campo codigo, que é estável — a mensagem pode mudar.
A lista está em Erros. Guarde o requestId no seu log: é com ele que a equipe OTL
localiza a chamada.
Próximos passos
- Usando o token e Segurança
- Conceitos: dinheiro, datas, paginação, limite de chamadas
- Boas práticas: o que a OTL confere antes de liberar a produção
