Python SDK
The HostRepute Python SDK, hostrepute version 0.1.0, is a typed client for the REST API v1 with a synchronous
Client and an AsyncClient built on httpx. It needs Python 3.10 or later, httpx (0.27 up to, not including, 0.29)
and typing_extensions. Version 0.1.0 manages domains and IPs, check profiles, alert channels and delivery hours well,
but can’t read check results or metrics yet: read known problems in 0.1.0 before you build on
it.
Install
Section titled “Install”pip install hostreputeCreate a client
Section titled “Create a client”hostrepute.Client takes a team API token, or a hostrepute.Config with the token and other settings. Create the
token in Settings, then API tokens with the abilities your
code needs; Authentication and API tokens explains them. The SDK doesn’t read
environment variables itself: the examples on this page read the token from HOSTREPUTE_API_TOKEN.
import os
import hostrepute
config = hostrepute.Config( token=os.environ["HOSTREPUTE_API_TOKEN"], timeout=45.0, user_agent="deploy-checks/1.4",)
with hostrepute.Client(config) as client: for host in client.hosts.iterate(per_page=100): print(host.host, host.is_blocklisted)Leaving the with block closes the client’s connections; without it, call client.close(). Config raises a
ValueError for an empty token, a base URL without a scheme or host, a timeout of zero or less, or an invalid retry
setting. Client.builder() offers the same settings as with_… methods, such as
Client.builder().with_token(token).with_timeout(45.0).build().
Config field |
Default | What it does |
|---|---|---|
token |
required | The team API token, sent as Authorization: Bearer <token>. |
base_url |
https://app.hostrepute.com |
The API’s address. Give the origin only: the SDK adds /api/v1/… to every path. |
timeout |
30.0 seconds |
The httpx read, write and pool timeouts. |
connect_timeout |
10.0 seconds |
The httpx connect timeout. |
user_agent |
hostrepute-python/0.1.0 httpx/<version> |
The User-Agent header. |
retry_max_attempts, retry_base_delay_ms, retry_max_delay_ms |
3, 200, 5000 |
The retry policy. See retries. |
default_headers |
{} |
Extra headers on every request. They are applied last, so they also replace Authorization or User-Agent if you name them. |
To use your own httpx.Client (for proxies or instrumentation), pass it as hostrepute.Client(config, http_client=...). The SDK then uses it as is: timeout and connect_timeout don’t apply, and the SDK doesn’t close
it.
Async client
Section titled “Async client”hostrepute.AsyncClient has the same resources and methods as coroutines; iterate() is an async iterator:
async with hostrepute.AsyncClient( hostrepute.Config(token=os.environ["HOSTREPUTE_API_TOKEN"])) as client: async for host in client.hosts.iterate(per_page=100): print(host.host)Resources
Section titled “Resources”The client has one attribute per API resource. The names follow the API, not the portal:
| In HostRepute | Attribute | Methods | API |
|---|---|---|---|
| Domains and IPs | client.hosts |
list, iterate, get, create, update, delete |
/api/v1/hosts |
| Blocklists | client.data_sources |
list, iterate, get |
/api/v1/data-sources |
| Check profiles | client.monitoring_profiles |
list, iterate, get, create, update, delete |
/api/v1/data-source-groups |
| Alert channels | client.alerts |
list, iterate, get, create, update, delete |
/api/v1/alerts |
| Delivery hours | client.contact_groups |
list, iterate, get, create, update, delete |
/api/v1/alert-groups |
| Blocklist checks | client.blacklist |
check, status, check_and_wait, wait_for |
/api/v1/blacklist |
| Certificate checks | client.certificates |
check, status, check_and_wait, wait_for |
/api/v1/certificates |
| Email authentication checks | client.deliverability |
check, status, check_and_wait, wait_for |
/api/v1/deliverability |
| Prometheus metrics | client.metrics |
get |
/api/v1/metrics |
list(page=..., per_page=...)returns aPagewithdata,meta,links,current_page,last_page,per_page,totalandhas_next_page.per_pageis 1–100; the API sends 15 when you leave it out.iterate()walks every page, 50 items per request unless you setper_page. Read Pagination.get,updateanddeletetake theuuid, exceptdata_sources.get, which takes the blocklist’s numericid.updatesendsPUTwith the fields you pass, and raises aValueErrorwhen you pass none.- The SDK has no method for sending a test alert. Call
POST /api/v1/alerts/{alert}/testdirectly.
Add a domain or IP
Section titled “Add a domain or IP”Every domain or IP needs a check profile. The SDK calls it
monitoring_profile_uuid and sends it as data_source_group_uuid:
profiles = client.monitoring_profiles.list()profile = next(p for p in profiles.data if p.is_default)
host = client.hosts.create( name="Mail", host="mail.example.com", monitoring_profile_uuid=profile.uuid,)Set delivery hours and an alert channel
Section titled “Set delivery hours and an alert channel”Delivery hours are contact_groups in the SDK. schedule is a dict that the
SDK sends unchanged, so give it the shape the API expects:
- Keys
mon,tue,wed,thu,fri,satandsun, each withenabled,startandend. Times areHH:MM, and an enabled day must end after it starts. - A day you leave out gets no alerts. Leave
scheduleout entirely for delivery hours that are open at any time. updateleaves outNonearguments, so it can’t turn existing delivery hours back to any time. Send"schedule": nullwith the REST API instead.- The SDK’s README shows a
daysandhoursshape: the API rejects it with422.
weekday = {"enabled": True, "start": "08:00", "end": "18:00"}weekend = {"enabled": False, "start": "08:00", "end": "18:00"}
hours = client.contact_groups.create( name="Business hours", timezone="America/New_York", schedule={ "mon": weekday, "tue": weekday, "wed": weekday, "thu": weekday, "fri": weekday, "sat": weekend, "sun": weekend, },)An alert channel is alerts. settings holds the field the channel type needs
(email here; Set up alert channels lists them all), and contact_group_uuids the delivery
hours it follows:
channel = client.alerts.create( type=hostrepute.AlertType.EMAIL, frequency=hostrepute.AlertFrequency.ONCE_ON_LISTED_DELISTED, contact_group_uuids=[hours.uuid],)For frequency, use AlertFrequency.ONCE_ON_LISTED_DELISTED (Listed and removed
in the portal) or AlertFrequency.ONCE_PER_CHECK_WHILE_LISTED (Only when listed).
The SDK also defines AlertFrequency.DAILY, which the API rejects with 422, and AlertFrequency.EVERY_CHECK, a
retired value that the API stores as once_on_listed_delisted.
Run checks
Section titled “Run checks”Each check uses 1 credit (credit costs). check() starts a
blocklist or certificate check and returns it with status pending; its uuid identifies the check:
scan = client.blacklist.check(host="mail.example.com")print(scan.uuid, scan.status)certificates.check() also takes protocol, port and sni, and both take callback_url to be told when the check
ends. A callback’s signature can’t be verified yet, so treat the callback as a notification and read the result from
the status endpoint, as Receive webhooks explains. The SDK’s own webhook
helpers don’t match what HostRepute sends, so don’t use them.
The SDK also has status(uuid), wait_for(uuid, timeout=..., poll_interval=...) and
check_and_wait(host, ..., timeout=..., poll_interval=...). The wait helpers poll status until the check is
completed or failed, for up to timeout (60 seconds by default) every poll_interval (2 seconds), and then raise
hostrepute.TimeoutError with the scan_uuid. In 0.1.0 they don’t work against the API (see below), so poll
GET /api/v1/blacklist/status/{uuid} or GET /api/v1/certificates/status/{uuid} yourself, or use a callback, as
Run checks and wait for results shows.
Known problems in 0.1.0
Section titled “Known problems in 0.1.0”- Status and wait helpers fail while a check runs.
status(),wait_for()andcheck_and_wait()onblacklistandcertificatesraiseValueError: 'processing' is not a valid ScanStatusas soon as the API reports the check as running. It’s a plainValueError, soexcept hostrepute.HostreputeErrordoesn’t catch it. - Results are missing. The blocklist and certificate check objects have no
resultand no counts (such as how many blocklists list the host), so even acompletedcheck doesn’t tell you what it found. - Email authentication checks always raise. Every
deliverabilitymethod raises aValueError(or aDecodingErrorforfailed) on the API’s status, after the API has run the check and used the credit. metrics.get()raises aDecodingError, because it reads the Prometheus text as JSON.402has no typed error. Readerr.body["required_credits"]anderr.body["available_credits"]on theApiError.
Retries
Section titled “Retries”The SDK retries a failed request up to 3 attempts in total:
429is retried for every method. A429means the API refused the request before running it, so a retried check isn’t charged twice.5xxand network errors are retried only forGET,HEAD,OPTIONS,PUTandDELETE. APOSTthat creates something or starts a check isn’t retried, so the SDK never starts a check twice.- Waits. When the response has
Retry-After(seconds or an HTTP date), the SDK waits that long. Otherwise it waits a random delay between zero and 200 ms × 2attempt − 1, capped at 5 seconds. - When the attempts run out, you get the error for the last response, for example a
RateLimitError.
client = hostrepute.Client( hostrepute.Config( token=os.environ["HOSTREPUTE_API_TOKEN"], retry_max_attempts=5, retry_base_delay_ms=500, retry_max_delay_ms=10_000, ))retry_max_attempts=1 turns retries off. Rate limits lists the limits behind 429.
Errors
Section titled “Errors”All SDK errors extend hostrepute.HostreputeError. API errors extend ApiError, with status_code, errors (field
names to messages), body (the parsed response) and response; the message is str(err).
| Status or cause | Class | Extra fields |
|---|---|---|
401 |
AuthenticationError |
|
403 |
AuthorizationError |
|
404 |
NotFoundError |
|
422 |
ValidationError |
errors |
429 |
RateLimitError |
retry_after, in seconds |
5xx |
ServerError |
|
Any other status, including 402 |
ApiError |
|
| No response, or an httpx timeout | NetworkError |
__cause__, the httpx error |
| A wait helper’s timeout | TimeoutError |
scan_uuid |
| A response the SDK can’t read | DecodingError |
hostrepute.TimeoutError isn’t Python’s built-in TimeoutError: catch it by its full name.
try: client.blacklist.check(host="mail.example.com")except hostrepute.ValidationError as err: print(err.errors)except hostrepute.RateLimitError as err: print(f"Rate limited, retry in {err.retry_after} s")except hostrepute.ApiError as err: if err.status_code != 402: raise print(f"Needs {err.body['required_credits']} credits, {err.body['available_credits']} left")Errors shows the response body behind each status.
Related
Section titled “Related”- Official SDKs compares the five SDKs.
- Make your first API call uses the REST API without an SDK.
- Run checks and wait for results explains polling, callbacks and credits.
- API token abilities lists what each ability allows.
- The API reference documents every operation.

