Pular para o conteúdo
HILLS API v1 Acesso antecipado

Guias

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.

Atualizado em

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

{
  "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 lista os erros de cada endpoint. Escopos e erros reúne os comuns a todos.

Erros de validação

Um 400 invalid indica o primeiro problema encontrado:

{
  "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.

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.

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

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:

curl -i "https://api.hillsmusic.com/v1/releases/999999" \
  -H "Authorization: Bearer $HILLS_API_KEY"
# HTTP/2 404
# {"error":"…","code":"not_found"}

Pronto para integrar?

Solicite acesso à API e retornamos em 1 a 3 dias úteis.