Skip to main content

Meteroid Python SDK

The official Python SDK for Meteroid, the open-source billing and pricing platform. Meteroid manages subscriptions, usage-based billing and metering, invoicing and revenue analytics; this library calls its REST API and verifies its webhooks, against Meteroid Cloud (https://api.meteroid.com) or a self-hosted instance.

Website · Documentation · API reference · Meteroid on GitHub

Installation

pip install meteroid

Python 3.10 or newer. The SDK depends on httpx only and is fully typed. Every method of the API is listed in api.md.

Usage

from meteroid import Meteroid

client = Meteroid(api_key="your-api-key")

add_on = client.add_ons.retrieve("addon_id")
print(add_on)

Without api_key, the client reads METEROID_API_KEY, and METEROID_BASE_URL overrides the default base URL, https://api.meteroid.com. Every argument is a keyword argument. The constructor also takes base_url, timeout, max_retries, default_headers, http_client (an httpx.Client of yours), middleware, and the credentials the API accepts (token_provider, basic_auth, api_keys). Close the client, or use it as a context manager, to release its connections.

AsyncMeteroid has the same resources for asyncio:

from meteroid import AsyncMeteroid

async with AsyncMeteroid() as client:
    add_on = await client.add_ons.retrieve("addon_id")

Requests

The fields of a JSON or form request body are keyword arguments, next to the query and header parameters; path parameters come first:

client.connect.create_onboarding_link("id", redirect_url="redirect_url")

An optional argument left out is not sent; None sends null where the API accepts it. An enum argument takes the enum or its value as a string. Other bodies (lists, unions, files) are one body argument.

Every method also takes, for that request only, extra_headers=, extra_query=, extra_body= (merged into the body), timeout= and max_retries=. These headers, like default_headers, win over the client's credentials.

Models

Models are keyword-only dataclasses with from_dict/to_dict. In models requests send, an optional field that accepts null defaults to UNSET (from meteroid.models): it is left out of the request, while None sends null; in response models it is simply None when absent. A field holding a string or an object, such as an expandable id, is typed str | Model. A discriminated union is the union of its variant models (Circle | Square | UnknownVariant), decoded into the variant the tag names; when its variants share fields, it is a model holding the discriminator and the variant, and passing content= alone fills in the tag.

Properties the API added after this SDK was generated are kept in extra_fields (and read as attributes at runtime), and sent back when the model is serialized. A property named after a model member, such as extra_fields or to_dict, gets a trailing _.

Pagination

List methods return their first page, which is also the response of the request: a subclass of the response model, such as AddOnsListPage (in meteroid.api), whose properties are read on the page. Iterating it walks every item of every page, fetching the next ones on demand:

for add_on in client.add_ons.list():
    print(add_on)

page = client.add_ons.list()
print(page.pagination_meta.total_pages)  # a property of the response
page.items  # this page's items
if page.has_next_page():
    page = page.get_next_page()
for page in client.add_ons.list().iter_pages():
    print(len(page.items))

A response property named like a paging member (items, has_next_page, get_next_page, iter_pages or body) is read on page.body, the response as decoded.

With the async client, async for item in client.add_ons.list() walks the items, and page = await client.add_ons.list() returns the first page, whose get_next_page() is awaited and iter_pages() walked with async for.

Multipart bodies take Upload(content, filename, content_type) files, and binary bodies bytes or file objects.

Raw responses

Prefix a call with with_raw_response for the HTTP response next to the decoded result:

response = client.with_raw_response.add_ons.retrieve("addon_id")
print(response.status_code, response.headers, response.request_id)
add_on = response.parse()

Errors

Every error derives from MeteroidError. A non-2xx response raises an APIStatusError subclass named after its status (BadRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError), whose body is the error response decoded into its schema (its JSON when the API declares none) and request_id the id to quote to support.

from meteroid import APIConnectionError, APITimeoutError, NotFoundError

try:
    client.add_ons.retrieve("addon_id")
except NotFoundError as error:
    print(error.status_code, error.request_id, error.body)
except APITimeoutError:
    ...  # the request timed out, after retries
except APIConnectionError:
    ...  # no response, after retries

A successful response that does not decode raises APIResponseValidationError.

Retries and timeouts

Connection errors, timeouts, 408, 429 and 5xx responses are retried twice with exponential backoff, honoring Retry-After, when replaying the request is safe: for idempotent methods and requests with an Idempotency-Key header. Requests time out after 60 seconds.

client = Meteroid(max_retries=5, timeout=20.0)
client.with_options(max_retries=0).add_ons.retrieve("addon_id")
client.add_ons.retrieve("addon_id", timeout=5.0, max_retries=0)  # for one call

Middleware

middleware=[...] wraps every HTTP attempt: a callable receiving the httpx.Request and next, returning an httpx.Response, to cache, log or sign requests.

Generated by perseid.

Metadata

Release files for meteroid 0.28.0

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

Source distribution (sdist)

Source distribution for meteroid 0.28.0
File Size Uploaded
meteroid-0.28.0.tar.gz 130.0 kB Details

Built distribution (wheel)

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

Total release size: 398.8 kB

Release files / meteroid-0.28.0.tar.gz

Download URL meteroid-0.28.0.tar.gz
Size 130.0 kB
Tags Source
SHA-256 checksum
How to use checksums
c7b5d51dd41b7852a9d12880ef1474ed300101add7adcb21b7bc3a56f2eebc5f
BLAKE2b-256 checksum
How to use checksums
685b9bd3721963700a2fb16814fe629b3adc47d90b4a5cff858f55ec7e01756c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / meteroid-0.28.0-py3-none-any.whl

Download URL meteroid-0.28.0-py3-none-any.whl
Size 268.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0cc42918edbbfb27d5eb58962ffe342de8b50ac4a961d1b01bcf28c8537bf9cf
BLAKE2b-256 checksum
How to use checksums
6ebfa9d64ba23e49e0d42f8bf3f022319cd5466c7d38fdd1ef672236be3bfd23
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.28.0 This release

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