Skip to main content
Version: 1.0

Python SDK

Roadmap feature

The SyVault Python SDK is in alpha (v0.1.0) and not yet published to PyPI. The package name (syvault-sdk) will be published when the SDK reaches a stable release. Track progress in sdks/python/.

The official SyVault Python SDK provides a synchronous and asynchronous interface for accessing secrets from Python applications, scripts, and notebooks.

Installation

pip install syvault-sdk

Requires Python 3.9 or later.

Authentication

from syvault_sdk import SyVaultClient

client = SyVaultClient(
server="https://vault.example.com",
client_id="c9a1b2d3-4e5f-6789-abcd-ef0123456789",
client_secret=os.environ["SY_CLIENT_SECRET"],
)

The SDK generates an ECDSA P-256 signed JWT for each request. Token refresh is handled internally.

Fetching Secrets

List all secrets

secrets = client.secrets.list()

for s in secrets:
print(s.uid, s.title)

Get a full secret

secret = client.secrets.get("7Kj9mNpQ2xRs")

print(secret.fields["host"]) # "db.example.com"
print(secret.fields["password"]) # "s3cret!"

Resolve a notation

password = client.secrets.notation("sy://Production/Database/field/password")
print(password) # "s3cret!"

Creating Secrets

new_secret = client.secrets.create(
folder_id="folder-uuid-here",
title="Stripe API Key",
fields={
"key": "sk_live_abc123",
"environment": "production",
},
)

print(new_secret.uid) # "Xp4qRtY8mNwK"

Rotating Secrets

result = client.secrets.rotate("7Kj9mNpQ2xRs")

print(result.status) # "completed"
print(result.new_fields["password"]) # new generated password

Async Support

For asyncio-based applications (FastAPI, aiohttp), use the async client:

from syvault_sdk import AsyncSyVaultClient

client = AsyncSyVaultClient(
server="https://vault.example.com",
client_id="c9a1b2d3-4e5f-6789-abcd-ef0123456789",
client_secret=os.environ["SY_CLIENT_SECRET"],
)

secret = await client.secrets.get("7Kj9mNpQ2xRs")
print(secret.fields["password"])

Error Handling

from syvault_sdk import SyVaultClient
from syvault_sdk.exceptions import SecretNotFoundError, AuthError

try:
secret = client.secrets.get("nonexistent")
except SecretNotFoundError as e:
print(f"Secret {e.uid} does not exist")
except AuthError:
print("Authentication failed — check client credentials")

Django Example

Load database credentials from SyVault in settings.py:

import os
from syvault_sdk import SyVaultClient

sy = SyVaultClient(
server=os.environ["SY_SERVER"],
client_id=os.environ["SY_CLIENT_ID"],
client_secret=os.environ["SY_CLIENT_SECRET"],
)

db_secret = sy.secrets.get(os.environ["SY_DB_SECRET_UID"])

DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"HOST": db_secret.fields["host"],
"PORT": db_secret.fields["port"],
"NAME": db_secret.fields["database"],
"USER": db_secret.fields["username"],
"PASSWORD": db_secret.fields["password"],
}
}

FastAPI Example

from contextlib import asynccontextmanager
from fastapi import FastAPI
from syvault_sdk import AsyncSyVaultClient

sy = AsyncSyVaultClient(
server="https://vault.example.com",
client_id="...",
client_secret="...",
)

@asynccontextmanager
async def lifespan(app: FastAPI):
# Load secrets at startup
db_secret = await sy.secrets.get("7Kj9mNpQ2xRs")
app.state.db_password = db_secret.fields["password"]
yield

app = FastAPI(lifespan=lifespan)

@app.get("/health")
async def health():
return {"ok": True}

Caching

The SDK caches decrypted secrets in memory for 60 seconds by default:

client = SyVaultClient(
server="https://vault.example.com",
client_id="...",
client_secret="...",
cache_ttl=300, # 5 minutes
cache_max=500, # max entries
)

# Disable caching
client = SyVaultClient(
# ...
cache_ttl=0,
)

Context Manager

The client can be used as a context manager to ensure resources are cleaned up:

with SyVaultClient(server="...", client_id="...", client_secret="...") as sy:
secret = sy.secrets.get("7Kj9mNpQ2xRs")
print(secret.fields["password"])
# Connection pool is closed here

# Async equivalent
async with AsyncSyVaultClient(server="...", client_id="...", client_secret="...") as sy:
secret = await sy.secrets.get("7Kj9mNpQ2xRs")