Skip to main content

Overview

What is x402

x402 is a new open payment protocol that enables instant, automatic stablecoin payments directly over HTTP.

Instant access, zero friction. x402 leverages the HTTP 402 Payment Required status code to enable direct stablecoin payments over the web. It replaces complex authentication and paywalls with a simple protocol: pay the network, get the resource. Whether for API monetization or digital content, x402 allows clients—from users to automated bots—to transact instantly without ever needing an account.

Why build with x402?

  • Zero-Friction Access: Eliminates the need for accounts, registrations, or complex OAuth flows. Access is granted instantly via payment, creating a stateless "pay-and-go" experience.
  • Built for AI Agents: Specifically optimized for machine-to-machine commerce, enabling autonomous agents to handle high-frequency microtransactions and pay-per-request API calls.
  • Instant Global Settlement: Utilizes internet-native stablecoin protocols to remove financial intermediaries, ensuring low-cost and immediate settlement for sellers.
  • Direct Monetization: Empowers developers and content creators to monetize granularly (e.g., per API call or article) while allowing buyers to access resources programmatically without subscriptions.

How it works

x402 enables programmatic payments over HTTP using a simple request-response flow. When a client requests a paid resource, the server responds with payment requirements, the client submits payment, and the server delivers the resource.

Key features

  • Gas subsidies: Make gas-free tokens (whitelisted tokens) transfers and payments on Gate Layer.
  • Multi-network support: Gate Layer support. Stay tuned for more networks.
  • SDKs: Production-ready client and server libraries.

Payment Flow

paymentflowdigram


API Access and Usage

Before using the API, you need to create a project and generate an API key in the developer portal.

Rate Limiting

To ensure service stability, we enforce rate limits on API requests.

  • Rate Limits:
    • Per Access Key: Each API endpoint is limited to 1 request per second per Access Key.
    • Global Limit: Each specific API action is limited to 50 requests per second globally.
  • Response: If these limits are exceeded, the API will return the following error code.
Error codeConstant NameDescription
10131RATE_LIMIT_GLOBAL_EXCEEDEDGlobal rate limit exceeded
10132RATE_LIMIT_PER_AK_EXCEEDEDPer access key rate limit exceeded
10133RATE_LIMIT_PER_ACTION_EXCEEDEDPer action rate limit exceeded

Supported networks and crypto

Gate Layer is now supported. Support for more networks is under development. Stay tuned.

Networkx402 APIChainIndex
Gate LayerSupported10088

Testnet Facilitator

The x402 testnet facilitator is available for testing and development:

Networkx402 APIChainIndex
Gate Layer TestnetSupported10087

Start

Developer Platform

To help you quickly access and manage API services, this guide introduces the main features and usage methods of the Developer Management Platform, including registration/login, API key creation, account security settings, and key management.


API List

Introduction

The x402 payment protocol is an HTTP-based payment protocol that enables developers running resource servers to accept payments from users using a variety of payment methods. The x402 Facilitator APIs enable you to facilitate payments using the x402 payment protocol by exposing three APIs.


Get basic information

Request address https://openapi.gateweb3.cc/api/v1/x402

Action

{"action": "x402.supported", "params": {}}

Request parameters

No

Response parameters

ParameterTypeDescription
kindsArrayArray of supported payment types
>x402VersionIntegerVersion of x402, e.g., 1
>schemeStringSettlement scheme, e.g., exact (one-time payment of a fixed amount)
>networkStringNetwork identifier, e.g., gatelayer
extensionsArray[String]Extension fields

Request example

curl -X POST https://openapi.gateweb3.cc/api/v1/x402 \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-H "X-Signature: your-signature" \
-H "X-Timestamp: $(date +%s%3N)" \
-H "X-Request-Id: ${REQUEST_ID}" \
-d '{
"action": "x402.supported",
"params": {
}
}'

Response example

{
"code": 0,
"msg": "",
"data": {
"kinds": [
{
"x402Version": 2,
"scheme": "exact",
"network": "gatelayer_testnet"
}
],
"extensions": []
},
"timestamp": 1769592841
}

Submit transaction

Request address https://openapi.gateweb3.cc/api/v1/x402

Action

{"action": "x402.settle", "params": {}}

Request parameters

