Formato de erro, códigos e estratégias de tratamento.
Erros seguem o formato GraphQL padrão:
{
"data": null,
"errors": [
{
"message": "Invalid API token",
"code": "UNAUTHORIZED"
}
]
} | Código | HTTP Status | Descrição |
|---|---|---|
UNAUTHORIZED | 401 | Token ausente, inválido ou revogado. |
FORBIDDEN | 403 | Token não possui a permissão necessária para a operação. |
NOT_FOUND | 200 | Recurso não encontrado (retornado no body GraphQL). |
BAD_REQUEST | 200 | Dados de entrada inválidos ou query malformada. |
RATE_LIMIT_EXCEEDED | 429 | Limite de requisições por minuto excedido. |
INTERNAL_ERROR | 500 | Erro interno do servidor. |
INVALID_TOKEN | 200 | Token não está associado a uma loja válida. |
async function officeApi(query, variables = {}) {
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${TOKEN}`
},
body: JSON.stringify({ query, variables })
});
if (response.status === 401) {
throw new Error('Token inválido ou expirado. Verifique suas credenciais.');
}
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || '60';
throw new Error(`Rate limit excedido. Tente novamente em ${retryAfter}s.`);
}
const result = await response.json();
if (result.errors?.length) {
const error = result.errors[0];
throw new Error(`[${error.code}] ${error.message}`);
}
return result.data;
} Para operações em massa, implemente retry com backoff exponencial:
async function withRetry(fn, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
const isRetryable = error.message.includes('RATE_LIMIT')
|| error.message.includes('INTERNAL_ERROR');
if (!isRetryable || attempt === maxRetries - 1) {
throw error;
}
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}