Python connector
The Passwork Python connector wraps the REST API and all cryptographic operations in a high-level Python interface. Use it when you need more control than Passwork CLI provides: batch operations, conditional logic, error handling, migrations, or custom reporting.
The core class is PassworkClient. It provides access to all Passwork objects — vaults, folders, items, users, groups, sessions — and handles token refresh and CSE transparently.
Installation
- PyPI
- GitHub (SSH)
pip install passwork-python
pip install git+ssh://[email protected]:passwork-me/passwork-python.git
Requirements:
- Python 3.10+,
- requests>=2.31.0
- cryptography>=42.0.
- pbkdf2>=1.3
Authentication
- Token pair (recommended)
- With CSE (master key)
import os
from passwork import Client
client = Client(
url=os.environ["PASSWORK_HOST"],
token=os.environ["PASSWORK_TOKEN"],
refresh_token=os.environ.get("PASSWORK_REFRESH_TOKEN"),
)
import os
from passwork import Client
client = Client(
url=os.environ["PASSWORK_HOST"],
token=os.environ["PASSWORK_TOKEN"],
refresh_token=os.environ.get("PASSWORK_REFRESH_TOKEN"),
master_key=os.environ["PASSWORK_MASTER_KEY"],
)
When refresh_token is provided, the connector renews the access token automatically on expiry. No manual token management is needed in long-running scripts.
Reading secrets
Get a single item by ID
item = client.get_password(item_id="<item_id>")
print(item.name) # item name
print(item.login) # login field
print(item.password) # password field (decrypted if CSE enabled)
Get all items from a folder
items = client.get_passwords(folder_id="<folder_id>")
for item in items:
print(f"{item.name}: {item.password}")
Access custom fields
Custom fields are available on the item.fields dictionary, keyed by field name:
item = client.get_password(item_id="<item_id>")
aws_key_id = item.login
aws_secret_key = item.fields.get("AWS_SECRET_ACCESS_KEY")
aws_region = item.fields.get("AWS_REGION")
Search across vaults
results = client.search_passwords(query="postgres")
for item in results:
print(f"{item.name} in vault {item.vault_id}")
CSE and the MasterKeyManager
When client-side encryption is enabled, the MasterKeyManager component handles key derivation from the master key, RSA private key decryption, and per-vault and per-item key unwrapping. The client handles this automatically when master_key is provided.
If you need to derive the master key from a master password (rather than providing the pre-derived key):
from passwork import Client
from passwork.crypto import MasterKeyManager
manager = MasterKeyManager()
master_key = manager.derive_master_key(
password="your_master_password",
salt="<salt_from_user_profile>",
)
client = Client(
url="https://passwork.example.com",
token="<token>",
master_key=master_key,
)
In practice, most automation uses the pre-derived PASSWORK_MASTER_KEY (which is a base64-encoded byte string) rather than the raw master password.
Writing and updating secrets
Update an existing item's password
item = client.get_password(item_id="<item_id>")
item.password = "new_strong_password_here"
client.update_password(item)
Update a custom field value
item = client.get_password(item_id="<item_id>")
item.fields["AWS_SECRET_ACCESS_KEY"] = "new_aws_secret_key"
client.update_password(item)
Create a new item
from passwork.models import PasswordItem
new_item = PasswordItem(
name="Redis sessions",
login="redis",
password="generated_password",
folder_id="<target_folder_id>",
tags=["production", "messaging"],
)
client.create_password(new_item)
Session persistence
For scripts that run frequently, save and restore the session to avoid generating a new token pair on every run:
import os
from passwork import Client
session_file = "/tmp/passwork_session.enc"
client = Client(url=os.environ["PASSWORK_HOST"])
if os.path.exists(session_file):
client.load_session(session_file)
else:
client.set_tokens(
token=os.environ["PASSWORK_TOKEN"],
refresh_token=os.environ["PASSWORK_REFRESH_TOKEN"],
)
# ... use client ...
client.save_session(session_file)
Saved sessions are encrypted. The encryption key is derived from a combination of token material and is not stored alongside the session file.
Error handling
from passwork import Client
from passwork.exceptions import PassworkResponseError, PassworkError
try:
item = client.get_password(item_id="<item_id>")
except PassworkResponseError as e:
# HTTP error from the Passwork API (4xx, 5xx)
print(f"API error {e.code}: {e.message}")
except PassworkError as e:
# Client-side error (network, encryption, etc.)
print(f"Client error: {e}")
Common API error codes to handle:
| Code | Meaning | Action |
|---|---|---|
accessTokenExpired | Access token expired | Connector handles automatically if refresh token is set |
itemNotFound | Item ID does not exist | Verify item ID or check vault access |
forbidden | Service account lacks permission | Review vault access level |
masterKeyRequired | CSE enabled but no master key provided | Add master_key to Client() constructor |
Universal call() method
For any API endpoint not covered by a specific connector method, use call():
# Get activity logs
response = client.call(
method="GET",
endpoint="/api/v1/activity-logs",
params={"limit": 100},
)
# Bulk delete items
response = client.call(
method="POST",
endpoint="/api/v1/items/delete/bulk",
json={"ids": ["id1", "id2", "id3"]},
)
For full API reference, see API and integrations: overview.
For more Python connector examples, see the integration examples repository.