X402
Sign Authorization
Manually sign X402 authorization proofs for custom integrations
Sign Authorization
The Sign Authorization API lets you manually create X402 authorization signatures. Use this when you need full control over the transaction flow or are building custom integrations.
For most use cases, we recommend using X402 Fetch which handles authorization signing automatically.
When to Use Sign Authorization
- Building custom HTTP clients
- Integrating with non-standard transaction flows
- Need to inspect authorization details before sending
- Implementing retry logic with custom backoff
The response is a ready-to-use X-PAYMENT header as defined in X402 Core Concepts.
Endpoint
POST /api/sign-paymentRequest Body
{
"paymentRequirements": {
"accepts": [{
"scheme": "exact",
"network": "base-sepolia",
"maxAmountRequired": "250000",
"maxTimeoutSeconds": 300,
"resource": "https://api.example.com/endpoint",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"payTo": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7",
"extra": {
"name": "USD Coin",
"version": "2"
}
}]
},
"requestData": {
"url": "https://api.example.com/endpoint",
"method": "POST"
}
}Authorization Requirements Object
| Field | Type | Description |
|---|---|---|
accepts | array | Array of accepted authorization options |
accepts[].scheme | string | Authorization scheme: "exact" or "upto" |
accepts[].network | string | Blockchain network (e.g., "base-sepolia", "base") |
accepts[].maxAmountRequired | string | Maximum amount in atomic units |
accepts[].maxTimeoutSeconds | number | Authorization validity window |
accepts[].resource | string | The resource being accessed |
accepts[].asset | string | Token contract address (USDC) |
accepts[].payTo | string | Recipient wallet address |
accepts[].extra | object | Additional metadata |
Request Data Object
| Field | Type | Description |
|---|---|---|
url | string | Target URL for the request |
method | string | HTTP method (GET, POST, etc.) |
Response
{
"success": true,
"paymentHeader": "eyJ2ZXJzaW9uIjoxLCJwYXltZW50Ijp7...",
"amountPaid": 0.25,
"network": "base-sepolia",
"scheme": "exact"
}| Field | Type | Description |
|---|---|---|
success | boolean | Whether signing succeeded |
paymentHeader | string | Base64-encoded X402 authorization header |
amountPaid | number | Amount authorized in USD |
network | string | Network used for the transaction |
scheme | string | Authorization scheme used |
Using the Authorization Header
After signing, attach the header to your request:
curl https://api.example.com/endpoint \
-H "X-PAYMENT: eyJ2ZXJzaW9uIjoxLCJwYXltZW50Ijp7..." \
-H "Content-Type: application/json" \
-d '{"your": "data"}'Complete Flow Example
Step 1: Make Initial Request
import requests
# First, try the endpoint without authorization
response = requests.get("https://api.example.com/paid-endpoint")
if response.status_code == 402:
# Extract authorization requirements from response
payment_requirements = response.json()Step 2: Sign Authorization
# Sign the authorization with Agnic
sign_response = requests.post(
"https://api.agnic.ai/api/sign-payment",
headers={
"X-Agnic-Token": "agnic_tok_YOUR_TOKEN",
"Content-Type": "application/json"
},
json={
"paymentRequirements": payment_requirements,
"requestData": {
"url": "https://api.example.com/paid-endpoint",
"method": "GET"
}
}
)
payment_header = sign_response.json()["paymentHeader"]Step 3: Retry with Authorization
# Retry the request with authorization header
final_response = requests.get(
"https://api.example.com/paid-endpoint",
headers={
"X-PAYMENT": payment_header
}
)
print(final_response.json())JavaScript Example
async function makeRequest(url) {
// Step 1: Try request
let response = await fetch(url);
if (response.status === 402) {
const paymentRequirements = await response.json();
// Step 2: Sign authorization
const signResponse = await fetch('https://api.agnic.ai/api/sign-payment', {
method: 'POST',
headers: {
'X-Agnic-Token': 'agnic_tok_YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
paymentRequirements,
requestData: { url, method: 'GET' }
})
});
const { paymentHeader } = await signResponse.json();
// Step 3: Retry with authorization
response = await fetch(url, {
headers: { 'X-PAYMENT': paymentHeader }
});
}
return response.json();
}Authorization Schemes
Exact Scheme
The exact amount specified is authorized:
{
"scheme": "exact",
"maxAmountRequired": "250000" // Exactly $0.25
}UpTo Scheme
Authorize up to a maximum amount (actual cost may be less):
{
"scheme": "upto",
"maxAmountRequired": "1000000" // Up to $1.00
}See X402 Core Concepts for how these map to EIP-3009 and EIP-2612.
Error Handling
Insufficient Balance
{
"success": false,
"error": "insufficient_balance",
"error_description": "Wallet balance too low for transaction"
}Invalid Authorization Requirements
{
"success": false,
"error": "invalid_payment_requirements",
"error_description": "Missing required field: accepts"
}Spending Limit Exceeded
{
"success": false,
"error": "spending_limit_exceeded",
"error_description": "Transaction exceeds configured spending limit"
}