/category, /tag, /page) do not return full HTML without payment.
Use this documentation, llms.txt, and
pricing.json first.
Welcome to Free3D.io's AI-friendly API. We support AI agents and bots, but require payment for access to our content catalog. Payments are accepted exclusively via the open x402 protocol (USDC / PYUSD on Base or Ethereum) or via a persistent API key.
| Plan | Price | Rate Limit | Best For |
|---|---|---|---|
| Pay Per Request | $1.00 per request (USDC / PYUSD) | No limit | One-time access, testing |
| Basic API Key | $50/month | 100/hour, 1,000/day | Small AI agents |
| Pro API Key | $200/month | 1,000/hour, 20,000/day | Production agents |
| Enterprise | Custom | 10,000/hour, 500,000/day | Large-scale training |
When your bot accesses our site without a valid payment header, you receive a spec-compliant response:
HTTP/1.1 402 Payment Required
Content-Type: application/json
PAYMENT-REQUIRED: <base64-encoded PaymentRequired JSON>
{
"x402Version": 2,
"error": "PAYMENT-SIGNATURE header is required",
"resource": { "url": "https://free3d.io/...", "mimeType": "application/json" },
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"amount": "1000000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x...",
"maxTimeoutSeconds": 300,
"extra": { "name": "USDC", "version": "2" }
}
]
}
Purchase a monthly subscription and use your API key for all requests.
curl -H "X-API-Key: x402_your_api_key_here" https://free3d.io/
Contact: free3dio@pm.me โ to purchase API keys (paid in USDC/PYUSD).
Sign an EIP-3009 TransferWithAuthorization off-chain and send it in the PAYMENT-SIGNATURE header. No gas paid by the client.
import base64, json, secrets, time, requests
from eth_account import Account
from eth_account.messages import encode_typed_data
# 1. Read payment requirements from PAYMENT-REQUIRED header (or response body).
r = requests.get("https://free3d.io/")
pr = json.loads(base64.b64decode(r.headers["PAYMENT-REQUIRED"]))
chosen = pr["accepts"][0] # e.g. Base USDC
# 2. Build EIP-3009 authorization.
auth = {
"from": "0xYourWallet",
"to": chosen["payTo"],
"value": chosen["amount"],
"validAfter": int(time.time()),
"validBefore": int(time.time()) + chosen["maxTimeoutSeconds"],
"nonce": "0x" + secrets.token_hex(32),
}
# 3. Sign EIP-712 (TransferWithAuthorization).
typed = {
"types": {
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "verifyingContract", "type": "address"},
],
"TransferWithAuthorization": [
{"name": "from", "type": "address"},
{"name": "to", "type": "address"},
{"name": "value", "type": "uint256"},
{"name": "validAfter", "type": "uint256"},
{"name": "validBefore", "type": "uint256"},
{"name": "nonce", "type": "bytes32"},
],
},
"primaryType": "TransferWithAuthorization",
"domain": {
"name": chosen["extra"]["name"],
"version": chosen["extra"]["version"],
"chainId": int(chosen["network"].split(":")[1]),
"verifyingContract": chosen["asset"],
},
"message": auth,
}
signed = Account.sign_typed_data(full_message=typed, private_key="0xYourPrivKey")
# 4. Build PaymentPayload (x402 v2 ยง5.2) and send.
payload = {
"x402Version": 2,
"resource": pr["resource"],
"accepted": chosen,
"payload": {
"signature": signed.signature.hex(),
"authorization": auth,
},
}
headers = {
"PAYMENT-SIGNATURE": base64.b64encode(json.dumps(payload).encode()).decode()
}
print(requests.get("https://free3d.io/", headers=headers).status_code)
Send 1 USDC/USDT/PYUSD to the wallet listed in accepts[i].payTo, then either retry the request with the transaction hash, or exchange it for a one-time access token.
# Direct retry with header:
curl -H "X-Payment: 0xYourTxHash:base" https://free3d.io/
# Two-step: verify on-chain, then use one-time access token (15 min):
curl -X POST https://free3d.io/x402/verify \
-H "Content-Type: application/json" \
-d '{"tx_hash":"0xYourTxHash","network":"base","resource_id":"/"}'
# โ {"access_token":"uuid-token"}
curl -H "X-Access-Token: uuid-token" https://free3d.io/
import requests
# With API key:
headers = {"X-API-Key": "x402_your_key"}
r = requests.get("https://free3d.io/", headers=headers)
if r.status_code == 200:
print("Access granted!")
elif r.status_code == 402:
print("Payment required:", r.json())
elif r.status_code == 429:
print("Rate limit exceeded")
const axios = require('axios');
async function accessWithApiKey() {
try {
const r = await axios.get('https://free3d.io/', {
headers: { 'X-API-Key': 'x402_your_key' },
});
console.log('Access granted!', r.data);
} catch (err) {
if (err.response?.status === 402) {
console.log('Payment required:', err.response.data);
} else if (err.response?.status === 429) {
console.log('Rate limit exceeded');
}
}
}
curl -H "X-API-Key: x402_your_key" https://free3d.io/ curl -H "X-API-Key: x402_your_key" https://free3d.io/model/chair/abc123?a=download&do=get
| Code | Meaning | Action |
|---|---|---|
200 | Success | Access granted |
402 (preferred) or 401 | Payment Required | Decode PAYMENT-REQUIRED (base64 JSON) or read the JSON body; check X-X402-Status: payment_required |
429 | Rate Limit Exceeded | Wait or upgrade plan |
401 | Invalid API Key (non-AI clients) | Renew or replace your API key |
Successful payments (402 โ 200) are logged to logs/x402_conversions.log:
[2026-05-07 10:31:00] CONVERSION_200 | method: api_key | resource: / | id: x402_key_123 | IP: 1.2.3.4 | UA: CustomAgent/1.0 [2026-05-07 10:32:00] CONVERSION_200 | method: eip3009 | resource: / | id: eip3009_signature | IP: 1.2.3.4 | UA: x402-fetch/0.4 [2026-05-07 10:33:00] CONVERSION_200 | method: legacy | resource: /tag/character | id: 0xabc...:base | IP: 1.2.3.4 | UA: ChatGPT-User/1.0 [2026-05-07 10:34:00] CONVERSION_200 | method: token | resource: / | id: uuid-token | IP: 1.2.3.4 | UA: ClaudeBot/1.0
Methods tracked: api_key, eip3009, legacy, token.
Errors are logged to logs/x402.log.
/x402/verify are single-use and expire in 15 minutes.Questions: free3dio@pm.me
Machine-readable pricing: /x402/pricing.json
Powered by x402 Protocol v2 | Back to Free3D.io