Nonagon Link — AI Agent Developer Guide
Integration guide for calling Nonagon Link paid APIs with USDC from AI agents
1. Overview
Nonagon Link is an agentic payment gateway compliant with the x402 protocol (Coinbase). AI agents can use paid APIs in the following two ways.
| Method | Best suited for | Required implementation |
|---|---|---|
| MCP (recommended) | MCP-capable AI such as Claude / GPT-4 | MCP server connection settings only |
| Direct x402 protocol integration | Custom agents / SDK embedding | Integration of @x402/fetch |
2. Prerequisites
- A Solana wallet for payments (USDC / SOL will be paid from this wallet). Use mainnet for production, or devnet to try things out at no cost
- USDC token holdings (production = real USDC on mainnet / testing = free airdrop on devnet)
- Node.js >= 20.0.0 (for the MCP method)
Preparing a Solana wallet and USDC for payments (the example below uses devnet for testing)
# Generate a keypair with the Solana CLI
solana-keygen new --outfile ~/.config/solana/devnet.json --no-bip39-passphrase
# Check the public key
solana-keygen pubkey ~/.config/solana/devnet.json
# Airdrop devnet SOL (for transaction fees)
solana airdrop 2 --url devnet
# devnet USDC is distributed automatically in the Nonagon Link test environment3. Method A: Connect via Nonagon Link (recommended)
MCP (Model Context Protocol) is a standard protocol that lets AI agents such as Claude / GPT-4 call external tools. Nonagon Link provides the Nonagon Link MCP server, allowing AI agents to call paid APIs transparently.
3-1. Setup
See the MCP setup guide for details.
For Claude Code:
.claude/settings.json:
{
"mcpServers": {
"nonagon-link": {
"command": "npx",
"args": ["tsx", "apps/nonagon_link/src/mcp/server.ts"],
"cwd": "/path/to/nonagon_link",
"env": {
"NONAGON_PRIVATE_KEY": "<private key of the Solana wallet used for payments (Base58)>",
"NONAGON_NETWORK": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"NONAGON_LINK_BASE_URL": "https://api.nnglink.ai",
"LOG_LEVEL": "info"
}
}
}
}Even when using HTTP stream, the runtime binds only to 127.0.0.1, so treat it as intended for local HTTP clients on the same machine. Do not expose it as a public endpoint over the network.
In HTTP stream mode, setting MCP_AUTH_TOKEN is required. Set MCP_AUTH_TOKEN on the server side, and always attach Authorization: Bearer <MCP_AUTH_TOKEN> on the client side as well.
Use a CSPRNG-generated secret of at least 32 bytes for MCP_AUTH_TOKEN. The published configuration examples only accept values of at least 43 base64url characters or at least 64 hex characters.
3-2. Available tools
pay_and_call
Pays USDC to a paid API and retrieves data.
| Parameter | Type | Required | Description |
|---|---|---|---|
proxyUrl | string (URL) | Required | URL of the API to call (HTTPS only) |
method | "GET" | "POST" | Optional | HTTP method (default: GET) |
body | object | Optional | Body of the POST request |
maxPaymentUsdc | number | Required | Maximum USDC allowed to be paid for this call (greater than 0, up to 10). If the amount requested by the 402 exceeds this, an error is returned without paying |
Usage example (request to Claude):
Please call the following API with pay_and_call:
- URL: https://api.nnglink.ai/api/proxy/weather-api/current
- Method: POST
- Body: { "city": "Tokyo" }
- Payment limit: 0.05 USDCExample response:
{
"success": true,
"data": {
"city": "Tokyo",
"temperature": 22,
"condition": "sunny"
},
"paymentInfo": {
"amountUsdc": "0.01",
"txSignature": "5xKt..."
}
}If paymentInfo is null, the response was returned without an additional payment, either because the API is free or an existing token was reused.
get_active_tokens
Retrieves summaries of currently valid masked tokens and their remaining validity time.
The public response returns only summaries containing maskedToken; raw token values are never exposed.
Example response:
{
"tokens": [
{
"maskedToken": "agt_abcd...mnop",
"proxyUrl": "https://api.nnglink.ai/api/proxy/weather-api/current",
"expiresAt": "2026-05-11T12:00:00Z",
"remainingMinutes": 45
}
]
}search_listings
Searches paid APIs on Nonagon Link and returns the proxyUrl, price, and parameter specification that can be passed to pay_and_call.
Note: To use this tool, the MCP server must be configured with NONAGON_LINK_BASE_URL (e.g. https://api.nnglink.ai).
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Optional | Search keyword (partial match on name / description, up to 200 characters) |
category | string | Optional | Filter by category (up to 40 characters) |
limit | number | Optional | Number of results (1–10, default 5) |
get_payment_history
Fetches the payment history for this MCP server's wallet (NONAGON_PRIVATE_KEY), including inline payments made via pay_and_call. History is scoped to the wallet, not the session.
Note: To use this tool, the MCP server must be configured with NONAGON_LINK_BASE_URL.
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | number | Optional | Number of records (1–50, default 10) |
status | string | Optional | Filter by payment status (settled / authorized / failed / refunded, etc.) |
get_spending
Fetches cumulative spending (settled + authorized) for this MCP server's wallet by period, with a per-currency breakdown. Useful for budget tracking and cap checks.
Note: To use this tool, the MCP server must be configured with NONAGON_LINK_BASE_URL.
| Parameter | Type | Required | Description |
|---|---|---|---|
period | string | Optional | Aggregation period: day (24h) / week (7d) / month (30d) / all (default) |
4. Method B: Direct x402 protocol integration
4-1. Overview of the x402 protocol
x402 is a micropayment protocol that uses the HTTP 402 (Payment Required) response.
Agent → Provider API → 402 Payment Required (PaymentRequirements)
Agent → Signs a USDC transfer transaction offline on Solana
Agent → Provider API + X-PAYMENT-* headers
Provider → Nonagon Link /verify → verification OK
Provider → Returns response
Provider → Nonagon Link /settle → submitted to the blockchain4-2. Integration using @x402/fetch
import { wrapFetchWithPayment, x402Client } from '@x402/fetch'
import { ExactSvmScheme } from '@x402/svm'
import { createKeyPairSignerFromBytes } from '@solana/kit'
import bs58 from 'bs58'
// 1. Initialize the Solana signer (private key of the payment wallet)
const privateKeyBytes = bs58.decode(process.env.NONAGON_PRIVATE_KEY!)
const signer = await createKeyPairSignerFromBytes(privateKeyBytes)
// 2. Initialize the x402 client
const client = new x402Client()
client.register(
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', // mainnet (devnet is solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1)
new ExactSvmScheme(signer)
)
// 3. Create a payment-enabled fetch
const payFetch = wrapFetchWithPayment(fetch, client)
// 4. Call the API (if a 402 is returned, it automatically pays and retries the request)
const response = await payFetch(
'https://api.nnglink.ai/api/proxy/weather-api/current',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ city: 'Tokyo' }),
}
)
const data = await response.json()
console.log(data)4-3. Facilitator API reference
GET /api/facilitator/supported
Returns information about supported blockchains and tokens.
Response:
{
"x402Version": 2,
"kinds": [
{
"scheme": "exact",
"network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"feePayer": "<facilitator fee payer public key>"
}
]
}POST /api/facilitator/verify
Verifies the Agent's partially signed transaction and issues a settleToken.
Request: Conforms to the x402 protocol specification (HMAC-SHA256 signature + nonce)
Response:
{
"valid": true,
"settleToken": "<JWT>"
}POST /api/facilitator/settle
Co-signs the verified transaction, submits it to the blockchain, and finalizes the payment.
Request: settleToken + HMAC-SHA256 signature
Response:
| Field | Description |
|---|---|
success | true (payment settled) |
transaction | Solana transaction signature |
network | e.g. solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp |
payer | Agent wallet address |
accessToken | Issued access token (agt_ format). Treat as a secret — never log it |
accessTokenExpiresAt | Access token expiry (ISO 8601) |
5. Searching for APIs
5-1. Listing search API
GET /api/listings?category=weather&sort=price_usdc&order=asc&limit=10| Parameter | Description |
|---|---|
q | Keyword search (partial match on name / description) |
category | Filter by category |
sort | Sort field (updated_at / price_usdc / name, default: updated_at) |
order | Sort order (asc / desc, default: desc) |
limit | Number of results (default: 20, max: 100) |
offset | Pagination (default: 0) |
Response:
{
"total": 42,
"limit": 20,
"offset": 0,
"listings": [
{
"id": "uuid",
"name": "Weather API",
"description": "API that returns the current weather",
"category": "weather",
"endpointUrl": "https://api.nnglink.ai/api/proxy/weathercorp/weather-api",
"httpMethod": "POST",
"priceUsdc": "0.010000",
"listingType": "proxy",
"timeoutSeconds": 60,
"providerId": "uuid",
"providerName": "WeatherCorp",
"hasSchema": true,
"hasExample": true,
"hasResponseSchema": true,
"hasResponseSample": true,
"coverage": null,
"updatedAt": "2026-05-10T09:00:00Z",
"openapiUrl": "/api/providers/<providerId>/listings/<id>/openapi"
}
]
}5-2. Provider public information API
GET /api/providers/{id}/publicRetrieves the Provider's public profile and the list of Listings it offers.
6. Calling the Proxy API
When calling a Provider API through the Nonagon Link proxy:
POST /api/proxy/{providerSlug}/{listingSlug}- Authentication: x402 protocol (automatic payment) or a pre-obtained access token
- The Provider's API Key is injected server-side by Nonagon Link (never exposed to the Agent)
- SSRF protection: private IPs / loopback are automatically rejected
7. Security considerations
Private key management
- Manage
NONAGON_PRIVATE_KEYvia environment variables and never hardcode it in code - Use Secrets Manager or similar in CI/CD
USDC balance
- Confirm you have a sufficient USDC balance before paying
- If the balance is insufficient, a 402 response is returned
Network
- devnet: for testing (free USDC)
- mainnet: for production (real USDC)
- Be careful not to mix up environments
8. Error codes
| HTTP | Code | Description |
|---|---|---|
| 402 | PAYMENT_REQUIRED | USDC payment required |
| 401 | UNAUTHORIZED | Authentication failed / invalid token |
| 403 | FORBIDDEN | Insufficient permissions |
| 404 | NOT_FOUND | Listing / Provider not found |
| 422 | NONCE_EXPIRED | nonce expired (5 minutes) |
| 429 | RATE_LIMITED | Rate limit exceeded |
| 502 | PROXY_PROVIDER_ERROR | The Provider API returned an error |
| 503 | SERVICE_UNAVAILABLE | Service temporarily unavailable |
9. SDKs and reference links
| Resource | URL |
|---|---|
| x402 protocol specification | https://www.x402.org |
| @x402/fetch (Agent SDK) | https://www.npmjs.com/package/@x402/fetch |
| @x402/svm (Solana) | https://www.npmjs.com/package/@x402/svm |
| MCP specification | https://modelcontextprotocol.io |
| MCP setup guide | /docs/mcp |