Skip to main content

ohapi

A typed Python client for the ohapi secrets API. It has no dependencies. It uses only the standard library. It needs Python 3.10 or later.

Install

pip install ohapi

The package is not on PyPI yet.

Example

import os

from ohapi import Ohapi, OhapiError, Pending

ohapi = Ohapi(os.environ["OHAPI_TOKEN"])

result = ohapi.secrets.set(project_id, "production", "API_URL", "https://api.example.com", confirm_production=True)

if isinstance(result, Pending):
    # Dual control holds the change. Nothing is written yet.
    try:
        ohapi.change_requests.wait(result.change_request_id)
    except OhapiError as error:
        if error.code != "rejected":
            raise
        print("A reviewer refused the change:", error.change_request.status)
else:
    print("Wrote version", result.version)

Methods

Method Endpoint Audit row
me() GET /api/v1/me No
projects.list(), projects.get(id) GET /api/v1/projects, …/{id} No
environments.list(), .iterate(), .get() GET …/environments No
secrets.list(), .iterate(), .get() GET …/secrets No. Metadata only.
secrets.value() GET …/secrets/{key}/value Yes. One READ row for each call.
secrets.pull() GET /api/v1/secrets Yes. One READ row for the environment. Expired keys are omitted.
secrets.set(), .create(), .patch(), .delete() PUT, POST, PATCH, DELETE Yes, when the write lands. A Pending result has no row yet. The row is written when an admin approves the change.
change_requests.get(), .wait() GET /api/v1/change-requests/{id} No

list() takes page and page_size. iterate() takes page_size. The server accepts page numbers up to 10000 and page sizes up to 500.

The client is synchronous. There is no asyncio client.

Pending writes

Dual control can hold a write to production. In that case a write returns Pending with a change_request_id. The value is not written. Check isinstance(result, Pending) before you read version.

A write returns one of these types:

Call Result
set(), create() Written(key, version, created, id)
patch() Patched(key)
delete() Deleted(key)
Any of them, when dual control holds the change Pending(change_request_id, key)

wait(change_request_id, interval_s=5.0, timeout_s=600.0, cancel=None) returns only when the request is APPLIED. It raises OhapiError with code rejected when a reviewer rejects or cancels the request. The terminal request is in error.change_request. To stop a wait from another thread, pass a threading.Event as cancel and set it. A request that is already in flight ends at its own deadline, which is never later than the end of timeout_s.

Omitted and None

set() and create() take format_regex, rotation_due_at, expires_at, value_type and note as optional arguments. value_type is STRING, JSON, PASSWORD or CERTIFICATE. patch() takes the same arguments except value_type. An argument you leave out does not change the stored value. An argument you pass as None clears the stored value. Dates are ISO 8601 strings or datetime objects.

Errors

Every failure of a request, and every input that the SDK refuses, is an OhapiError with a code, a status (0 when there was no response), and a message. A wrong call, for example a missing argument, is still a normal Python TypeError.

Code Cause
invalid Bad input. The SDK refused it before any request, or the server answered 400.
unauthenticated 401. The key is missing, wrong, or expired.
forbidden 403. The key has a read-only role, the route is for admins only, or the key scope does not cover the target.
not_found 404. The thing does not exist, or the key cannot reach it.
conflict 409. create() found the key already there.
unprocessable 422. The server refused the value.
rate_limited 429. retry_after_seconds holds the wait.
server Any other HTTP failure. A redirect is also server, and so is a 2xx answer that is not JSON. The SDK never follows a redirect and never reads its Location header.
network No connection.
timeout The whole request, headers and body included, did not finish within timeout_s (30 seconds by default), or wait() ended.
rejected wait() found a rejected or cancelled change request.

The SDK does not retry. You decide the retry policy. The SDK does not log.

The key

The client keeps the key in a name-mangled attribute. repr() and str() of the client do not print it. A traceback that shows local variables does not contain it either. This protects logs. It does not hide the key from other code in the same process. The SDK refuses a key that contains a carriage return, a line feed or a null character. It also refuses a custom user_agent that is not printable ASCII.

Not included

The SDK does not create, rename, or delete projects and environments. It does not wrap the organization endpoints. Use the dashboard or the HTTP API for those.

Tests

sdk-python/scripts/test.sh

The script runs the unit tests in Docker. The tests need no server.

Metadata

Release files for ohapi 0.1.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 ohapi 0.1.0
File Size Uploaded
ohapi-0.1.0.tar.gz 24.7 kB Details

Built distribution (wheel)

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

Total release size: 39.7 kB

Release files / ohapi-0.1.0.tar.gz

Download URL ohapi-0.1.0.tar.gz
Size 24.7 kB
Tags Source
SHA-256 checksum
How to use checksums
9ee28ff5f952c8c8b5e23c30c9ac73fe3743eac4481e886adc8b0639553c8d3a
BLAKE2b-256 checksum
How to use checksums
0db50c4788c8813fbb307a43ccd366350ccc0b4d34c60ce19ce63e6454dfa7c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.11

Release files / ohapi-0.1.0-py3-none-any.whl

Download URL ohapi-0.1.0-py3-none-any.whl
Size 15.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
36eeb08297c70199103f9602bc12aba3a3b21d889770ca5d3e8d4ad82cb35c78
BLAKE2b-256 checksum
How to use checksums
6c4e756dddd09a14e7974abb7a126a441846d441688e081b4d49b500d75e5ad2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.11

Release history Release notifications | RSS feed

This release

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