Skip to main content

OpenHandle Python SDK

The official Python client for the OpenHandle API.

Installation

pip install openhandle

The package supports Python 3.10 and newer and ships full type annotations.

Usage

Create a Test key in the Openhandle dashboard, store it as OPENHANDLE_TEST_KEY, and create one reusable client:

import os

from openhandle import OpenHandle

openhandle = OpenHandle(api_key=os.environ["OPENHANDLE_TEST_KEY"])
profile = openhandle.instagram.profile("northstar_forge_test")

response = profile.get()
posts = profile.posts.list(freshness="24h")

print(response.data["handle"], len(posts.data))

The key selects the environment. oh_test_ keys return deterministic synthetic data with a $0.000 actual charge; oh_live_ keys use real public identifiers and normal billing. Never expose an API key in client-side code.

See the API reference for a typed SDK example for every operation.

Resource selection

The SDK follows one predictable grammar:

openhandle.<platform>.<resource>(reference).<subresource>.<operation>(options)

Only terminal operations such as get, list, search, and fetch perform network requests. Selecting a resource is synchronous and reusable:

post = openhandle.instagram.post("Db04otPRpRH")

response = post.get()
comments = post.comments.list()

A profile selector accepts a username shorthand or an explicit reference:

openhandle.instagram.profile("openai")
openhandle.instagram.profile("https://www.instagram.com/openai/")
openhandle.instagram.profile(username="12356")
openhandle.instagram.profile(id="25025320")
openhandle.instagram.profile(url="https://www.instagram.com/openai/")

A raw string is never treated as a platform ID. profile("12356") selects the username 12356; profile(id="12356") selects platform ID 12356. Numeric reference values are rejected because platform IDs are opaque strings.

Call openhandle.fetch(url) when you do not know which resource a supported social URL represents.

Pagination

A list or search operation returns one typed page:

page = openhandle.instagram.profile("northstar_forge_test").posts.list()

print(page.data, page.has_next_page, page.next_cursor)
next_page = page.next()

items() iterates lazily across pages, one request per page:

for post in openhandle.instagram.profile("northstar_forge_test").posts.items():
    print(post["id"])

Async client

AsyncOpenHandle exposes the same resource graph with async terminal operations:

import asyncio
import os

from openhandle import AsyncOpenHandle


async def main() -> None:
    async with AsyncOpenHandle(api_key=os.environ["OPENHANDLE_TEST_KEY"]) as openhandle:
        response = await openhandle.instagram.profile("northstar_forge_test").get()
        print(response.data["handle"])

        async for post in openhandle.instagram.profile("northstar_forge_test").posts.items():
            print(post["id"])


asyncio.run(main())

Responses

Every response preserves the public envelope. data stays typed through the generated models in openhandle.models, and metadata is available on the response object:

response = openhandle.instagram.profile("northstar_forge_test").get()

response.platform  # "instagram"
response.resource  # "profile"
response.captured_at  # datetime
response.source  # "live" or "cache"
response.request_id  # stable request identifier for logs and support
response.billing.cost  # authoritative charge as a decimal string

A missing metric is None. It is never 0.

Errors and retries

The SDK raises OpenHandleError with the documented fields. Branch on code, never on message:

from openhandle import OpenHandle, OpenHandleError

try:
    response = openhandle.instagram.profile("private_account").get()
except OpenHandleError as error:
    print(error.code, error.request_id, error.retryable)

Retryable failures are retried automatically with capped exponential backoff and Retry-After support. Configure the client, or override per request:

openhandle = OpenHandle(api_key="...", timeout=10.0, max_retries=1)
openhandle.twitter.profile("openai").get(timeout=5.0, max_retries=0)

Locally invalid references raise OpenHandleReferenceError before any request is made. ReferenceMismatchError reports a social URL that belongs to a different platform or resource than the selector.

License

MIT

Release files for openhandle 1.0.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 openhandle 1.0.1
File Size Uploaded
openhandle-1.0.1.tar.gz 41.8 kB Details

Built distribution (wheel)

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

Total release size: 86.2 kB

Release files / openhandle-1.0.1.tar.gz

Download URL openhandle-1.0.1.tar.gz
Size 41.8 kB
Tags Source
SHA-256 checksum
How to use checksums
35db762e614e1d9810a64b48ce0c21468aba78468548daa0eeee4423767388f0
BLAKE2b-256 checksum
How to use checksums
c2690608ca3ff92e8b0eab83ea0d79d9716cddcbfd9caaa3780fc50445c53400
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 30, 2026.

Transparency log

Release files / openhandle-1.0.1-py3-none-any.whl

Download URL openhandle-1.0.1-py3-none-any.whl
Size 44.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
47421736e20fe44b6979a81ade9a8f9fa5cc6061395e9829b124ff7040e4137a
BLAKE2b-256 checksum
How to use checksums
10bc3528c9f2b6f3cdb91546fcf666326d0739d6b813ffd97fa4caccd4e151f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 30, 2026.

Transparency log

Release history Release notifications | RSS feed

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

This release

1.0.1 This release

2 release files

1.0.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