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.

MethodBest suited forRequired implementation
MCP (recommended)MCP-capable AI such as Claude / GPT-4MCP server connection settings only
Direct x402 protocol integrationCustom agents / SDK embeddingIntegration 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 environment

3. 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.

ParameterTypeRequiredDescription
proxyUrlstring (URL)RequiredURL of the API to call (HTTPS only)
method"GET" | "POST"OptionalHTTP method (default: GET)
bodyobjectOptionalBody of the POST request
maxPaymentUsdcnumberRequiredMaximum 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 USDC

Example 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).

ParameterTypeRequiredDescription
qstringOptionalSearch keyword (partial match on name / description, up to 200 characters)
categorystringOptionalFilter by category (up to 40 characters)
limitnumberOptionalNumber 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.

ParameterTypeRequiredDescription
limitnumberOptionalNumber of records (1–50, default 10)
statusstringOptionalFilter 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.

ParameterTypeRequiredDescription
periodstringOptionalAggregation 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 blockchain

4-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:

FieldDescription
successtrue (payment settled)
transactionSolana transaction signature
networke.g. solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
payerAgent wallet address
accessTokenIssued access token (agt_ format). Treat as a secret — never log it
accessTokenExpiresAtAccess 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
ParameterDescription
qKeyword search (partial match on name / description)
categoryFilter by category
sortSort field (updated_at / price_usdc / name, default: updated_at)
orderSort order (asc / desc, default: desc)
limitNumber of results (default: 20, max: 100)
offsetPagination (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}/public

Retrieves 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_KEY via 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

HTTPCodeDescription
402PAYMENT_REQUIREDUSDC payment required
401UNAUTHORIZEDAuthentication failed / invalid token
403FORBIDDENInsufficient permissions
404NOT_FOUNDListing / Provider not found
422NONCE_EXPIREDnonce expired (5 minutes)
429RATE_LIMITEDRate limit exceeded
502PROXY_PROVIDER_ERRORThe Provider API returned an error
503SERVICE_UNAVAILABLEService temporarily unavailable

9. SDKs and reference links

ResourceURL
x402 protocol specificationhttps://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 specificationhttps://modelcontextprotocol.io
MCP setup guide/docs/mcp

当サイトでは、利用状況の把握と改善のためにアクセス解析 (Google アナリティクス) を使用します。「同意する」を選ぶと、閲覧ページ等の計測情報が Google LLC(米国)へ送信されます。詳細: プライバシーポリシー / 利用者情報の外部送信について