Call draconic21's x402 API from Python
The official x402 Python SDK (PyPI package x402) wraps a requests.Session so a 402 challenge gets signed and paid automatically — here's the exact working code against draconic21's live SEC EDGAR route.
Which package
Install x402 from PyPI (not the older, separate x402-requests package, which this unified SDK supersedes):
pip install "x402[evm,requests]"
This pulls in eth_account for EVM signing and requests for the HTTP session wrapper. An httpx-based async variant is also available via the httpx extra if you'd rather not block on I/O.
Prerequisites
- A wallet on the Base network (chain id 8453) funded with a little USDC — a few dollars covers hundreds of calls at these prices.
- An x402 v2 client library (installed per snippet below) that can sign the "exact" EVM payment scheme (EIP-3009, gasless — no ETH for gas needed on your side).
- Your wallet's private key available to your own process/agent — never share it, never commit it, never paste it into a chat with an AI you don't fully trust with funds.
The code
Dry-run (no key set) prints the payment challenge and pays nothing; set BUYER_PRIVATE_KEY to actually pay $0.02 for one edgar_filings call.
"""Python x402 client for draconic21's paid routes.
Uses the OFFICIAL x402 v2 Python SDK on PyPI: package name is just `x402`
(the standalone `x402-requests` package is superseded by this one).
Install:
pip install "x402[evm,requests]"
Prerequisites:
- A Base-network wallet funded with a little USDC (this route costs
$0.02; fund with $1-2 for headroom).
- Your wallet's private key in an env var. Never commit it or share it.
Run it:
DRY RUN (no key, safe, shows the payment challenge, pays nothing):
python call_paid_route.py
PAY FOR REAL ($0.02 USDC on Base, non-refundable):
BUYER_PRIVATE_KEY=0x... python call_paid_route.py
Endpoint used below: POST /v1/edgar_filings ($0.02) -- recent SEC filings for
a ticker. Swap ORIGIN/ROUTE/BODY for any other draconic21 route (see
https://draconic21-x402-api.onrender.com/openapi.json).
"""
import json
import os
import requests
ORIGIN = os.environ.get("DRACONIC21_ORIGIN", "https://draconic21-x402-api.onrender.com")
ROUTE = "/v1/edgar_filings"
BODY = {"ticker": "AAPL", "limit": 3}
def dry_run() -> None:
"""Probe the route, print the exact payment requirements, pay nothing."""
resp = requests.post(ORIGIN + ROUTE, json=BODY, timeout=15)
if resp.status_code != 402:
raise RuntimeError(f"expected HTTP 402 Payment Required, got {resp.status_code}")
# The x402 SDK's own payment-required parser reads BOTH the
# PAYMENT-REQUIRED header and the JSON body (v2 puts the structured
# challenge in the header; some fields also echo in the body).
from x402.http.x402_http_client import x402HTTPClientSync
from x402 import x402ClientSync
probe = x402HTTPClientSync(x402ClientSync())
body = resp.json() if resp.content else None
required = probe.get_payment_required_response(resp.headers.get, body)
accept = next((a for a in required.accepts if a.network == "eip155:8453"), required.accepts[0])
print("HTTP 402 Payment Required. Set BUYER_PRIVATE_KEY to actually pay.")
print(
json.dumps(
{
"network": accept.network,
"price": getattr(accept, "amount", None) or getattr(accept, "max_amount_required", None),
"asset": accept.asset,
"pay_to": accept.pay_to,
},
indent=2,
)
)
def pay_and_call(private_key: str) -> None:
"""Actually sign and settle the $0.02 payment, then print the result."""
from eth_account import Account
from x402 import x402ClientSync
from x402.http.clients import x402_requests
from x402.mechanisms.evm.signers import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
account = Account.from_key(private_key)
client = x402ClientSync()
register_exact_evm_client(client, EthAccountSigner(account))
session = x402_requests(client) # wraps requests.Session: 402 -> sign -> retry, transparently
resp = session.post(ORIGIN + ROUTE, json=BODY, timeout=15)
resp.raise_for_status()
print(json.dumps(resp.json(), indent=2))
if __name__ == "__main__":
key = os.environ.get("BUYER_PRIVATE_KEY")
if key:
pay_and_call(key)
else:
dry_run()
# Dry run (no wallet, no payment):
python call_paid_route.py
# Pay for real ($0.02 USDC on Base):
BUYER_PRIVATE_KEY=0x... python call_paid_route.py
Routes you can call this way
Every example below targets one specific route to keep the snippet runnable, but the same client works against any draconic21 x402 route. Full list and schemas: /openapi.json.
| Route | Price | What it does |
|---|---|---|
POST /v1/sanctions_screen | $0.006 | OFAC SDN name/wallet screening |
POST /v1/sanctions_delta | $0.008 | OFAC SDN list changes since a date |
POST /v1/edgar_filings | $0.02 | Recent SEC filings by ticker/CIK |
POST /v1/edgar_company_facts | $0.02 | Key XBRL facts by ticker/CIK |
POST /v1/edgar_fulltext_search | $0.02 | Full-text search of SEC filings since 2001 |
POST /v1/signal_latest | $0.03 | Daily agent-economy signal brief |
POST /v1/signal_delta | $0.05 | What changed in Signal since a date |