Errors & pagination

Handle the SDK's typed exception hierarchy, understand automatic retries, and page through list responses.

The SDK turns HTTP failures into a small hierarchy of typed exceptions and pages list responses with a predictable shape. Both behave identically on the synchronous and asynchronous clients.

The exception hierarchy

Every error raised by the SDK derives from RankError. API responses with a non-2xx status become an APIError subclass chosen by status code; transport problems become APIConnectionError (or its subclass APITimeoutError).

RankError
├── APIError
│   ├── AuthenticationError    (401)
│   ├── PermissionDeniedError  (403)
│   ├── NotFoundError          (404)
│   ├── ConflictError          (409)
│   ├── UnprocessableEntityError (422)
│   ├── RateLimitError         (429)
│   └── InternalServerError    (5xx)
├── APIConnectionError
└── APITimeoutError

All of these are importable directly from rank (for example rank.NotFoundError).

APIError attributes

Any APIError carries the full context of the failed request:

AttributeTypeDescription
messagestrHuman-readable error description.
status_codeintHTTP status code.
bodyAnyParsed response body (JSON when available, otherwise the raw string).
requesthttpx.RequestThe request that failed.
responsehttpx.ResponseThe response received.

RateLimitError additionally exposes retry_after — the value of the Retry-After header in seconds, or None if the server did not send one.

Handling errors

Catch the specific subclass you care about, and fall back to the broader APIError for anything else. Because the subclasses are ordered from specific to general, list the narrow ones first.

Automatic retries

The client automatically retries transient failures — network errors, timeouts and 5xx responses — up to max_retries times (default 2). Once the retries are exhausted, the final error is raised as one of the exceptions above.

Client errors in the 4xx range (validation, not found, permission denied, …) are not retried, because retrying them would never succeed; they are raised immediately. Tune the behaviour per client:

import rank

# Retry network/5xx failures up to 4 times
client = rank.Rank(max_retries=4)

# Disable retries entirely
client = rank.Rank(max_retries=0)

See Client setup for the related timeout option.

Pagination

List methods accept page and per_page keyword arguments and return a response object with two parts: items, the records on the current page, and pagination, the metadata describing where you are in the result set.

import rank

with rank.Rank() as client:
    response = client.pentests.list(page=1, per_page=20)

    for p in response.items:
        print(p.id, p.name)

    meta = response.pagination
    print(f"Page {meta.current_page} of {meta.total_pages}{meta.total} total")

Pagination metadata

The pagination object exposes these fields:

FieldDescription
current_pageThe page you just fetched.
total_pagesTotal number of pages available.
per_pageItems requested per page.
totalTotal number of records across all pages.
countNumber of records on the current page.

Iterating every page

To walk the whole result set, request pages until current_page reaches total_pages:

import rank

with rank.Rank() as client:
    page = 1
    while True:
        response = client.pentests.list(page=page, per_page=50)
        for p in response.items:
            print(p.id, p.name)

        if response.pagination.current_page >= response.pagination.total_pages:
            break
        page += 1

Auto-paging helpers

For convenience, the SDK also ships page helpers — SyncPage and AsyncPage (in rank._utils._pagination) — that wrap a page of results and expose:

  • has_next_page() — whether another page exists.
  • next_page() — fetch the next page (await it on AsyncPage).
  • auto_paging_iter() — iterate over every item across all pages, fetching as it goes.
# Iterate all items without managing page numbers yourself
for item in page.auto_paging_iter():
    print(item)

With errors and pagination handled, revisit the Resources tour for the full set of list endpoints, or build something end-to-end from the Cookbook.