Skip to main content

BYO - Python SDK for BYOK

Project description

BYO PYTHON SDK for BYOK

Official Python SDK for BYO — BYOK (Bring Your Own Key).

Installation

pip install byok

Quick Start

import os
from byo import BYOK

byok = BYOK(api_key=os.environ["BYOK_API_KEY"])

# Proxy an OpenAI request
openai = byok.openai(ref_id="customer_123")
response = openai.responses.create(
    model="gpt-4.1",
    input="Hello from BYOK!"
)
print(response)

OpenAI

Responses API

openai = byok.openai(ref_id="customer_123")
response = openai.responses.create(model="gpt-4.1", input="What is BYOK?")

Chat Completions API

openai = byok.openai(ref_id="customer_123")
response = openai.chat.completions.create(
    model="gpt-4.1",
    messages=[{"role": "user", "content": "Hello!"}]
)

Anthropic

Messages API

claude = byok.anthropic(ref_id="customer_123")
response = claude.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}]
)

Google AI Studio

Generate Content

gemini = byok.google(ref_id="customer_123")
response = gemini.generate_content.create(
    model="gemini-2.0-flash",
    contents=[{"parts": [{"text": "Hello!"}]}]
)

Azure OpenAI

Chat Completions

azure = byok.azure_openai(ref_id="customer_123")
response = azure.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Hello!"}]
)

Azure OpenAI requires provider_config when connecting the key:

byok.keys.connect(
    provider="azure-openai",
    ref_id="customer_123",
    provider_key="your-azure-api-key",
    provider_config={
        "baseUrl": "https://your-resource.openai.azure.com",
        "deploymentName": "gpt-4",
    },
)

AWS Bedrock

Converse

bedrock = byok.bedrock(ref_id="customer_123")
response = bedrock.converse.create(
    modelId="anthropic.claude-3-haiku-20240307-v1:0",
    messages=[{"role": "user", "content": [{"text": "Hello!"}]}]
)

AWS Bedrock requires provider_config when connecting the key:

byok.keys.connect(
    provider="bedrock",
    ref_id="customer_123",
    provider_key="your-aws-secret-access-key",
    provider_config={
        "accessKeyId": "AKIA...",
        "region": "us-east-1",
    },
)

Key Management

# Connect a provider key
byok.keys.connect(
    provider="openai",
    ref_id="customer_123",
    provider_key="sk-..."
)

# Validate a stored key
result = byok.keys.validate(provider="openai", ref_id="customer_123")

# Revoke a stored key
byok.keys.revoke(provider="openai", ref_id="customer_123")

Usage and cost

Every proxied LLM call captures the model, prompt/completion tokens and an estimated USD cost. Read it back per customer (ref_id) to power your own billing UI:

from datetime import datetime, timedelta, timezone

usage = byok.usage.get(ref_id="customer_123")
print(usage["totals"]["costUsd"], usage["byModel"], usage["daily"])

# Filter by date range and provider; pass datetime or ISO string.
last_7d = byok.usage.get(
    ref_id="customer_123",
    provider="openai",
    since=datetime.now(timezone.utc) - timedelta(days=7),
)

# 24-hour rollup used by the dashboard overview.
stats = byok.usage.stats()

The cost is calculated server-side using BYO's built-in pricing table. If you call a model BYO doesn't have a price for (a fine-tune, a fresh model release, an OpenAI-compatible local server), it'll show up in usage["unknownModels"] so you know exactly what to add — and the cost row will be None until you patch it:

print(usage["unknownModels"])
# [{'provider': 'openai', 'model': 'ft:gpt-4o-...:abc',
#   'requests': 142, 'totalTokens': 184230}]

Custom model prices

Patch in custom prices per project — useful for fine-tunes, niche OpenAI-compatible endpoints, or anything BYO ships without a default for. The shape mirrors the BYO_MODEL_PRICING env var; numbers are USD per 1,000,000 tokens. Changes take effect within ~60s on every API instance.

byok.pricing.update(project_id, {
    "openai": {"my-finetune": {"input": 0.5, "output": 2.0}},
})

current = byok.pricing.get(project_id)

byok.pricing.clear(project_id)  # back to BYO's defaults

Streaming note: to capture token counts on streamed OpenAI Chat Completions, include stream_options={"include_usage": True} in the request — otherwise providers don't return a usage block and the log row will have tokens and costUsd set to None.

