---
title: Sign Authorization
description: 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.

<Callout type="info">
  For most use cases, we recommend using [X402 Fetch](/docs/x402/x402-fetch) which handles authorization signing automatically.
</Callout>

## 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](/docs/x402/core-concepts).

## Endpoint

```http
POST /api/sign-payment
```

## Request Body

```json
{
  "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

```json
{
  "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:

```bash
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

```python
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

```python
# 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

```python
# 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

```javascript
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:

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

### UpTo Scheme

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

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

See [X402 Core Concepts](/docs/x402/core-concepts#authorization-schemes) for how these map to EIP-3009 and EIP-2612.

## Error Handling

### Insufficient Balance

```json
{
  "success": false,
  "error": "insufficient_balance",
  "error_description": "Wallet balance too low for transaction"
}
```

### Invalid Authorization Requirements

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

### Spending Limit Exceeded

```json
{
  "success": false,
  "error": "spending_limit_exceeded",
  "error_description": "Transaction exceeds configured spending limit"
}
```

<Cards>
  <Card title="X402 Fetch" href="/docs/x402/x402-fetch" />
  <Card title="Balance" href="/docs/agnicpay-features/balance" />
</Cards>
