PayGraph
Open-source spend governance for AI agents. Issue single-use virtual cards or pay x402-enabled APIs with USDC — with policy enforcement, audit logging, and human-in-the-loop approval.
Architecture
Agent (LangGraph / CrewAI / any framework)
│
▼
┌────────────────────────────────────────┐
│ AgentWallet │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Policy Engine│ │ Audit Logger │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ ┌──────▼─────────────────▼─────────┐ │
│ │ Payment Rails │ │
│ │ Card: Mock │ Stripe │ StripeMPP │ │
│ │ │ │
│ │ x402: X402Gateway │ MockX402 │ │
│ └──────────────────────────────────┘ │
└────────────────────────────────────────┘
Install
pip install paygraph
With LangGraph support:
pip install paygraph[langgraph]
With CrewAI support:
pip install paygraph[crewai]
With x402 support (EVM + Solana USDC payments):
pip install paygraph[x402]
With live demo (includes LLM providers):
pip install paygraph[live]
Quickstart
from paygraph import AgentWallet, SpendPolicy, MockGateway
wallet = AgentWallet(
gateway=MockGateway(auto_approve=True),
policy=SpendPolicy(
max_transaction=25.0,
daily_budget=100.0,
blocked_vendors=["doordash"],
),
)
result = wallet.request_spend(
amount=4.20,
vendor="Anthropic API",
justification="Need Claude credits for document summarization.",
)
print(result) # Card approved. PAN: 4111..., CVV: 123, Expiry: 12/28
StripeCardGateway (Real Cards)
from paygraph import AgentWallet, SpendPolicy, StripeCardGateway
wallet = AgentWallet(
gateway=StripeCardGateway(api_key="sk_test_..."),
policy=SpendPolicy(max_transaction=50.0),
)
result = wallet.request_spend(
amount=4.20,
vendor="Anthropic API",
justification="API credits for task completion.",
)
Configuration
StripeCardGateway accepts the following parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
required | Stripe secret key (sk_test_... or sk_live_...) |
cardholder_id |
str | None |
None |
Existing cardholder ID to use (skips auto-creation) |
currency |
str |
"usd" |
Card currency (e.g. "eur", "gbp") |
billing_address |
dict | None |
US address | Cardholder billing address (line1, city, postal_code, country) |
single_use |
bool |
True |
Mint a new card per transaction; set False to reuse one card |
When single_use=False, a single card is created on the first spend and reused for subsequent calls (spending limit is updated each time).
StripeMPPGateway (Shared Payment Tokens)
For sellers that accept Stripe machine payments (MPP / agentic commerce), use StripeMPPGateway to issue scoped Shared Payment Tokens instead of virtual cards.
Requires Stripe machine payments access (preview API). See Stripe docs.
from paygraph import AgentWallet, SpendPolicy, StripeMPPGateway
wallet = AgentWallet(
gateway=StripeMPPGateway(
api_key="sk_test_...",
payment_method="pm_...",
grantee="profile_...",
),
policy=SpendPolicy(max_transaction=50.0),
)
result = wallet.request_spend(
amount=4.20,
vendor="Anthropic API",
justification="API credits for task completion.",
)
print(result) # SPT approved. Token: spt_... (spend limit: $4.20)
Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
required | Stripe secret key (sk_test_... or sk_live_...) |
payment_method |
str |
required | Saved PaymentMethod id (pm_...) |
grantee |
str |
required | Seller identifier (typically profile_...) |
currency |
str |
"usd" |
ISO currency code |
expires_in_seconds |
int |
3600 |
Token lifetime from issuance in seconds |
x402 Gateway (Pay APIs with USDC)
x402 is an HTTP 402-based protocol for machine-to-machine payments. Instead of minting a card, the gateway makes an HTTP request, handles the 402→sign→retry cycle on-chain, and returns the API response.
from paygraph import AgentWallet, X402Gateway, SpendPolicy
wallet = AgentWallet(
x402_gateway=X402Gateway(evm_private_key="0x..."), # Base/Polygon USDC
policy=SpendPolicy(max_transaction=5.0),
)
response = wallet.request_x402(
url="https://api.example.com/paid-endpoint",
amount=0.01,
vendor="ExampleAPI",
justification="Need data for analysis.",
)
print(response) # The API response body
Supports both EVM (Base, Polygon, etc.) and Solana:
# Solana only
gateway = X402Gateway(svm_private_key="BASE58_KEY")
# Both networks
gateway = X402Gateway(evm_private_key="0x...", svm_private_key="BASE58_KEY")
For testing without blockchain:
from paygraph import AgentWallet, MockX402Gateway
wallet = AgentWallet(
x402_gateway=MockX402Gateway(auto_approve=True, response_body='{"data": 42}'),
)
LangGraph Integration
from paygraph import AgentWallet, SpendPolicy, MockX402Gateway
wallet = AgentWallet(
x402_gateway=MockX402Gateway(auto_approve=True),
policy=SpendPolicy(max_transaction=25.0, blocked_vendors=["doordash"]),
)
# wallet.spend_tool → card payments, wallet.x402_tool → x402 API payments
tools = [wallet.spend_tool, wallet.x402_tool]
# Use with LangGraph
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-sonnet-4-6")
agent = create_react_agent(llm, tools=tools)
result = agent.invoke({"messages": [("user", "Buy $4.20 in API credits from Anthropic")]})
CrewAI Integration
pip install paygraph[crewai]
from crewai import Agent, Task, Crew
from paygraph import AgentWallet, SpendPolicy, MockGateway
wallet = AgentWallet(
gateway=MockGateway(auto_approve=True),
policy=SpendPolicy(max_transaction=25.0),
)
agent = Agent(
role="Purchasing Agent",
goal="Buy API credits when needed",
tools=[wallet.crewai_tool],
)
Policy Configuration
SpendPolicy accepts the following parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
max_transaction |
float |
50.0 |
Maximum amount per transaction (dollars) |
daily_budget |
float |
200.0 |
Maximum total spend per day |
allowed_vendors |
list[str] | None |
None |
If set, only these vendors are allowed (case-insensitive substring match) |
blocked_vendors |
list[str] | None |
None |
Vendors that are always denied (case-insensitive substring match) |
allowed_mccs |
list[int] | None |
None |
Merchant category code allowlist |
require_justification |
bool |
True |
Require non-empty justification string |
Environment Variables
| Variable | Required for | Description |
|---|---|---|
ANTHROPIC_API_KEY |
--live (default) |
Anthropic API key for Claude LLM |
OPENAI_API_KEY |
--live --model openai |
OpenAI API key for GPT LLM |
STRIPE_API_KEY |
--stripe or --stripe-mpp |
Stripe secret key (sk_test_ or sk_live_) |
STRIPE_CURRENCY |
Stripe gateways (optional) | Currency for card/SPT limits (default: usd) |
STRIPE_BILLING_COUNTRY |
--stripe (optional) |
Billing address country code (e.g. FR) |
STRIPE_CARDHOLDER_ID |
--stripe (optional) |
Reuse an existing cardholder ID |
STRIPE_MPP_PAYMENT_METHOD |
--stripe-mpp |
PaymentMethod id (pm_...) for SPT issuance |
STRIPE_MPP_GRANTEE |
--stripe-mpp |
Seller grantee id (typically profile_...) |
STRIPE_MPP_EXPIRES_IN_SECONDS |
--stripe-mpp (optional) |
SPT lifetime in seconds (default: 3600) |
EVM_PRIVATE_KEY |
x402 (EVM) | EVM private key for Base/Polygon USDC payments |
SVM_PRIVATE_KEY |
x402 (Solana) | Solana private key (base58) for USDC payments |
Copy .env.example to .env and fill in your keys:
cp .env.example .env
CLI
# Run simulated demo (no API keys needed)
paygraph demo
# Run live demo with a real LLM
export ANTHROPIC_API_KEY=sk-ant-...
paygraph demo --live
# Use OpenAI instead
export OPENAI_API_KEY=sk-...
paygraph demo --live --model openai
# Use Stripe Issuing for real card issuance
export STRIPE_API_KEY=sk_test_...
paygraph demo --live --stripe
# Use Stripe MPP (Shared Payment Tokens)
export STRIPE_API_KEY=sk_test_...
export STRIPE_MPP_PAYMENT_METHOD=pm_...
export STRIPE_MPP_GRANTEE=profile_...
paygraph demo --live --stripe-mpp
License
MIT
Metadata
Release files for paygraph 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 | |
|---|---|---|---|
| paygraph-0.2.0.tar.gz | 40.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| paygraph-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 73.1 kB
Release files / paygraph-0.2.0.tar.gz
| Download URL | paygraph-0.2.0.tar.gz |
|---|---|
| Size | 40.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
495a5044d314e66588dc2d169d389bfacb0d599025016e5cfb8c0d01d60e4c9d
|
|
BLAKE2b-256 checksum How to use checksums |
cf4ff12e5ba91deeffd36c524f549af87e190e0eca3efbe4eb7a7d74264fa097
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 23, 2026.
Transparency logRelease files / paygraph-0.2.0-py3-none-any.whl
| Download URL | paygraph-0.2.0-py3-none-any.whl |
|---|---|
| Size | 33.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
01ced5e7b4f9234bf2cbabb1446dac9203305ffa127611652a8c48b9a0a8f4c0
|
|
BLAKE2b-256 checksum How to use checksums |
b83c1ca99c878ae95cf4de3128653d8bdcf2868988eb6cf14b35af46edd7ce35
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 23, 2026.
Transparency log