Python SDK for the Grantex delegated authorization protocol — OAuth 2.0 for AI agents
Project description
grantex
Python SDK for the Grantex delegated authorization protocol — OAuth 2.0 for AI agents.
Grantex lets humans authorize AI agents with verifiable, revocable, audited grants built on JWT and the OAuth 2.0 model. This SDK provides a complete client for the Grantex API.
Homepage | Docs | API Reference | Sign Up Free | GitHub
Install
pip install grantex
Quick start
from grantex import Grantex, ExchangeTokenParams, verify_grant_token, VerifyGrantTokenOptions
client = Grantex(api_key="YOUR_API_KEY")
# 1. Start the authorization flow
request = client.authorize(
agent_id="ag_01HXYZ...",
user_id="usr_01HXYZ...",
scopes=["files:read", "email:send"],
)
# Redirect the user to the consent page — they approve in plain language
print(request.consent_url)
# 2. Exchange the authorization code for a grant token
# (your redirect callback receives the `code` after user approves)
token = client.tokens.exchange(ExchangeTokenParams(code=code, agent_id="ag_01HXYZ..."))
print(token.grant_token) # RS256-signed JWT
print(token.scopes) # ('files:read', 'email:send')
# 3. Verify the grant token offline (no network call)
grant = verify_grant_token(
token=token.grant_token,
options=VerifyGrantTokenOptions(
jwks_uri="https://api.grantex.dev/.well-known/jwks.json",
),
)
print(grant.principal_id) # 'usr_01HXYZ...'
# 4. Revoke when done
client.tokens.revoke(grant.token_id)
Offline verification
Verify grant tokens without a network call using the public JWKS:
from grantex import verify_grant_token
verified = verify_grant_token(
token="eyJhbGciOiJSUzI1NiIs...",
jwks_url="https://api.grantex.dev/.well-known/jwks.json",
)
print(verified.scopes) # ['files:read', 'email:send']
print(verified.principal_id) # 'usr_01HXYZ...'
print(verified.agent_did) # 'did:web:...'
PKCE Support
The SDK includes built-in PKCE (Proof Key for Code Exchange) support using the S256 method:
from grantex import Grantex, ExchangeTokenParams, generate_pkce
client = Grantex(api_key="YOUR_API_KEY")
# 1. Generate a PKCE challenge
pkce = generate_pkce()
# pkce.code_verifier — random 43-char string (keep secret)
# pkce.code_challenge — SHA-256 hash of verifier (send to server)
# pkce.code_challenge_method — 'S256'
# 2. Pass the challenge when requesting authorization
request = client.authorize(
agent_id="ag_01HXYZ...",
user_id="usr_01HXYZ...",
scopes=["files:read"],
code_challenge=pkce.code_challenge,
code_challenge_method=pkce.code_challenge_method,
)
# 3. Exchange the code with the verifier
token = client.tokens.exchange(ExchangeTokenParams(
code="auth_code_from_redirect",
agent_id="ag_01HXYZ...",
code_verifier=pkce.code_verifier,
))
Features
| Feature | Description |
|---|---|
| Authorization flow | client.authorize() — initiate consent, get grant tokens |
| Token exchange | client.tokens.exchange() — exchange an authorization code for a grant token |
| Token management | client.tokens.verify(), .revoke() — online verification and revocation |
| Offline verification | verify_grant_token() — RS256 signature check against JWKS |
| Agent management | client.agents.create(), .get(), .list(), .update(), .delete() |
| Grant management | client.grants.list(), .get(), .revoke() |
| Multi-agent delegation | client.grants.delegate() — scoped sub-grants with cascade revocation |
| Audit trail | client.audit.log(), .list(), .get() — tamper-evident hash-chained log |
| Policy engine | client.policies.create(), .list(), .update(), .delete() |
| Anomaly detection | client.anomalies.list(), .detect() |
| Compliance | client.compliance.summary(), .export_audit(), .export_grants(), .evidence_pack() |
| Webhooks | client.webhooks.create(), .list(), .delete() + verify_webhook_signature() |
| Billing | client.billing.status(), .checkout(), .portal() |
| SCIM 2.0 | client.scim.create_user(), .list_users(), .get_user(), .update_user(), .delete_user() |
| OIDC SSO | client.sso.create_config(), .get_config(), .login(), .callback() |
Configuration
from grantex import Grantex
# Explicit API key
client = Grantex(api_key="gx_live_...")
# Or via environment variable
# export GRANTEX_API_KEY=gx_live_...
client = Grantex()
# Custom base URL (self-hosted)
client = Grantex(
api_key="gx_live_...",
base_url="https://auth.your-company.com",
)
# Custom timeout (seconds)
client = Grantex(api_key="gx_live_...", timeout=60.0)
The client also works as a context manager:
with Grantex(api_key="gx_live_...") as client:
agents = client.agents.list()
Error handling
from grantex import Grantex, GrantexApiError, GrantexAuthError, GrantexNetworkError
client = Grantex(api_key="gx_live_...")
try:
client.agents.get("ag_invalid")
except GrantexAuthError:
# 401 — invalid or expired API key
pass
except GrantexApiError as e:
# Any other API error (4xx/5xx)
print(e.status_code, e.code, e.message)
except GrantexNetworkError:
# Connection failure, timeout, DNS error
pass
Requirements
- Python 3.9+
- httpx (sync HTTP client)
- PyJWT + cryptography (for offline token verification)
Links
Grantex Ecosystem
| Package | Description |
|---|---|
@grantex/sdk |
TypeScript SDK |
@grantex/langchain |
LangChain integration |
@grantex/autogen |
AutoGen integration |
@grantex/vercel-ai |
Vercel AI SDK integration |
grantex-crewai |
CrewAI integration |
grantex-openai-agents |
OpenAI Agents SDK integration |
grantex-adk |
Google ADK integration |
@grantex/mcp |
MCP server for Claude Desktop / Cursor / Windsurf |
@grantex/cli |
Command-line tool |
License
Apache 2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file grantex-0.1.7.tar.gz.
File metadata
- Download URL: grantex-0.1.7.tar.gz
- Upload date:
- Size: 27.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f145ede3ae61f91aee288666a7297d41798c82ce151ab2cfef27a1b5dd6724b1
|
|
| MD5 |
a5a6312908e441761c2a8e7830e158c7
|
|
| BLAKE2b-256 |
e4f1018c6fc9a2a128b7a99d2baaf8d3e7f29557f8d44eb96125015fd6f0365a
|
File details
Details for the file grantex-0.1.7-py3-none-any.whl.
File metadata
- Download URL: grantex-0.1.7-py3-none-any.whl
- Upload date:
- Size: 24.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8409a7969bcfa9b4bc364ccf5ede9cd695254f2188341b516c57ae00e1d55a24
|
|
| MD5 |
91d948485016cd540b3fc840246c77e4
|
|
| BLAKE2b-256 |
f3a94e7cf518ec36cddd07d992f51cb66d461c998ebffb2b914f69986fc44c74
|