# Erros > O formato dos erros, cada status e código que a API responde, quais erros tentar de novo e um tratador de erros em Node pronto para copiar. Quando uma requisição falha, a API responde com um status 4xx ou 5xx e um corpo JSON com um `code` estável. Tome decisões com base em `code`. O texto de `error` é para pessoas e pode mudar. ## O formato ```json { "error": "This API key doesn't have the earnings:read scope.", "code": "insufficient_scope", "scope": "earnings:read" } ``` | Campo | Sempre | Significado | | --- | --- | --- | | `error` | Sim | O que deu errado, por extenso. Pode ser registrado em log ou mostrado a um operador. | | `code` | Sim | Um código estável. Veja as tabelas abaixo. | | `field` | Com `invalid` | O parâmetro ou campo do corpo com problema. | | `scope` | Com `insufficient_scope` | O escopo de que a chave precisa. | Alguns erros acrescentam campos próprios. Por exemplo, `409 upload_incomplete` lista as partes em `missing` e `wrong_size`. ## Erros que qualquer endpoint pode responder | Status | `code` | Significado | Tentar de novo? | | --- | --- | --- | --- | | 400 | `invalid` | Um parâmetro está errado. `field` indica qual. | Não. Corrija a requisição. | | 401 | `unauthenticated` | Falta o header `Authorization: Bearer`. | Não | | 401 | `invalid_key` | A chave não existe. | Não | | 401 | `key_revoked` | A chave foi revogada. Crie uma nova. | Não | | 401 | `key_expired` | A chave expirou. Crie uma nova. | Não | | 401 | `test_keys_retired` | Uma chave `hm_test_`. Desativada em 12 de outubro de 2026. Use uma chave `hm_live_`. | Não | | 403 | `insufficient_scope` | Falta à chave o escopo exigido por este endpoint. `scope` indica qual. | Não | | 403 | `account_inactive` | Sua conta não está ativa. | Não | | 403 | `api_not_in_plan` | Seu plano não inclui a API. Ela vem com o Enterprise e o Custom. | Não | | 404 | `not_found` | Esse endpoint não existe, ou o recurso não é seu. | Não | | 429 | `rate_limited` | Acima do seu limite por minuto nesta chave. | Sim, após `Retry-After` segundos | | 500 | `server_error` | Algo deu errado do nosso lado. | Sim, com backoff | `404 not_found` cobre tanto "não existe" quanto "pertence a outra conta". A API nunca revela que o lançamento de outra pessoa existe. ## Erros de endpoints específicos | Status | `code` | Onde | Significado | | --- | --- | --- | --- | | 409 | `exists` | `POST /members/invite` | Já existe uma conta com este e-mail. | | 413 | `too_large` | `POST /ddex/validate` | Maior do que um teste aceita. Entregue-o com `POST /ddex`. | | 413 | `too_large` | `POST /ddex` | Acima de 20 GB (corpo bruto) ou 512 MB (multipart). Use um upload direto. | | 429 | `busy` | `POST /ddex/validate` | Testes demais ao mesmo tempo. Tente de novo em instantes. | | 409 | `upload_incomplete` | `POST /ddex/uploads/{id}/commit` | Partes ausentes ou com tamanho errado. Envie-as e confirme de novo. | | 409 | `already_committed` | Uploads diretos | Já confirmado antes. `status_url` aponta para a entrega. | | 409 | `commit_in_progress` | `POST /ddex/uploads/{id}/commit` | Outra confirmação deste upload está em andamento. | | 400 | `invalid_url` | `POST /webhooks`, `PATCH /webhooks/{id}` | Não é uma URL https pública na porta 443. | | 409 | `too_many` | `POST /webhooks` | Você já tem 20 endpoints. | | 409 | `endpoint_disabled` | Teste e reenvio de webhook | O endpoint está desativado. Ative-o primeiro. | Cada [página da referência](https://developer.hillsmusic.com/pt/reference/releases/) lista os erros de cada endpoint. [Escopos e erros](https://developer.hillsmusic.com/pt/reference/scopes-and-errors/) reúne os comuns a todos. ## Erros de validação Um `400 invalid` indica o primeiro problema encontrado: ```json { "error": "updated_since is an ISO date or time.", "code": "invalid", "field": "updated_since" } ``` Apenas um campo é informado por vez. Corrija-o e envie de novo. Se você construir um formulário sobre a API, mostre `error` ao lado do campo indicado por `field`. Com arquivos DDEX é diferente. Um lote DDEX com problemas não gera `400`. O teste responde `200` com todas as verificações e um veredito, e uma entrega responde `202` e informa os problemas por lançamento. Veja [Entrega DDEX](https://developer.hillsmusic.com/pt/guides/ddex/). ## O que tentar de novo - **Tente de novo** em caso de `429` e `5xx`, e de erros de rede como timeouts e conexões resetadas. - **Não tente de novo** os outros `4xx`. A mesma requisição recebe a mesma resposta. Corrija antes a requisição, a chave ou os escopos dela. Para `429`, aguarde o número de segundos de `Retry-After`. Para `5xx`, espere mais a cada tentativa (1 s, 2 s, 4 s…) e desista depois de algumas. Veja [Limites de requisições](https://developer.hillsmusic.com/pt/guides/rate-limits/). Leituras podem ser repetidas com segurança. Pense antes de repetir uma escrita. Um `POST /ddex` repetido depois de uma resposta perdida pode colocar o lote na fila duas vezes. Confira antes em `GET /ddex`. ## Um tratador de erros em Node ```js export class HillsError extends Error { constructor(status, body, headers) { super(body.error ?? `HTTP ${status}`); this.status = status; this.code = body.code; this.field = body.field; this.scope = body.scope; this.retryAfter = Number(headers.get("Retry-After")) || null; } } const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); export async function hills(path, init = {}, tries = 4) { for (let i = 1; ; i++) { const res = await fetch("https://api.hillsmusic.com/v1" + path, { ...init, headers: { ...init.headers, Authorization: `Bearer ${process.env.HILLS_API_KEY}` }, }); const body = await res.json().catch(() => ({})); if (res.ok) return body; const err = new HillsError(res.status, body, res.headers); const retryable = res.status === 429 || res.status >= 500; if (!retryable || i >= tries) throw err; await sleep(err.retryAfter ? err.retryAfter * 1000 : 1000 * 2 ** (i - 1)); } } try { await hills("/earnings"); } catch (err) { if (err.code === "insufficient_scope") console.error(`Add ${err.scope} to this key.`); else if (err.code === "api_not_in_plan") console.error("The plan doesn't include the API."); else throw err; } ``` Com curl, adicione `-w '%{http_code}'` para ver o status, ou `-i` para ver os headers: ```bash curl -i "https://api.hillsmusic.com/v1/releases/999999" \ -H "Authorization: Bearer $HILLS_API_KEY" # HTTP/2 404 # {"error":"…","code":"not_found"} ``` Fonte: https://developer.hillsmusic.com/pt/guides/errors/