Official Python SDK for the Rerout branded-link API.
Project description
rerout
Official Python SDK for the Rerout API.
Branded link infrastructure on Cloudflare. Create short links, render QR codes, read analytics, and verify webhook signatures.
Install
pip install rerout
# or
uv add rerout
# or
poetry add rerout
Requires Python 3.10+.
Usage
from rerout import Rerout, CreateLinkInput
rerout = Rerout(api_key="rrk_...")
link = rerout.links.create(
CreateLinkInput(
target_url="https://example.com/q4-sale",
domain_hostname="go.brand.com",
code="q4",
)
)
print(link.short_url) # https://go.brand.com/q4
stats = rerout.project.stats(days=7)
print(f"Last 7 days: {stats.total_clicks} clicks, {stats.qr_scans} QR scans")
The client can be used as a context manager to ensure the underlying HTTP connection pool is closed:
with Rerout(api_key="rrk_...") as rerout:
link = rerout.links.get("q4")
API
Construction
from rerout import Rerout
rerout = Rerout(
api_key="rrk_...", # required
base_url="https://api.rerout.co", # optional, defaults shown
timeout=30.0, # optional, seconds
client=None, # optional, inject your own httpx.Client
)
Inject a custom httpx.Client for proxies, retries, or shared connection
pools. The SDK does not close clients it didn't create.
Links
from rerout import CreateLinkInput, UpdateLinkInput
rerout.links.create(CreateLinkInput(target_url=..., domain_hostname=..., code=...))
rerout.links.list(cursor=None, limit=None)
rerout.links.get(code)
rerout.links.update(code, UpdateLinkInput(target_url=...))
rerout.links.delete(code)
rerout.links.stats(code, days=30)
UpdateLinkInput uses an UNSET sentinel to distinguish "leave this field
alone" from "clear this field on the server" — pass None to clear, or
just don't pass the field at all:
from rerout import UpdateLinkInput
# Clear the expiry, leave everything else untouched
rerout.links.update("q4", UpdateLinkInput(expires_at=None))
# Disable the link without touching SEO
rerout.links.update("q4", UpdateLinkInput(is_active=False))
Calling update with an UpdateLinkInput where no field has been set
raises ReroutError(code='bad_request') without hitting the API.
Project
rerout.project.stats(days=30) # -> ProjectStats
rerout.project.me() # -> ProjectInfo
QR codes
from rerout import QrOptions
# Pure URL builder — no network call
rerout.qr.url("q4", QrOptions(size=12, ecc="H", domain="go.brand.com"))
# Fetches the rendered SVG with the bearer token attached
svg = rerout.qr.svg("q4", QrOptions(refresh=True))
QR options:
| Field | Type | Notes |
|---|---|---|
size |
int |
Module size in px. 1–32. Server default 8. |
margin |
int |
Quiet zone in modules. 0–16. Server default 4. |
ecc |
'L' | 'M' | 'Q' | 'H' |
Error correction level. |
domain |
str |
Force the QR to encode a specific verified custom domain. |
refresh |
str | bool |
Cache-bust on regenerate. True is sent as 1; strings pass through. |
Webhook signature verification
from rerout import verify_rerout_signature
ok = verify_rerout_signature(
raw_body=request.body.decode(),
signature_header=request.headers["x-rerout-signature"],
secret=settings.REROUT_WEBHOOK_SECRET,
)
if not ok:
return Response(status=401)
Defaults to a 5-minute timestamp tolerance; pass tolerance_seconds=0 to
disable that check.
Error handling
Every method raises ReroutError on failure:
from rerout import Rerout, ReroutError, CreateLinkInput
try:
rerout.links.create(CreateLinkInput(target_url="http://insecure.example"))
except ReroutError as err:
print(err.code) # 'bad_target_url'
print(err.status) # 400
print(err.message) # 'target_url must use https.'
if err.is_rate_limited:
... # back off
Synthetic codes when the server didn't return a JSON body:
network_error, timeout, unexpected_response, unauthorized,
forbidden, not_found, rate_limited, server_error, client_error,
missing_api_key, bad_request.
Local development
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest
mypy src
ruff check src tests
ruff format --check src tests
License
MIT — see LICENSE in the workspace root.
Repository
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rerout-0.1.0.tar.gz.
File metadata
- Download URL: rerout-0.1.0.tar.gz
- Upload date:
- Size: 19.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c858e8c554d49a7fd2a53e30ab8a323100e687a6596429467e252dcce7556c85
|
|
| MD5 |
f4135e7ca38503c70f74b4ff5b4055cf
|
|
| BLAKE2b-256 |
8042e7b6058c4c515796660b42e39246efc823d1a8a9d5be809de36ea7d1eb39
|
File details
Details for the file rerout-0.1.0-py3-none-any.whl.
File metadata
- Download URL: rerout-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db1b80672a1fcb2b3a9ed4085f85c2f7bc7b597a1cae46f946ac289776089b8f
|
|
| MD5 |
6458a8d0bf0f3e7d7c6650415b6b01f9
|
|
| BLAKE2b-256 |
4fac922e8b3c116cd86321a94efbc6006ba060c54d54ec3aafd70d49923571df
|