Authentication
FairScale supports two authentication methods. Every request must use one.
Option A - API Key (Fairkey)
For subscribers on a paid plan. Pass your fairkey in the request header. Fairkeys have the format zpka_....
Header Format
fairkey: zpka_your_key_here
Rate limits and request quotas are enforced per key according to your plan tier.
| Plan | Requests/month | Requests/minute |
|---|---|---|
| Free | 1,000 | 10 |
| Builder | 20,000 | 100 |
| Scale | 50,000 | 300 |
| Pro | 100,000 | 600 |
Get a key at sales.fairscale.xyz.
Option B - x402 Pay-Per-Request
For agents and protocols that prefer usage-based billing with no subscription. No account required. Pay $0.005 USDC per request on Solana mainnet using the x402 protocol.
When a request arrives without a fairkey, the API returns HTTP 402 Payment Required with a PAYMENT-REQUIRED header containing payment instructions. The client signs and retries with a PAYMENT-SIGNATURE header. Payment is verified by Dexter and settled on-chain before the response is served.
Payment Details
| Field | Value |
|---|---|
| Price | $0.005 USDC per request |
| Network | Solana Mainnet |
| Asset | USDC (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v) |
| Facilitator | Dexter (https://x402.dexter.cash) |
| Receiving wallet | fairAUEuR1SCcHL254Vb3F3XpUWLruJ2a11f6QfANEN |
Using the Dexter SDK
import { wrapFetch } from "@dexterai/x402/client";
const x402Fetch = wrapFetch(fetch, {
walletPrivateKey: process.env.SOLANA_PRIVATE_KEY,
});
const res = await x402Fetch(
"https://agent-api.fairscale.xyz/v1/score?wallet=WALLET_ADDRESS"
);
const data = await res.json();
Using the Coinbase x402 SDK
import { wrapAxiosWithPayment, x402Client } from "@x402/axios";
import { registerExactSvmScheme } from "@x402/svm/exact/client";
const client = new x402Client();
registerExactSvmScheme(client, { keypair: yourSolanaKeypair });
const api = wrapAxiosWithPayment(
axios.create({
baseURL: "https://agent-api.fairscale.xyz",
}),
client
);
const res = await api.get("/v1/score?wallet=WALLET_ADDRESS");
Security Best Practices
✅ Do
- Store API keys in environment variables
- Use HTTPS for all requests
- Keep keys secret and secure
❌ Don't
- Expose keys in client-side code
- Share keys publicly
Error Responses
All errors follow a consistent shape:
{
"error": "error_code",
"message": "Human-readable description"
}
| HTTP Status | Error Code | Meaning |
|---|---|---|
| 400 | missing_wallet | No wallet address provided |
| 400 | invalid_wallet | Wallet address is not valid base58 (32–44 chars) |
| 400 | invalid_preset | Preset name not recognised |
| 400 | weights_must_sum_to_1 | Custom pillar weights do not sum to 1.0 (±0.02 tolerance) |
| 400 | missing_weights | POST to /v1/score/ai with no weights body |
| 400 | too_many_wallets | Batch request exceeds 25 wallets |
| 402 | Payment required | No fairkey and no x402 payment signature present |
| 502 | upstream_error | FairScale scoring engine unreachable |
402 Payment Required Example
{
"error": "Payment required",
"accepts": [
{
"scheme": "exact",
"network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"amount": "5000",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"payTo": "fairAUEuR1SCcHL254Vb3F3XpUWLruJ2a11f6QfANEN",
"maxTimeoutSeconds": 60
}
]
}