Skip to main content

Portals API Python client

A typed synchronous and asynchronous Python client for the Portals Partners API, the partner-facing programmatic API of the Portals marketplace.

Features

  • All 35 operations from the Portals Partners OpenAPI contract
  • Matching PortalsClient and AsyncPortalsClient APIs
  • Typed Pydantic v2 models for every schema in the contract (strict requests, forward-compatible responses)
  • httpx2 connection pooling and injectable HTTP clients
  • Exact Decimal amounts and parsed datetime timestamps
  • Typed API errors and rate-limit metadata
  • Python 3.11+ and a py.typed marker

Installation

pip install portals-api

Or with uv:

uv add portals-api

From a local checkout:

pip install .

The distribution is named portals-api; the import package is portals.

Quickstart

Synchronous

from portals import PortalsClient

with PortalsClient("your-api-key") as client:
    config = client.market.config()
    wallet = client.wallet.get()
    results = client.nfts.search(max_price="20", limit=20)

    print(config.deposit_wallet)
    print(wallet.balance)
    print(results.total_count)

Asynchronous

import asyncio

from portals import AsyncPortalsClient


async def main() -> None:
    async with AsyncPortalsClient("your-api-key") as client:
        wallet = await client.wallet.get()
        state = await client.arena.state()

        print(wallet.balance)
        print(state.server_time)


asyncio.run(main())

Get an API key from the Portals mini app under Profile → Partner API. Keep the key on your server and never commit it to source control.

Resources

Resource Operations
client.arena Arena state, inventory, and bets
client.offers Create, update, cancel, inspect, and accept collection offers
client.collections Collection previews, metrics, and attribute floor prices
client.market Market configuration and activity
client.nfts Search, owned NFTs, purchases, listings, transfers, and withdrawals
client.users User existence and authenticated user activity
client.wallet Balance, deposits, TON withdrawals, and withdrawal statuses

Methods return typed models. For example:

from decimal import Decimal

from portals import BuyDetail, PortalsClient

with PortalsClient("your-api-key") as client:
    purchase = client.nfts.buy(
        [
            BuyDetail(id="nft-id", price=Decimal("12.50")),
        ]
    )

    print(purchase.total_purchased)
    print(purchase.total_failed)
    print(purchase.total_spent)

Purchases may partially succeed. Inspect each item in purchase.purchase_results rather than assuming the whole request succeeded or failed.

Amounts and timestamps

Pass amounts as decimal strings or Decimal instances. Floats are rejected to avoid binary floating-point errors. Amounts are serialized as strings on the wire and exposed as Decimal values by response models.

RFC 3339 timestamps are exposed as datetime instances. Arena timestamps remain integers because the API returns Unix milliseconds.

Errors

from portals import APIError, PortalsClient, RateLimitError

with PortalsClient("your-api-key") as client:
    try:
        client.market.actions()
    except RateLimitError as exc:
        if exc.rate_limit is not None:
            print(exc.rate_limit.reset_seconds)
    except APIError as exc:
        print(exc.status_code, exc.code, exc.message)

Specific exceptions cover authentication, access denial, rate limits, an unavailable market feed, and unknown Arena bet outcomes. Transport failures, invalid JSON, and response-validation failures have separate exception types.

Write operations are not automatically retried. In particular, an Arena bet that returns 504 BET_OUTCOME_UNKNOWN or fails during network transmission may already have been placed; check client.arena.state() before trying again.

Custom HTTP clients

Pass an httpx2.Client or httpx2.AsyncClient to customize transports, proxies, or test behavior. The library closes only clients it creates itself.

import httpx2

from portals import PortalsClient

http_client = httpx2.Client(timeout=10)
client = PortalsClient("your-api-key", client=http_client)

client.close()
http_client.close()

Low-level requests

Use request() for new endpoints that do not yet have a typed method:

payload = client.request("GET", "/partners/example", params={"limit": 10})

Pass response_model=YourModel to validate the response with Pydantic.

Development

Install the project and development tools with uv:

uv sync

Run the checks used by CI:

uv run ruff check .
uv run ruff format --check .
uv run mypy
uv run pytest
uv build

The OpenAPI contract is vendored at specs/partners.en.json. Refresh it and regenerate the models, then review the resulting changes:

uv run python scripts/update_spec.py
uv run python scripts/generate_models.py
uv run ruff check --fix src/portals/models.py
uv run ruff format src/portals/models.py

License

MIT

Metadata

Release files for portals-api 0.1.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 portals-api 0.1.1
File Size Uploaded Provenance Actions
portals_api-0.1.1.tar.gz 28.4 kB With provenance Details for portals_api-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for portals-api 0.1.1
File Interpreter ABI Platform Actions
portals_api-0.1.1-py3-none-any.whl Python 3 none any Details for portals_api-0.1.1-py3-none-any.whl

Total release size: 53.8 kB

Release files / portals_api-0.1.1.tar.gz

Download URL portals_api-0.1.1.tar.gz
Size 28.4 kB
Tags Source
SHA-256 checksum
How to use checksums
4be47e7742d024fab1db4a5f69ebed7044dd088dbcace6ec9a4318ef4c7ad221
BLAKE2b-256 checksum
How to use checksums
7b504a9a2f20f33407df9f497700019c07b6a3d1f3fd4a08f9fca67f7f80e44b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 31, 2026.

Transparency log

Release files / portals_api-0.1.1-py3-none-any.whl

Download URL portals_api-0.1.1-py3-none-any.whl
Size 25.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0a29253fd9ab2f0560c2b871002b6dd116b69404b3805ef900fa0b4c70f24b45
BLAKE2b-256 checksum
How to use checksums
f0121a8599a18b6da773a4b5de237b1de081b2d1a6d51464c934f96225e7c1b9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 31, 2026.

Transparency log

Security for portals-api 0.1.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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for portals_api-0.1.1.tar.gz

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 Oct 31, 2026.

Transparency log

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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

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