ParameterTypeRequiredDescription
x402VersionIntegerYesx402 protocol version, e.g., 2
paymentPayloadObjectYesThe x402 payment payload carried by the client along with the request for the protected resource
>x402VersionIntegerYesx402 protocol version, e.g., 2
>acceptObjectYesThe settlement scheme to be used
>>schemeStringNoSettlement scheme, e.g., exact (one-time payment of a fixed amount). If empty, returns paymentRequirements.
>>networkStringNoNetwork identifier, e.g., gatelayer. If empty, returns paymentRequirements.
>payloadObjectYesPayment signature and authorization data object
>>signatureStringYesCryptographic signature
>>authorizationObjectYesAuthorization information
>>>fromStringYesPayer address
>>>toStringYesPayee address
>>>valueStringYesTransfer amount
>>>validAfterStringYesEffective time (Unix timestamp)
>>>validBeforeStringYesExpiration time (Unix timestamp)
>>>nonceStringYesRandom number (Nonce) to prevent replay attacks
paymentRequirementsObjectYesPayment details required to access the resource (Amount/Network/Asset/Payee, etc.)
>schemeStringYesSettlement scheme, e.g., exact (one-time payment of a fixed amount)
>networkStringYesNetwork identifier, e.g., gatelayer
>assetStringYesAsset identifier / Contract address (Network dependent)
>amountStringYesTransfer amount
>payToStringYesPayee / Recipient
>maxTimeoutSecondsIntegerNoMaximum waiting seconds after the authorization becomes valid

Response parameters

ParameterTypeDescription
successBooleanWhether the call was successful
payerStringPayer
transactionStringTransaction Hash
errorReasonStringReason for failure
networkStringNetwork

Request example

curl -X POST https://openapi.gateweb3.cc/api/v1/x402 \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-H "X-Signature: your-signature" \
-H "X-Timestamp: $(date +%s%3N)" \
-H "X-Request-Id: ${REQUEST_ID}" \
-d '{
"action": "x402.settle",
"params": {
"x402Version": 2,
"paymentPayload": {
"x402Version": 2,
"accepted": {
"scheme": "exact",
"network": "gatelayer_testnet"
},
"payload": {
"signature": "0x437830ba...",
"authorization": {
"from": "0x9F7236e6B4AAd75603C0DdB28dE5f12DeDe6E9D4",
"to": "0xe734bb6268fcd90756e36c30d6a5fce30569eb6f",
"value": "1111",
"validAfter": "0",
"validBefore": "1768978707",
"nonce": "0x50f24a..."
}
}
},
"paymentRequirements": {
"scheme": "exact",
"network": "gatelayer_testnet",
"asset": "0x9be8Df37C788B244cFc28E46654aD5Ec28a880AF",
"amount": "1111",
"payTo": "0xe734bb6268fcd90756e36c30d6a5fce30569eb6f",
"maxTimeoutSeconds": 3600
}
}
}'

Response example

Success:

{
"code": 0,
"msg": "",
"data": {
"success": true,
"payer": "0x9F7236e6B4AAd75603C0DdB28dE5f12DeDe6E9D4",
"transaction": "0xc36d65c0de132e47852830e27325552a669e2ab6604facc5bddd674ee3eb594c",
"network": "gatelayer_testnet"
},
"timestamp": 1769593302
}

Fail:

{
"code": 200,
"msg": "",
"data": {
"success": false,
"errorReason": "transaction reverted on-chain...",
"transaction": "",
"network": ""
},
"timestamp": 1768997786
}

Verify the transaction

Request address https://openapi.gateweb3.cc/api/v1/x402

Action

{"action": "x402.verify", "params": {}}

Request parameters

ParameterTypeRequiredDescription
x402VersionIntegerYesx402 protocol version, e.g., 2
paymentPayloadObjectYesThe x402 payment payload carried by the client along with the protected request
>x402VersionIntegerYesx402 protocol version, e.g., 2
>acceptObjectNoThe settlement scheme to be used
>>schemeStringNoSettlement scheme, e.g., exact (fixed amount one-time payment).
>>networkStringNoNetwork identifier, e.g., gatelayer.
>payloadObjectYesPayment signature and authorization data object
>>signatureStringYesCryptographic signature
>>authorizationObjectYesAuthorization information
>>>fromStringYesPayer address
>>>toStringYesPayee address
>>>valueStringYesTransfer amount
>>>validAfterStringYesEffective time (Unix timestamp)
>>>validBeforeStringYesExpiration time (Unix timestamp)
>>>nonceStringYesRandom number (Nonce) to prevent replay attacks
paymentRequirementsObjectYesPayment details required to access the resource (Amount/Network/Asset/Payee, etc.)
>schemeStringYesSettlement scheme, e.g., exact (fixed amount one-time payment)
>networkStringYesNetwork identifier, e.g., gatelayer
>assetStringYesAsset identifier / Contract address (Network dependent)
>amountStringYesTransfer amount
>payToStringYesPayee / Recipient
>maxTimeoutSecondsIntegerNoMaximum waiting seconds after the authorization becomes valid

