AgnicPay

Sign Payment

Manually sign X402 payment proofs for custom integrations

Sign Payment

The Sign Payment API lets you manually create X402 payment signatures. Use this when you need full control over the payment flow or are building custom integrations.

For most use cases, we recommend using X402 Fetch which handles payment signing automatically.

When to Use Sign Payment

  • Building custom HTTP clients
  • Integrating with non-standard payment flows
  • Need to inspect payment details before sending
  • Implementing retry logic with custom backoff

Endpoint

POST /api/sign-payment

Request 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"
  }
}

Payment Requirements Object

FieldTypeDescription
acceptsarrayArray of accepted payment options
accepts[].schemestringPayment scheme: "exact" or "upto"
accepts[].networkstringBlockchain network (e.g., "base-sepolia", "base")
accepts[].maxAmountRequiredstringMaximum amount in atomic units
accepts[].maxTimeoutSecondsnumberPayment validity window
accepts[].resourcestringThe resource being paid for
accepts[].assetstringToken contract address (USDC)
accepts[].payTostringRecipient wallet address
accepts[].extraobjectAdditional metadata

Request Data Object

FieldTypeDescription
urlstringTarget URL for the payment
methodstringHTTP method (GET, POST, etc.)

Response

{
  "success": true,
  "paymentHeader": "eyJ2ZXJzaW9uIjoxLCJwYXltZW50Ijp7...",
  "amountPaid": 0.25,
  "network": "base-sepolia",
  "scheme": "exact"
}
FieldTypeDescription
successbooleanWhether signing succeeded
paymentHeaderstringBase64-encoded X402 payment header
amountPaidnumberAmount paid in USD
networkstringNetwork used for payment
schemestringPayment scheme used

Using the Payment 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 payment
response = requests.get("https://api.example.com/paid-endpoint")
 
if response.status_code == 402:
    # Extract payment requirements from response
    payment_requirements = response.json()

Step 2: Sign Payment

# Sign the payment with AgnicPay
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 Payment

# Retry the request with payment header
final_response = requests.get(
    "https://api.example.com/paid-endpoint",
    headers={
        "X-PAYMENT": payment_header
    }
)
 
print(final_response.json())

JavaScript Example

async function makePayment(url) {
  // Step 1: Try request
  let response = await fetch(url);
 
  if (response.status === 402) {
    const paymentRequirements = await response.json();
 
    // Step 2: Sign payment
    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 payment
    response = await fetch(url, {
      headers: { 'X-PAYMENT': paymentHeader }
    });
  }
 
  return response.json();
}

Payment Schemes

Exact Scheme

The exact amount specified is paid:

{
  "scheme": "exact",
  "maxAmountRequired": "250000"  // Exactly $0.25
}

UpTo Scheme

Pay up to a maximum amount (actual cost may be less):

{
  "scheme": "upto",
  "maxAmountRequired": "1000000"  // Up to $1.00
}

Error Handling

Insufficient Balance

{
  "success": false,
  "error": "insufficient_balance",
  "error_description": "Wallet balance too low for payment"
}

Invalid Payment Requirements

{
  "success": false,
  "error": "invalid_payment_requirements",
  "error_description": "Missing required field: accepts"
}

Spending Limit Exceeded

{
  "success": false,
  "error": "spending_limit_exceeded",
  "error_description": "Payment exceeds configured spending limit"
}

On this page