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

Authorization Requirements Object

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

Request Data Object

FieldTypeDescription
urlstringTarget URL for the request
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 authorization header
amountPaidnumberAmount authorized in USD
networkstringNetwork used for the transaction
schemestringAuthorization 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"
}