Response parameters

ParameterTypeDescription
isValidbooleanWhether it is valid
invalidReasonstringReason for invalidity
payerstringIn valid cases, the payer address

Request example

curl -X POST https://openapi.gateweb3.cc/api/v1/x402 \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-H "X-Signature: your-signature" \
-H "X-Timestamp: $(date +%s%3N)" \
-H "X-Request-Id: ${REQUEST_ID}" \
-d '{
"action": "x402.verify",
"params": { ... }
}'

Response example

Success:

{
"code": 0,
"msg": "",
"data": {
"isValid": true,
"payer": "0x9F7236e6B4AAd75603C0DdB28dE5f12DeDe6E9D4"
},
"timestamp": 1769593299
}

Error Codes

Error CodeConstant NameDescription
0CodeSuccessSuccess
51001CodeInvalidPayloadPayment payload invalid or missing
51002CodeInvalidRequirementsPayment requirements invalid or missing
51003CodeMissingPayloadFieldMissing payload field
51101CodeUnsupportedNetworkUnsupported network
51201CodeTokenNotFoundToken not found
51301CodeInvalidExactPayloadInvalid exact payload format
51302CodeMissingSignatureMissing signature
51401CodeRecipientMismatchRecipient address mismatch
51402CodeInvalidAuthValueInvalid auth value format
51403CodeInvalidRequiredAmountInvalid required amount format
51404CodeInsufficientAmountInsufficient amount
51502CodeNonceAlreadyUsedNonce already used
51602CodeInsufficientBalanceInsufficient balance
51701CodeInvalidSignatureFormatInvalid signature format
51702CodeInvalidSignatureLengthInvalid signature length (should be 65 bytes)
51704CodeInvalidSignatureInvalid signature
51901CodeInvalidValueFormatInvalid value format
51902CodeInvalidValidAfterFormatInvalid validAfter format
51903CodeInvalidValidBeforeFormatInvalid validBefore format
51904CodeInvalidNonceFormatInvalid nonce format
51905CodeInvalidNonceLengthInvalid nonce length (should be 32 bytes)

Guidelines

Payment case

This guide will show you how to create a Go client that can initiate paid requests to x402-protected resources.

Prerequisites

Before starting, ensure you have:

  • A crypto wallet with USDC (any EVM-compatible wallet)
  • Go 1.24+ installed
  • A service requiring payment via x402

1. Install Dependencies

Add the x402 Go module to your project:

go get [github.com/gatechain/x402/go](https://github.com/gatechain/x402/go)

2. Create a Payment-enabled HTTP Client

The SDK automatically handles payment creation and signing using the chain's DOMAIN_SEPARATOR. For gatelayer_testnet, it uses the correct DOMAIN_SEPARATOR from the token contract to ensure valid signatures.

Here is a complete runnable example:

package main

import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"time"

x402 "[github.com/gatechain/x402/go](https://github.com/gatechain/x402/go)"
x402http "[github.com/gatechain/x402/go/http](https://github.com/gatechain/x402/go/http)"
evm "[github.com/gatechain/x402/go/mechanisms/evm/exact/client](https://github.com/gatechain/x402/go/mechanisms/evm/exact/client)"
evmsigners "[github.com/gatechain/x402/go/signers/evm](https://github.com/gatechain/x402/go/signers/evm)"
)

