Skip to main content

📦 PyAPIq

PyPI Python Versions License

PyAPIq is a modern Python toolkit for building both synchronous and asynchronous API clients with clean, minimal code and full type safety.

Define endpoints using decorators like @sync_endpoint or @async_endpoint, structure logic with optional namespaces, and leverage Pydantic models for strict request/response validation — all with built-in rate limiting and retries.

Downloads Downloads Downloads

Installation

pip install pyapiq

Quickstart

1. Define your models

Use Pydantic to define request and response schemas with full type safety:

from typing import List
from pydantic import BaseModel


class BulkAccountsRequest(BaseModel):
    account_ids: List[str]


class AccountInfoResponse(BaseModel):
    address: str
    balance: int
    status: str


class BulkAccountsResponse(BaseModel):
    accounts: List[AccountInfoResponse]

2. Define your client

Declare your API client by subclassing AsyncClientAPI and annotating endpoints with @async_endpoint:

from pyapiq import AsyncClientAPI, async_endpoint
from pyapiq.types import HTTPMethod


class AsyncTONAPI(AsyncClientAPI):
    base_url = "https://tonapi.io"
    headers = {"Authorization": "Bearer <YOUR_API_KEY>"}
    version = "v2"
    rps = 1
    max_retries = 2

    @async_endpoint(HTTPMethod.GET)
    async def status(self) -> dict:
        """Check API status (GET /status)"""

    @async_endpoint(HTTPMethod.GET)
    async def rates(self, tokens: str, currencies: str) -> dict:
        """Get token rates (GET /rates?tokens={tokens}&currencies={currencies})"""

Notes:

  • If you prefer synchronous clients, simply use SyncClientAPI with @sync_endpoint instead.
  • For synchronous clients, use SyncClientAPI and @sync_endpoint — interface is fully symmetrical.
  • Method arguments are automatically mapped to path and query parameters. The return value is parsed from JSON and returned as a dict, unless a return_as=Model is specified.

3. Group endpoints with namespaces (optional)

Use AsyncAPINamespace to logically organize endpoints under a common prefix (e.g., /accounts):

from pyapiq import AsyncAPINamespace, async_endpoint
from pyapiq.types import HTTPMethod


class Accounts(AsyncAPINamespace):
    namespace = "accounts"

    @async_endpoint(HTTPMethod.GET, path="/{account_id}", return_as=AccountInfoResponse)
    async def info(self, account_id: str) -> AccountInfoResponse:
        """Retrieve account information by account_id (GET /accounts/{account_id})"""

    @async_endpoint(HTTPMethod.POST, path="/_bulk", return_as=BulkAccountsResponse)
    async def bulk_info(self, payload: BulkAccountsRequest) -> BulkAccountsResponse:
        """Retrieve info for multiple accounts with a Pydantic model (POST /accounts/_bulk)"""

    @async_endpoint(HTTPMethod.POST, path="/_bulk")
    async def bulk_info_dict(self, payload: dict) -> dict:
        """Retrieve info for multiple accounts with a dict payload (POST /accounts/_bulk)"""

Then include the namespace in your main client:

class AsyncTONAPI(AsyncClientAPI):
    base_url = "https://tonapi.io"
    headers = {"Authorization": "Bearer <YOUR_API_KEY>"}
    version = "v2"
    rps = 1
    max_retries = 2

    # ... endpoints above ...

    @property
    def accounts(self) -> Accounts:
        return Accounts(self)

Note: The namespace can be defined with or without a leading slash. It will be joined correctly with endpoint paths. Each namespace instance receives the parent client instance automatically.

4. Usage

async def main():
    tonapi = AsyncTONAPI()

    async with tonapi:
        # GET /status
        status = await tonapi.status()
        print(status)

Note: Always use async with to open and close the session properly. All retries, throttling, and connection reuse are handled under the hood.

API Configuration

All settings are defined as class attributes on your client class:

Name Type Description Default
base_url str Base URL of the API (must start with http:// or https://) —
version str Optional API version prefix (e.g. "v1" → /v1/... in requests) None
rps int Max requests per second (client-side rate limit) 1
max_retries int Max automatic retries for HTTP 429 (Too Many Requests) 3
headers dict Default headers to send with each request None
cookies dict Default cookies to send with each request None
timeout float Default request timeout in seconds None

Note: The version field is automatically prefixed to all endpoint paths (e.g. /v2/accounts/...). Rate limiting and retries are handled transparently and apply only per-client instance.

Endpoints

  • Use @async_endpoint(method, path=..., return_as=...) to declare each endpoint.

  • All method arguments are automatically mapped:

    • Scalars → query/path parameters
    • dict or Pydantic models → request body
  • return_as=Model lets you parse responses into Pydantic models.

  • If omitted, response is returned as dict.

Note: If path is omitted, the method name becomes the endpoint path (e.g. rates → /rates). You can define both flat and namespaced methods together.

Notes

  • Fully asynchronous: all clients and endpoints require async with.
  • Zero boilerplate: request building, error handling, retries, and throttling are automatic.
  • Namespaces help organize large APIs, but are optional.
  • Both dicts and Pydantic models are supported in request payloads.
  • Great for building typed SDKs or internal tools.

Contribution

We welcome your contributions! If you find a bug or have an idea, please open an issue or submit a pull request.

License

Distributed under the MIT License. Use freely for commercial or personal projects.

Metadata

Release files for pyapiq 0.2.1

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

Source distribution (sdist)

Source distribution for pyapiq 0.2.1
File Size Uploaded Provenance
pyapiq-0.2.1.tar.gz 16.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pyapiq 0.2.1
File Interpreter ABI Platform
pyapiq-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 35.7 kB

Release files / pyapiq-0.2.1.tar.gz

Download URL pyapiq-0.2.1.tar.gz
Size 16.1 kB
Tags Source
SHA-256 checksum
How to use checksums
c210a97c6fd6e4bac5279989e68c2ac6906db193b14aca29cb39457d26814fef
BLAKE2b-256 checksum
How to use checksums
c2bac465fd5c35fc3a07de086b74a38dd3f1db254a1d9a8c5e0dabd06659b695
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.10.11

Release files / pyapiq-0.2.1-py3-none-any.whl

Download URL pyapiq-0.2.1-py3-none-any.whl
Size 19.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
36f80bd3684ba091102fe90900de9de1e8d639b7cef5808106a01cfe4baffad3
BLAKE2b-256 checksum
How to use checksums
c55ba2e3e37607c4f8d80accfbf4481df35bd7d73c655c2afcf407a1bdecf478
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.10.11

Security for pyapiq 0.2.1

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

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