Logs

Inspect individual proxied requests, including the captured tokens and cost:

result = byok.logs.list(ref_id="customer_123", success=False, limit=50)
for entry in result["data"]:
    print(entry["model"], entry["totalTokens"], entry["costUsd"])

log = byok.logs.get(result["data"][0]["id"])

Error Handling

The SDK raises typed exceptions so you can branch on the failure mode without parsing status codes by hand:

Class When it's raised
AuthenticationError 401 — invalid or missing API key
AuthorizationError 403 — key isn't allowed to perform this action
ValidationError 400 / 422 — bad payload
NotFoundError 404 — project / log / endpoint missing
RateLimitError 429 — exposes retry_after_ms from Retry-After
ProviderError Upstream provider (OpenAI, Anthropic, …) rejected
ServerError 5xx from the BYO API
NetworkError Connection failure (httpx raised)
TimeoutError Hit the SDK request timeout
BYOKError Base class — catch this for "anything from BYO"
from byo import (
    BYOK, BYOKError, AuthenticationError,
    RateLimitError, ProviderError,
)

try:
    response = openai.responses.create(model="gpt-4.1", input="Hello")
except AuthenticationError:
    print("Invalid API key")
except RateLimitError as e:
    print(f"Rate limited; retry in {e.retry_after_ms}ms")
except ProviderError as e:
    print(f"Upstream {e.provider} rejected: {e.message}")
except BYOKError as e:
    print(f"Error {e.status_code}: {e.message}")

Webhooks

Verify webhook deliveries from BYO with one call. The signature is a constant-time HMAC-SHA256 over the raw request body using the endpoint's signing secret:

from byo import construct_webhook_event

@app.post("/webhooks/byo")
async def byo_webhook(request):
    body = await request.body()
    try:
        event = construct_webhook_event(
            body,
            request.headers.get("X-BYO-Signature"),
            os.environ["BYO_WEBHOOK_SECRET"],
        )
    except Exception:
        return Response(status_code=400)
    handle_event(event)
    return Response(status_code=200)

Need just the boolean? Use verify_webhook_signature(payload, header, secret).

Project Origin Allowlist

When you ship a publishable key (byo_pk_*) into a frontend, lock it down to the origins that should be allowed to call /keys/connect and /connect/form:

byok.origins.update("proj_123", [
    "https://app.example.com",
    "https://staging.example.com",
])

byok.origins.clear("proj_123")  # empty list = unrestricted

Audit Log

Every security-relevant mutation (project changes, key revokes, pricing updates, origin allowlist edits, webhook config changes) is recorded in an append-only audit log:

from datetime import datetime, timedelta, timezone

result = byok.audit.list(
    project_id="proj_123",
    action="provider_key.revoked",
    since=datetime.now(timezone.utc) - timedelta(days=1),
)
for entry in result["data"]:
    print(entry["createdAt"], entry["action"], entry["actorId"])

License

FSL-1.1-MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

byok-0.4.0.tar.gz (14.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

byok-0.4.0-py3-none-any.whl (12.5 kB view details)

Uploaded Python 3

File details

Details for the file byok-0.4.0.tar.gz.

File metadata

  • Download URL: byok-0.4.0.tar.gz
  • Upload date:
  • Size: 14.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for byok-0.4.0.tar.gz
Algorithm Hash digest
SHA256 bc441db1dc5500d695bd993ed78be768db916fb618a2611d6e146b67515952f2
MD5 1eb03740d4a401fa578aea1156d9734d
BLAKE2b-256 6026bf8c5b2d9f08d9f81d89ddede83c81af9cd617bfcf9734de3644d577fcde

See more details on using hashes here.

Provenance

The following attestation bundles were made for byok-0.4.0.tar.gz:

Publisher: release.yml on treadiehq/byo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file byok-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: byok-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 12.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for byok-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 38807e7165c36dcb1a272de6f49e8673b2b7bf2ba7af5e3d25cf46313bad4592
MD5 294f7e86914f306b87728062a9cd45e8
BLAKE2b-256 56f0b163ac0f0d40d1dced814e3bb122ac9b75de72e8a7289fdb786cb80b5f46

See more details on using hashes here.

Provenance

The following attestation bundles were made for byok-0.4.0-py3-none-any.whl:

Publisher: release.yml on treadiehq/byo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page