func main() {
// Get configuration from environment
privateKey := os.Getenv("EVM_PRIVATE_KEY")
if privateKey == "" {
fmt.Println("❌ EVM_PRIVATE_KEY environment variable is required")
os.Exit(1)
}

url := os.Getenv("SERVER_URL")
if url == "" {
url = "http://localhost:4021/weather"
}

fmt.Printf("🚀 Making paid request to: %s\n\n", url)

// Create EVM signer from private key
evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(privateKey)
if err != nil {
fmt.Printf("❌ Failed to create signer: %v\n", err)
os.Exit(1)
}

fmt.Printf("✅ Signer created: %s\n\n", evmSigner.Address())

// Create x402 client and register EVM scheme
// The SDK automatically uses the chain's DOMAIN_SEPARATOR for signing
// For gatelayer_testnet, it uses the correct DOMAIN_SEPARATOR from the chain
x402Client := x402.Newx402Client().
Register("gatelayer_testnet", evm.NewExactEvmScheme(evmSigner))

// Wrap HTTP client with payment handling
// PaymentRoundTripper automatically handles 402 responses and retries with payment
httpClient := x402http.WrapHTTPClientWithPayment(
http.DefaultClient,
x402http.Newx402HTTPClient(x402Client),
)

// Make request - payment is handled automatically
// The PaymentRoundTripper will:
// 1. Make the initial request
// 2. If it receives a 402 Payment Required response, it will:
// - Parse the payment requirements from the response
// - Create a payment payload using the chain's DOMAIN_SEPARATOR
// - Sign the payment payload
// - Retry the request with the payment header
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
fmt.Printf("❌ Failed to create request: %v\n", err)
os.Exit(1)
}

resp, err := httpClient.Do(req)
if err != nil {
fmt.Printf("❌ Request failed: %v\n", err)
os.Exit(1)
}
defer resp.Body.Close()

// Check response status
if resp.StatusCode != http.StatusOK {
body, _ := json.Marshal(map[string]interface{}{
"status": resp.StatusCode,
"message": "Request failed",
})
fmt.Printf("❌ HTTP %d: %s\n", resp.StatusCode, string(body))
os.Exit(1)
}

// Read response
var data map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
fmt.Printf("❌ Failed to decode response: %v\n", err)
os.Exit(1)
}

fmt.Println("✅ Response received:")
prettyJSON, _ := json.MarshalIndent(data, " ", " ")
fmt.Printf("%s\n\n", string(prettyJSON))

// Check payment response header
paymentHeader := resp.Header.Get("PAYMENT-RESPONSE")
if paymentHeader == "" {
paymentHeader = resp.Header.Get("X-PAYMENT-RESPONSE")
}

if paymentHeader != "" {
fmt.Println("💰 Payment settled successfully!")
fmt.Printf(" Payment header: %s\n", paymentHeader)
}
}

3. How It Works

The wrapped HTTP client automatically:

  1. Detects 402 Responses: When the server responds with 402 Payment Required, the client extracts payment requirements from the PAYMENT-REQUIRED header.
  2. Creates Payment Payload: The client creates a signed payment payload using the registered payment scheme.
  3. Retries with Payment: The client automatically retries the request with the X-PAYMENT header containing the payment payload.
  4. Handles Settlement: After successful payment verification, the server returns the resource and includes settlement confirmation in the PAYMENT-RESPONSE header.

Configuration

Environment Variables

For Gate Web3 OpenAPI authentication, set the following environment variables:

# Required
export GATE_WEB3_API_KEY="your-api-key"
export GATE_WEB3_API_SECRET="your-api-secret"

# Optional
export GATE_WEB3_PASSPHRASE="your-passphrase"
export GATE_WEB3_REAL_IP="your-real-ip" # Defaults to 127.0.0.1

Facilitator Configuration

The facilitator client defaults to using Gate Web3 OpenAPI:

facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{
URL: "[https://openapi-test.gateweb3.cc/api/v1/x402](https://openapi-test.gateweb3.cc/api/v1/x402)",
// Optional: Custom HTTP client
HTTPClient: &http.Client{
Timeout: 30 * time.Second,
},
// Optional: Custom auth provider
AuthProvider: &MyAuthProvider{},
})

Collection case

This guide will show you how to integrate x402 into your Go server to accept payments for APIs or services.

Prerequisites

Before starting, ensure you have:

  • A crypto wallet for receiving funds (any EVM-compatible wallet)
  • Go 1.24+ installed
  • An existing HTTP server (Gin, standard library, etc.)

1. Install Dependencies

Add the x402 Go module to your project:

