Skip to main content

hawkapi-pagination

Pagination helpers for HawkAPI. Offset and cursor strategies. Page[T] / CursorPage[T] response envelopes. SQLAlchemy integration. In-memory iterable pagination.

Install

pip install hawkapi-pagination
pip install 'hawkapi-pagination[sqlalchemy]'   # adds SQLAlchemy + hawkapi-sqlalchemy helpers

Offset pagination

from hawkapi import Depends, HawkAPI
from hawkapi_sqlalchemy import get_session
from hawkapi_pagination import Page, OffsetParams, pagination_params, paginate_query
from sqlalchemy import select


@app.get("/items")
async def list_items(
    params: OffsetParams = Depends(pagination_params),
    session = Depends(get_session),
) -> Page[Item]:
    return await paginate_query(session, select(Item), params)

The route accepts ?page=N&size=M. Defaults: page=1, size=50, max_size=200. Out-of-range values are clamped (size > max_size → max_size) or rejected (page < 1 raises 400).

Page[T] shape:

{ "items": [...], "total": 137, "page": 1, "size": 50, "pages": 3 }

Skipping the COUNT

For large tables where SELECT COUNT(*) is expensive:

page = await paginate_query(session, stmt, params, include_total=False)
# page.total == -1, page.pages == -1

Clients can detect "more pages" by comparing len(items) to size.

Cursor pagination

Cursor pagination is the right choice for large tables that change under you (offset pages skip/duplicate rows when items are inserted/deleted between requests). The cursor is an HMAC-signed opaque token bound to:

  • the endpoint path (replay across routes rejected),
  • a TTL (default 1 hour),
  • a direction (asc / desc).
from hawkapi_pagination import CursorPage, CursorParams, cursor_params, paginate_cursor


@app.get("/items")
async def list_items(
    params: CursorParams = Depends(cursor_params),
    session = Depends(get_session),
) -> CursorPage[Item]:
    return await paginate_cursor(
        session,
        select(Item),
        order_by=Item.id,         # MUST be unique + sortable (PK is the usual choice)
        params=params,
        cursor_secret="stable secret, ≥32 chars",
        endpoint="/items",
        direction="asc",
    )

CursorPage[T] shape:

{ "items": [...], "next_cursor": "eyJrI...", "prev_cursor": "" }

When next_cursor is "", there are no more pages. Send the cursor back as ?cursor=... for the next call.

In-memory iterables

from hawkapi_pagination import paginate_iterable


page = await paginate_iterable(some_list, params)
# Works with sync iterables AND async generators.

Security notes

  • Cursor signing — HMAC-SHA256 over the JSON payload + hmac.compare_digest for verification.
  • Endpoint binding — a cursor minted for /api/items cannot be used at /api/users. Always pass an endpoint string that is stable across requests for the same route.
  • TTL — default 1 hour. Override per route via ttl= to paginate_cursor.
  • max_size cap — every params class enforces it; clients cannot ask for an unbounded page. Default 200.
  • Negative-int guard — page < 1 and size < 1 raise ValueError (which HawkAPI surfaces as 400).

Development

git clone https://github.com/Hawk-API/hawkapi-pagination.git
cd hawkapi-pagination
uv sync --extra dev
uv run pytest -q
uv run ruff check . && uv run ruff format --check .
uv run pyright src/

License

MIT.

Metadata

Release files for hawkapi-pagination 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hawkapi-pagination 0.1.2
File Size Uploaded
hawkapi_pagination-0.1.2.tar.gz 35.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hawkapi-pagination 0.1.2
File Interpreter ABI Platform
hawkapi_pagination-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 46.0 kB

Release files / hawkapi_pagination-0.1.2.tar.gz

Download URL hawkapi_pagination-0.1.2.tar.gz
Size 35.4 kB
Tags Source
SHA-256 checksum
How to use checksums
b54b29a1c55b8f889ee33b369571d8b20917643476d3549b9545aa8fe7737224
BLAKE2b-256 checksum
How to use checksums
5bf896ffb43a1678ec7275f627ae755dc59b322a82af1e24e537e4dc3563e02e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.

Transparency log

Release files / hawkapi_pagination-0.1.2-py3-none-any.whl

Download URL hawkapi_pagination-0.1.2-py3-none-any.whl
Size 10.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7e11f4018e5f8913eab19580d8973475de8dd065fdcf8c323b39bfb5a894486d
BLAKE2b-256 checksum
How to use checksums
6152dd0c76614e38a047d2c6a72dab027872382e8a6b004738a207064646810a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page