Skip to main content

unwrapr

Stop writing the same API response unwrapping code in every project.

pip install unwrapr

Requires Python 3.9+ · Zero dependencies


The problem

Every API you call returns a different shape:

{"data": {...}, "error": null}           # some APIs
{"success": True, "result": {...}}       # other APIs
{"status": 200, "payload": {...}}        # yet others
[{"id": 1}, {"id": 2}]                  # or just raw lists

You end up writing custom unwrapping logic for every single one.

unwrapr fixes that. One function. Any shape. Consistent output.


Quick start

from unwrapr import unwrap

# Works with any API response shape
env = unwrap({"success": True, "data": {"id": 1, "name": "Alice"}})

env.ok      # True
env.data    # {"id": 1, "name": "Alice"}
env.error   # None
env.status  # None
env.meta    # {}

Supported shapes

unwrapr auto-detects the response shape and normalises it:

# { data, error }
unwrap({"data": {"id": 1}, "error": None})

# { success, data }
unwrap({"success": True, "result": {"id": 1}})

# { status, payload }
unwrap({"status": 200, "payload": {"id": 1}})

# JSON:API
unwrap({"data": [...], "included": [], "meta": {"total": 5}})

# Plain dict or list
unwrap({"id": 1, "name": "Alice"})
unwrap([1, 2, 3])

HTTP status override

Pass the HTTP status code to let it override the body:

env = unwrap(response.json(), status=response.status_code)
env.ok      # True if 2xx, False otherwise
env.status  # the actual HTTP status code

Safe data access

env = unwrap({"success": False, "error": "Not found"})

# Raises UnwraprError if not ok
data = env.unwrap()

# Returns default if not ok — never raises
data = env.unwrap_or([])
data = env.unwrap_or(None)

# Use as a boolean
if env:
    print(env.data)

Custom strategies

Add your own shape detection logic:

from unwrapr import unwrap, DEFAULT_STRATEGIES

def my_api_strategy(raw):
    if isinstance(raw, dict) and "response" in raw:
        return {
            "ok": raw["response"]["success"],
            "data": raw["response"]["body"],
            "error": raw["response"].get("error"),
            "status": None,
            "meta": {},
        }
    return None  # return None to try the next strategy

env = unwrap(response, strategies=[my_api_strategy] + DEFAULT_STRATEGIES)

Works great with petchr

from petchr import petch
from unwrapr import unwrap

resp = petch("https://api.example.com/users/1")
env = unwrap(resp.data, status=resp.status_code)

if env:
    print(env.data)
else:
    print(f"Error: {env.error}")

The Envelope

Every call returns an Envelope:

Field Type Description
ok bool True if response is successful
data Any The extracted payload
error `str None`
status `int None`
meta dict Extra fields (pagination, links etc)
raw Any Original response before normalising

License

MIT

Metadata

Release files for unwrapr 1.0.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 unwrapr 1.0.0
File Size Uploaded Provenance Actions
unwrapr-1.0.0.tar.gz 8.3 kB Without provenance Details for unwrapr-1.0.0.tar.gz

Built distribution (wheel)

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

Total release size: 15.4 kB

Release files / unwrapr-1.0.0.tar.gz

Download URL unwrapr-1.0.0.tar.gz
Size 8.3 kB
Tags Source
SHA-256 checksum
How to use checksums
e023fc28bb91c818398981109841d098b78a8f1d0e50a7fa91d0acd41a3b57f0
BLAKE2b-256 checksum
How to use checksums
73a59ad1834de0981dab061959f1049cc1a6067c84a8885db37e695f0a56a51e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release files / unwrapr-1.0.0-py3-none-any.whl

Download URL unwrapr-1.0.0-py3-none-any.whl
Size 7.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f00c58682bf2bca5e8f64582f6371482c04adf8f0585b0b04fa4aa4bda7ee36b
BLAKE2b-256 checksum
How to use checksums
ec72bf9c4d6c5c3fe48fa808d8a0cefd0ff80218a86fce585f211a67f50f27c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Security for unwrapr 1.0.0

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.

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

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files No 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