go get [github.com/gatechain/x402/go](https://github.com/gatechain/x402/go)

2. Set Environment Variables

Set the required environment variables before running the server:

# Required: Wallet address to receive payments
export PAYEE_ADDRESS="0x1234567890123456789012345678901234567890"

# Required for Gate Web3 OpenAPI authentication
export GATE_WEB3_API_KEY="your-api-key"
export GATE_WEB3_API_SECRET="your-api-secret"

# Optional
export GATE_WEB3_PASSPHRASE="your-passphrase"
export GATE_WEB3_REAL_IP="your-real-ip"

3. Create a Payment-Protected Server

Here is a complete runnable example using the Gin framework:

package main

import (
"fmt"
"net/http"
"os"
"time"

"[github.com/gin-gonic/gin](https://github.com/gin-gonic/gin)"
x402 "[github.com/gatechain/x402/go](https://github.com/gatechain/x402/go)"
x402http "[github.com/gatechain/x402/go/http](https://github.com/gatechain/x402/go/http)"
ginmw "[github.com/gatechain/x402/go/http/gin](https://github.com/gatechain/x402/go/http/gin)"
evm "[github.com/gatechain/x402/go/mechanisms/evm/exact/server](https://github.com/gatechain/x402/go/mechanisms/evm/exact/server)"
)

func main() {
// Get receiving wallet address from environment variable
payTo := os.Getenv("PAYEE_ADDRESS")
if payTo == "" {
fmt.Println("❌ PAYEE_ADDRESS environment variable is required")
fmt.Println(" Example: export PAYEE_ADDRESS=0x1234567890123456789012345678901234567890")
os.Exit(1)
}

network := x402.Network("gatelayer_testnet") // Gate Layer testnet

fmt.Printf("🚀 Starting x402 payment server...\n")
fmt.Printf(" Payee address: %s\n", payTo)
fmt.Printf(" Network: %s\n", network)
fmt.Printf(" Facilitator: [https://openapi-test.gateweb3.cc/api/v1/x402](https://openapi-test.gateweb3.cc/api/v1/x402)\n\n")

r := gin.Default()

// Create facilitator client (Gate Web3 OpenAPI Testnet)
// The client will automatically use Gate Web3 authentication if environment variables are set:
// - GATE_WEB3_API_KEY
// - GATE_WEB3_API_SECRET
// - GATE_WEB3_PASSPHRASE (optional)
// - GATE_WEB3_REAL_IP (optional)
facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{
URL: "[https://openapi-test.gateweb3.cc/api/v1/x402](https://openapi-test.gateweb3.cc/api/v1/x402)",
})

// Apply x402 payment middleware
r.Use(ginmw.X402Payment(ginmw.Config{
Routes: x402http.RoutesConfig{
"GET /weather": {
Accepts: x402http.PaymentOptions{
{
Scheme: "exact",
PayTo: payTo,
Price: "$0.001", // Price in USD - automatically converts to USDC on the network
Network: network,
},
},
Description: "Get weather data for a city",
MimeType: "application/json",
},
},
Facilitator: facilitatorClient,
Schemes: []ginmw.SchemeConfig{
{Network: network, Server: evm.NewExactEvmScheme()},
},
SyncFacilitatorOnStart: true,
Timeout: 30 * time.Second,
}))

// Protected endpoint
r.GET("/weather", func(c *gin.Context) {
city := c.DefaultQuery("city", "San Francisco")
c.JSON(http.StatusOK, gin.H{
"city": city,
"weather": "sunny",
"temperature": 70,
"timestamp": time.Now().Format(time.RFC3339),
})
})

// Health check endpoint (no payment required)
r.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"status": "ok",
"version": "1.0.0",
})
})

fmt.Printf(" Server listening on http://localhost:4021\n")
if err := r.Run(":4021"); err != nil {
fmt.Printf("❌ Error starting server: %v\n", err)
os.Exit(1)
}
}

4. Test Your Integration

Start your server:

go run main.go

Make a request without payment:

curl http://localhost:4021/weather

The server will respond with 402 Payment Required, including payment instructions in the PAYMENT-REQUIRED header. Use a compatible client to complete payment and retry the request. After successful payment verification, the server will return your API response.

User Agreement

https://web3.gate.com/api-service-agreement

Last updated on 2026/02/06