Skip to content

Troubleshooting

Error handling

HTTP status codes, the flat `_error` format and recommended retry strategies.

The QUiCK API answers with predictable HTTP status codes and a simple, flat error object.

Error response shape

Every error response uses the same shape — a single _error text field:

json
{
  "_error": "Authentication credentials were not provided."
}

There is no error-code field and no per-field error list. The message is meant for humans: always branch your code on the HTTP status code, never on the contents of the text.

Status codes

CodeMeaningWhat to do
400Bad request or validation errorFix the parameters or the body — do not retry unchanged
401Missing or invalid tokenCheck the Authorization: Token <token> header
403No permission, or Quick-Company-Id is not the token's companyVerify permissions and company scope
404Resource not foundCheck the identifier and the trailing / in the URL
429Too many requestsWait, then retry with exponential backoff
5xxServer-side errorExponential backoff, a few attempts at most

Common pitfalls

401 with a token that looks right

The most frequent cause is the wrong prefix: QUiCK expects Token (Authorization: Token abc123), not Bearer. A quote or newline left over from an .env loader at the end of the token is the second most common cause.

404 for a resource that exists

Endpoints are valid with a trailing slash: /1/expenses/, not /1/expenses. The slash-less form may redirect or return 404, and on a POST the request body can be lost in the process.

If you get a 403 on a call that used to work, check whether you are sending a Quick-Company-Id header unnecessarily: if its value is not the token's company, the API rejects the request.

  1. On 4xx errors, fix the request — retrying it unchanged produces the same result.
  2. On 429, slow down: use exponential backoff, and honour the Retry-After header if the response carries one. Persistent 429s call for less frequent polling and a larger page_size, not more retries.
  3. On 5xx, retry with exponential backoff and an upper bound.
  4. Log the status code, the endpoint and the _error text on every failure — it is the fastest route to support.

Handling errors in the client

Convert the response into a typed error in one place:

ts
export class QuickApiError extends Error {
  constructor(public status: number, message: string) {
    super(message);
    this.name = "QuickApiError";
  }
}

export async function quickFetch(path: string, init: RequestInit = {}) {
  const res = await fetch(`https://api.quick.riport.co.hu${path}`, {
    ...init,
    headers: {
      ...init.headers,
      Authorization: `Token ${process.env.QUICK_API_TOKEN}`,
    },
  });

  if (!res.ok) {
    const body = await res.json().catch(() => ({}));
    throw new QuickApiError(res.status, body._error ?? res.statusText);
  }
  return res.json();
}

For a step-by-step version, see the Handling error responses recipe.