How to use Credit
Credit Mode pre-charges USDC and deducts credits off-chain each time you call an API. Because no on-chain transaction occurs per request, you incur no gas fees — making this mode well-suited for high-frequency calls and predictable workloads.
- Base URL:
https://x402.nodit.io - For a comparison of the two payment modes, see x402 Overview — Payment Methods.
Implementation follows these 5 steps.
- SIWx Authentication → JWT Issuance — Sign a message with your wallet and receive a JWT.
- Call API — Call the API with the JWT in the header. Credits are deducted off-chain if the balance is sufficient.
- Charge Credits — If the balance is insufficient, receive a
402response, generate a PAYMENT-SIGNATURE, and charge credits. - Retry API Call — After charging, call the same API again in the same way.
- Check Balance — Query the current credit balance.
Step 1. SIWx Authentication​
Before calling the API, issue a JWT through wallet-signature-based authentication (SIWx). Sign a message with your private key and submit it to POST /auth to receive a JWT. The issued JWT is valid for 1 hour and is used in the Authorization header for all subsequent API calls.
Step 1-1. Compose SIWx Message​
For EVM wallets, compose a SIWE message in the format below. Join each line with \n.
{DOMAIN} wants you to sign in with your Ethereum account:
{WALLET_ADDRESS}
Sign in to x402.nodit.io
URI: https://x402.nodit.io
Version: 1
Chain ID: {CHAIN_ID}
Nonce: {NONCE}
Issued At: {ISO_8601}
Expiration Time: {ISO_8601_PLUS_10MIN}
{DOMAIN}: The domain requesting the signature (e.g.,x402.nodit.io){WALLET_ADDRESS}: The EVM wallet address used for signing{CHAIN_ID}: The Chain ID of the network used for payment (e.g., Base Mainnet →8453){NONCE}: A 16-byte random hex string to prevent replay attacks{ISO_8601}: The ISO 8601 timestamp at the time of signing (e.g.,2025-01-01T00:00:00Z){ISO_8601_PLUS_10MIN}: The expiration time, 10 minutes after the signing timestamp
Joining each line of the template above with \n produces the following string.
x402.nodit.io wants you to sign in with your Ethereum account:\n0xAbC1234567890DEF1234567890AbCdEf12345678\n\nSign in to x402.nodit.io\n\nURI: https://x402.nodit.io\nVersion: 1\nChain ID: 8453\nNonce: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4\nIssued At: 2025-01-01T00:00:00Z\nExpiration Time: 2025-01-01T00:10:00Z
Step 1-2. Sign Message​
Sign the composed message with your private key. The signing method differs by chain.
| Chain | Signing Method | Signature Format |
|---|---|---|
| EVM | wallet.signMessage(message) (EIP-191 personal_sign) | Hex string |
| Solana | nacl.sign.detached(messageBytes, secretKey) | Base58-encoded string |
The signature is used in the signature field of the POST /auth request in the next step.
Step 1-3. Issue JWT​
Send the message and signature to POST /auth to receive a JWT in the accessToken field.
{
"message": "{SIWE_OR_SIWS_MESSAGE}",
"signature": "{SIGNATURE}"
}
{
"accessToken": "{JWT}"
}
Step 2. Call API​
After issuing a JWT, attach it to the Authorization header and call the API. If the credit balance is sufficient, credits are deducted off-chain and the API response is returned.
| API Type | URL Pattern |
|---|---|
| Web3 Data API | /credit/v1/{CHAIN}/{NETWORK}/{CATEGORY}/{METHOD} |
| Node API (JSON-RPC) | /credit/{CHAIN}/{NETWORK}/json-rpc |
The following is an example of a Web3 Data API call.
curl --request POST \
--url https://x402.nodit.io/credit/v1/ethereum/mainnet/blockchain/getBlockByHashOrNumber \
--header 'Authorization: Bearer {JWT}' \
--header 'Content-Type: application/json' \
--data '{"block": "latest"}'
If the balance is sufficient, credits are deducted and a 200 response is returned. If the balance is insufficient, a 402 Payment Required response is returned. In that case, charge credits following Step 3 below, then retry the same request.
Step 3. Charge Credits​
When the balance is insufficient, the API returns 402 Payment Required. Send a charge request to receive payment terms, generate a PAYMENT-SIGNATURE, and submit the retry request to charge credits. The minimum charge amount is 0.01 USDC (10,000 atomic units).
Step 3-1. Request Charge — Receive 402​
Send a charge request as shown below. The server returns 402 Payment Required.
curl --request POST \
--url https://x402.nodit.io/credit/charge \
--header 'Authorization: Bearer {JWT}' \
--header 'Content-Type: application/json' \
--data '{"amount": "1000000"}'
HTTP/1.1 402 Payment Required
Content-Type: application/json
PAYMENT-REQUIRED: eyJ4NDAyV...
Step 3-2. Select Payment Network​
Base64-decode the PAYMENT-REQUIRED header and select the accept object for the network you want to use for payment.
const paymentRequired = JSON.parse(
Buffer.from(res402.headers['payment-required'], 'base64').toString()
);
The decoded accepts array looks like the following.
{
"x402Version": 2,
"accepts": [
{
"network": "eip155:8453",
"asset": "0x...",
"payTo": "0x...",
"amount": "1000000",
"maxTimeoutSeconds": 3600,
"scheme": "exact",
"extra": { "name": "USDC", "version": "2" }
},
{
"network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"asset": "...",
"payTo": "...",
"amount": "1000000",
"scheme": "exact",
"extra": { "name": "USDC", "version": "1", "feePayer": "..." }
}
]
}
Step 3-3. Generate PAYMENT-SIGNATURE​
The signing method differs by the selected network. After signing, compose the payload in the JSON structure below and base64-encode it.
Sign using EIP-3009 TransferWithAuthorization.
{
"x402Version": 2,
"resource": { "url": "https://x402.nodit.io/credit/charge", "description": "Credit charge", "mimeType": "application/json" },
"accepted": { "network": "{NETWORK}", "asset": "{ASSET_ADDRESS}", "payTo": "{PAYTO_ADDRESS}", "amount": "{AMOUNT}", "scheme": "exact", "extra": { "name": "USDC", "version": "{VERSION}" } },
"payload": {
"signature": "{EIP_712_SIGNATURE}",
"authorization": {
"from": "{WALLET_ADDRESS}",
"to": "{PAYTO_ADDRESS}",
"value": "{AMOUNT}",
"validAfter": "0",
"validBefore": "{VALID_BEFORE}",
"nonce": "{NONCE}"
}
}
}
For details on generating the signature, see the EIP-3009 specification.
The PAYMENT-SIGNATURE is valid for 300 seconds. Submit the retry request within this window after generating the signature.
Step 3-4. Retry with PAYMENT-SIGNATURE​
Base64-encode the composed payload, attach it to the payment-signature header, and submit the retry request.
curl --request POST \
--url https://x402.nodit.io/credit/charge \
--header 'Authorization: Bearer {JWT}' \
--header 'Content-Type: application/json' \
--header 'PAYMENT-SIGNATURE: {BASE64_ENCODED_PAYMENT_PAYLOAD}' \
--data '{"amount": "1000000"}'
When the charge completes, the response returns the updated balance and transaction hash.
{
"balance": 1000000,
"paymentResponse": { "txHash": "{TX_HASH}" }
}
Step 4. Retry API Call​
After the charge completes, call the API again in the same way as Step 2. The charged credits are deducted off-chain and a 200 response is returned.
curl --request POST \
--url https://x402.nodit.io/credit/v1/ethereum/mainnet/blockchain/getBlockByHashOrNumber \
--header 'Authorization: Bearer {JWT}' \
--header 'Content-Type: application/json' \
--data '{"block": "latest"}'
Step 5. Check Balance​
Query the current credit balance via GET /credit/balance. Attach the JWT to the Authorization header.
curl --request GET \
--url https://x402.nodit.io/credit/balance \
--header 'Authorization: Bearer {JWT}'
{
"balance": 1000000
}
For Pay-Per-Use Mode, which settles each request on-chain without pre-charging, see How to use Pay-Per-Use.