Skip to main content

Errors, pagination and limits

Error bodies​

Every error is JSON, in one of these shapes.

Authentication, permission, not-found, conflict and rate-limit errors carry a human-readable detail, and sometimes a machine-readable code:

{"detail": "Authentication credentials were not provided."}

Match on the status code and on code when there is one; the messages are for people and can change.

Status codes​

StatusMeansWhat to do
200, 201Done; 201 when something was created
204Done, no body (a delete)
304Not modified: the ETag you sent in If-None-Match still holdsKeep the copy you have
400The request is invalid; nothing was changedFix the fields named in the body
401Missing, invalid, expired or revoked credential, or an API key on an endpoint that needs the dashboard's loginSee Authentication
402Not enough credits for a gateway callSee Credits
403The credential may not do this, for example a user without an organizationCheck which user the key belongs to with GET /key/context
404No such object in your organization, or a page past the end of a listCheck the id and the path
409The run is not in a state that allows the call: already finished, still active, or already claimedRead the run's status, then cancel it or wait
429Rate limitedWait the seconds in the Retry-After header, then retry
500, 502, 503, 504A server or upstream failureRetry later, with backoff

The reference lists, for each operation, the statuses it can answer and why.

Pagination​

List endpoints return one page at a time:

{
"count": 42,
"next": "https://api.hackagent.dev/agent?page=3",
"previous": "https://api.hackagent.dev/agent?page=1",
"results": []
}

count is the total across all pages, and next and previous are ready-to-use URLs, or null at either end. Ask for a page with page, starting at 1. Pages hold 10 items, except where an endpoint accepts page_size:

EndpointLargest page_size
GET /result, GET /run/{id}/goals1000
GET /run, GET /run/summary, GET /run/{id}/attempts100

A larger page_size is lowered to the largest. A page past the end gets 404 on most lists; the run report lists (/run/summary, /run/{id}/goals, /run/{id}/attempts) treat an invalid page as page 1 instead. A few endpoints return everything at once, such as GET /campaign/techniques and GET /run/{id}/matrix. To read every page, follow next until it is null; First request has a Python loop.

Rate limits​

Each user can make 1,000 requests an hour, shared by all of the user's API keys and dashboard sessions. Past that, requests get 429 with a Retry-After header saying how many seconds to wait. The run report reads (GET /run/summary and the /run/{id}/... reports) count against a separate, larger budget, so a live view that polls a run does not use up the main one.

Large campaigns that record their results from your machine make a request for every result and trace step, so they can reach the limit. To stay under it:

  • Poll GET /run/{id}/summary with If-None-Match, and read the heavier reports only when its revision moves.
  • Ask for larger pages where page_size is accepted, and leave out what you do not need (include_traces=false on GET /result, include_results=false on GET /run/{id}).
  • Launch on HackAgent cloud: a cloud run's requests count against its own budget, not yours.

Credits​

Only the LLM gateway is paid, from your organization's credit balance, and a cloud launch needs a minimum balance. Everything else in the API is free.