SynAuth SDK
Python SDK for AI agents to request human-approved actions. Two approval methods: TOTP (any authenticator app) or Face ID (SynAuth iOS app).
Install
pip install synauth
Two Ways to Get Started
Option A: TOTP (No iOS App Required)
Use any TOTP authenticator (Google Authenticator, Authy, Apple Passwords, 1Password). Time to first approval: ~5 minutes.
from synauth import SynAuthAdmin, SynAuthClient
# 1. Create account via magic link
result = SynAuthAdmin.request_magic_link("you@example.com")
# 2. Verify and register your device
device = SynAuthAdmin.verify_magic_link(result["token"], "My Laptop")
admin = SynAuthAdmin(device_id=device["device_id"])
# 3. Set up TOTP — scan the QR code with your authenticator app
setup = admin.totp_setup()
print(f"Add to authenticator: {setup['provisioning_uri']}")
# 4. Verify TOTP with a code from your authenticator
admin.totp_verify("123456") # replace with actual code
# 5. Create an API key for your agent
key = admin.create_key("my-agent", "Research Agent")
print(f"API key (save this!): {key['key']}")
Option B: Face ID (iOS App)
- Get the SynAuth iOS app from the App Store. Create an account.
- Copy your API key from the app — it starts with
aa_.
Quick Start — Agent Side
from synauth import SynAuthClient
client = SynAuthClient(api_key="aa_your_key_here")
# Agent requests approval for an action
result = client.request_action(
action_type="communication",
title="Send quarterly report",
description="Email to investor@example.com with Q4 results",
risk_level="low",
)
# Agent waits for human approval (TOTP or Face ID)
status = client.wait_for_result(result["id"])
if status["status"] == "approved":
send_email(...)
Approving Actions with TOTP
from synauth import SynAuthAdmin
admin = SynAuthAdmin(device_id="dev_your_device_id")
# See what's pending
pending = admin.get_pending()
for action in pending["actions"]:
print(f"{action['id']}: {action['title']}")
# Approve with your TOTP code
admin.approve("action_id_here", totp_code="123456")
# Or deny
admin.deny("action_id_here", reason="Not authorized")
How It Works
- Your AI agent calls
request_action()(or a convenience method likerequest_email()) - The action goes pending on SynAuth
- You approve via TOTP code or Face ID on your iPhone
- The agent polls for the result — or receives a webhook callback
- If using the credential vault, SynAuth executes the action with stored credentials
API Key Management
admin = SynAuthAdmin(device_id="dev_your_device_id")
# Create keys for your agents
key = admin.create_key("trading-agent", "Trading Bot")
# List active keys (values hidden — only prefixes)
keys = admin.list_keys()
for k in keys["keys"]:
print(f"{k['key_prefix']} — {k['name']} ({k['agent_id']})")
# Revoke a compromised key
admin.revoke_key("aa_abc12")
TOTP Management
admin = SynAuthAdmin(device_id="dev_your_device_id")
# Check TOTP status
status = admin.totp_status()
print(f"TOTP enabled: {status['enabled']}")
# Reset TOTP (delete and re-setup)
admin.totp_delete()
setup = admin.totp_setup()
admin.totp_verify("654321")
Credential Vault
The agent can't bypass what it can't access. Store your API credentials in SynAuth's vault. The agent requests actions through the SDK — SynAuth injects the real credentials after approval. The agent never sees your API keys.
# Discover available services
services = client.list_vault_services()
# Execute an API call through the vault (approval-gated)
result = client.execute_api_call(
service_name="openai",
method="POST",
url="https://api.openai.com/v1/chat/completions",
body='{"model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}]}',
)
Convenience Methods
# Email
client.request_email(recipient="team@co.com", subject="Update", preview="Q4 numbers")
# Purchase
client.request_purchase(amount=49.99, merchant="DigitalOcean", description="3x droplets")
# Booking
client.request_booking(title="Team lunch", description="12pm at Nobu", amount=850.00)
# Social media
client.request_post(platform="Twitter", content_preview="Announcing our Series A...")
# Data access
client.request_data_access(resource="production-db", reason="Monthly analytics export")
# Legal
client.request_contract(title="NDA with Acme Corp", description="Standard mutual NDA")
Payment-Only Wrapper
For agents that only need payment authorization:
from synauth.pay import SynPayClient
client = SynPayClient(api_key="aa_your_key_here")
request = client.request_payment(
amount=29.99,
merchant="OpenAI",
description="GPT-5 API credits",
)
status = client.wait_for_result(request["id"])
Error Handling
from synauth import (
SynAuthClient,
SynAuthError,
SynAuthAPIError,
RateLimitError,
ActionDeniedError,
ActionExpiredError,
VaultExecutionError,
)
client = SynAuthClient(api_key="aa_...")
try:
result = client.execute_api_call(
service_name="github",
method="POST",
url="https://api.github.com/repos",
body='{"name": "new-repo"}',
)
except ActionDeniedError as e:
print(f"User denied: {e.reason}")
except ActionExpiredError as e:
print(f"Request expired: {e.request_id}")
except RateLimitError:
print("Rate limited — back off and retry")
except VaultExecutionError as e:
print(f"Vault execution failed: {e.detail}")
except SynAuthAPIError as e:
print(f"API error {e.status_code}: {e.detail}")
Spending Limits
Check your agent's spending against configured limits before making purchases:
summary = client.get_spending_summary()
for s in summary["summaries"]:
print(f"{s['action_type']} ({s['period']}): ${s['spent']:.2f} / ${s['limit']:.2f}")
History
Review past action requests:
history = client.get_history(limit=10, status="approved")
for action in history["actions"]:
print(f"{action['title']} — {action['status']}")
Webhook Callbacks
Receive status updates without polling:
result = client.request_action(
action_type="purchase",
title="Buy API credits",
amount=100.00,
callback_url="https://your-server.com/webhook/synauth",
)
# SynAuth will POST to callback_url when the user approves or denies
Action Types
| Type | Examples | Default Risk |
|---|---|---|
communication |
Emails, messages, notifications | low |
purchase |
Buying, subscriptions, payments | medium |
scheduling |
Bookings, reservations, calendar | low |
legal |
Contracts, terms, agreements | critical |
data_access |
Database queries, file downloads | high |
social |
Social media posts, profile updates | medium |
system |
Config changes, restarts, deployments | high |
Configuration
| Class | Auth | Purpose |
|---|---|---|
SynAuthClient(api_key) |
API key (aa_...) |
Agent-facing: request actions, poll status, vault |
SynAuthAdmin(device_id) |
Device ID (dev_...) |
Developer-facing: TOTP, keys, approve/deny |
| Parameter | Default | Description |
|---|---|---|
base_url |
https://synauth.fly.dev |
SynAuth backend URL (override for self-hosted) |
Also Available
- synauth-mcp — MCP server for Claude and other MCP-compatible agents
- SynAuth iOS App — Face ID approval on your iPhone
License
MIT
Metadata
Release files for synauth 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| synauth-0.2.0.tar.gz | 23.9 kB | Without provenance | Details for synauth-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| synauth-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for synauth-0.2.0-py3-none-any.whl |
Total release size: 39.8 kB
Release files / synauth-0.2.0.tar.gz
| Download URL | synauth-0.2.0.tar.gz |
|---|---|
| Size | 23.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b7cef171b8fc72b2f39cbc97082e8fddc14d57d0ef1689e9dac3abc23e40aebf
|
|
BLAKE2b-256 checksum How to use checksums |
5864fdc210cd3c41af88d20710aa464ee361dba2a24d0a0abd36263dd6f0f195
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|
Release files / synauth-0.2.0-py3-none-any.whl
| Download URL | synauth-0.2.0-py3-none-any.whl |
|---|---|
| Size | 15.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
68c7ffa54bd5561e5b90070185a3b930958b5a04ca64b96243c14156c238a248
|
|
BLAKE2b-256 checksum How to use checksums |
a13cc7bf7a0f732b1212b9f3eb4394bab2ec004ffad2219b9ad46953d184b5f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.2
|
Security for synauth 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.