Skip to content
OAOpenAppPhysical Security as a Service
Login

Authentication

The SDK authenticates via OpenApp API keys. Tokens have the shape {base_url}_openapp_{secret}; the SDK parses the token and uses {base_url} as the API host unless you override it.

  1. Log in to the OpenApp dashboard.
  2. Go to Resources → API Keys.
  3. Click Create API key, give it a name, pick an expiry.
  4. Copy the token — it is shown only once.

You need the api_keys:create role in the target organization.

from openapp_sdk import Client
client = Client.connect(api_key="https://api.openapp.house/api/v1_openapp_YOUR_SECRET")

Client.connect / AsyncClient.connect parse the token, configure the HTTP client, and return a ready-to-use client. No additional setup.

If you are pointing at a staging / on-prem backend that does not match the token’s embedded base URL, pass base_url explicitly:

client = Client.connect(
api_key="...",
base_url="https://staging.example.com/api/v1",
)

This is primarily useful during development or when testing through a proxy.

The SDK does not read environment variables by default — we prefer explicit configuration in code. If you want env-var driven setup, wrap it yourself:

import os
from openapp_sdk import Client
def open_client() -> Client:
token = os.environ["OPENAPP_API_KEY"]
return Client.connect(api_key=token)

API keys are immutable; to rotate, mint a new key and delete the old one.

# Create a replacement.
new_key = client.api_keys.create(name="prod-ci", expires_in_days=90)
# Deploy new_key["token"] to your secret store, then:
client.api_keys.delete(new_key["id"]) # only once new_key is in use

Pluggable token providers for unattended rotation in long-running services are a planned extension point; for now, the Python SDK treats the token as fixed per client.

  • Never logs the token. repr(ApiKey(...)) elides the secret.
  • Never sends the token as a query string.
  • Never caches it to disk.
SymptomLikely cause
AuthError: invalid token formatThe token is missing the _openapp_ separator. Re-copy from the dashboard.
ConfigError: base URL could not be derivedToken prefix is not a valid URL; override with base_url=....
AuthError: unauthorized (401)Token revoked, expired, or pointing at the wrong backend.