Onchor API
API marketplace on Solana. List your APIs, let developers and AI agents discover and purchase them with USDC. 5% marketplace fee. Fully on-chain deposits via Anchor program with PDA-controlled vaults.
https://api.onchor.xyzAll endpoints return JSON. All request bodies must be
Content-Type: application/json.Quickstart
Start selling your API in 3 steps.
Create a seller account
Register with your email and set your Solana wallet address to receive USDC payments.
# Register
curl -X POST https://api.onchor.xyz/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"name": "My API Company",
"email": "seller@example.com",
"password": "securepassword123"
}'
# Response includes your JWT and API key
{
"access_token": "eyJhbGciOi...",
"merchant_id": "uuid-here",
"api_key": "a1b2c3d4...64chars"
}Set your Solana wallet
Configure the wallet where you want to receive USDC revenue.
curl -X PATCH https://api.onchor.xyz/api/merchants/me \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"wallet_solana": "YourSolanaPublicKey..."
}'List your API
Create a marketplace listing. Buyers and AI agents can discover and purchase access.
curl -X POST https://api.onchor.xyz/api/marketplace/seller/listings \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Weather API",
"category": "data",
"base_url": "https://api.weather.io/v1",
"pricing_model": "per_call",
"price_per_call_usdc": 0.01,
"monthly_call_limit": 10000
}'Authentication
Onchor supports three ways to authenticate:
JWT tokens expire after 24 hours. API keys don't expire but can be regenerated (which invalidates the previous key). All authenticated endpoints accept either method.
Server-to-Server (API Key)
Use your API key to call the Onchor API from your own server without a browser or wallet. This is useful for automating listing management, pulling stats into your own dashboard, or integrating Onchor into a CI/CD pipeline.
Find your API key in Dashboard → Settings → Server-to-Server API Key.
# Example: list your API listings from your server curl https://api.onchor.xyz/api/marketplace/seller/listings \ -H "X-API-Key: YOUR_API_KEY"
# Example: get your dashboard stats curl https://api.onchor.xyz/api/dashboard/stats \ -H "X-API-Key: YOUR_API_KEY"
X-API-Key or Authorization: Bearer {jwt} — both work interchangeably.Base URL
https://api.onchor.xyz
Sandbox & Testing
Onchor runs on Solana devnet for testing. All marketplace endpoints work identically — the only difference is USDC deposits use devnet tokens (free, no real money).
1. Use the production API at
https://api.onchor.xyz — all listing and discovery endpoints are free2. Create a listing, make a purchase, and poll the status — you'll get a deposit address on Solana
3. For end-to-end testing with actual USDC transfers, use small amounts ($1-2 USDC) on mainnet
Test the API without auth
These endpoints are fully public and require no setup. Try them now:
# Browse available APIs curl https://api.onchor.xyz/api/marketplace/listings # Search by keyword curl "https://api.onchor.xyz/api/marketplace/listings?q=weather" # Get available categories curl https://api.onchor.xyz/api/marketplace/categories # Get a specific listing curl https://api.onchor.xyz/api/marketplace/listings/weather-api
Full test flow (seller + buyer)
Register a test account
Create a seller account with a test email. No email verification needed.
curl -X POST https://api.onchor.xyz/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"name": "Test Seller",
"email": "test@example.com",
"password": "testpass123"
}'Create a listing
List a test API using the JWT from step 1.
curl -X POST https://api.onchor.xyz/api/marketplace/seller/listings \
-H "Authorization: Bearer YOUR_JWT" \
-H "Content-Type: application/json" \
-d '{
"name": "Test API",
"category": "other",
"base_url": "https://httpbin.org",
"pricing_model": "per_call",
"price_per_call_usdc": 0.001,
"monthly_call_limit": 100
}'Verify your listing is public
curl https://api.onchor.xyz/api/marketplace/listings?q=test
Initiate a purchase
curl -X POST https://api.onchor.xyz/api/marketplace/purchase \
-H "Content-Type: application/json" \
-d '{
"listing_id": "YOUR_LISTING_ID",
"buyer_identifier": "buyer@test.com"
}'
# You'll get a deposit_address and subscription_id
# Send USDC to the deposit address to complete the purchaseCode Examples
Ready-to-use snippets for the most common flows. All examples use the public marketplace endpoints (no auth required for discovery and purchase).
Browse & discover APIs
Python
import requests
# Search for APIs
response = requests.get("https://api.onchor.xyz/api/marketplace/listings", params={
"q": "weather",
"category": "data",
"sort_by": "popular"
})
listings = response.json()["listings"]
for api in listings:
print(f"{api['name']} — {api['pricing_model']} — {api['price_per_call_usdc']} USDC/call")Node.js
// Browse APIs (Node 18+ with native fetch)
const res = await fetch("https://api.onchor.xyz/api/marketplace/listings?q=weather&category=data");
const { listings } = await res.json();
listings.forEach(api => {
console.log(`${api.name} — ${api.pricing_model} — ${api.price_per_call_usdc} USDC/call`);
});PHP
// Browse APIs
$params = http_build_query(['q' => 'weather', 'category' => 'data']);
$response = file_get_contents("https://api.onchor.xyz/api/marketplace/listings?{$params}");
$data = json_decode($response, true);
foreach ($data['listings'] as $api) {
echo $api['name'] . " — " . $api['price_per_call_usdc'] . " USDC/call\n";
}Purchase API access & poll for key
Python
import requests, time
# 1. Purchase
purchase = requests.post("https://api.onchor.xyz/api/marketplace/purchase", json={
"listing_id": "YOUR_LISTING_ID",
"buyer_identifier": "agent@ai.com"
}).json()
print(f"Send {purchase['amount_usdc']} USDC to {purchase['deposit_address']}")
sub_id = purchase["subscription_id"]
# 2. Poll until payment confirmed
while True:
status = requests.get(f"https://api.onchor.xyz/api/marketplace/purchase/{sub_id}/status").json()
if status["status"] == "active":
api_key = status["api_key"] # Save this! Only returned once
print(f"API Key: {api_key}")
break
time.sleep(5)Node.js
// 1. Purchase
const purchase = await fetch("https://api.onchor.xyz/api/marketplace/purchase", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
listing_id: "YOUR_LISTING_ID",
buyer_identifier: "agent@ai.com"
})
}).then(r => r.json());
console.log(`Send ${purchase.amount_usdc} USDC to ${purchase.deposit_address}`);
// 2. Poll until payment confirmed
let apiKey;
while (!apiKey) {
await new Promise(r => setTimeout(r, 5000));
const status = await fetch(
`https://api.onchor.xyz/api/marketplace/purchase/${purchase.subscription_id}/status`
).then(r => r.json());
if (status.status === "active") {
apiKey = status.api_key; // Save this! Only returned once
console.log("API Key:", apiKey);
}
}Call an API through the gateway
Python
import requests
# Call the Weather API through Onchor gateway
response = requests.get(
"https://api.onchor.xyz/api/gateway/weather-api/forecast",
params={"city": "paris"},
headers={"X-Marketplace-Key": "YOUR_API_KEY"}
)
print(response.json())Node.js
const res = await fetch(
"https://api.onchor.xyz/api/gateway/weather-api/forecast?city=paris",
{ headers: { "X-Marketplace-Key": "YOUR_API_KEY" } }
);
console.log(await res.json());PHP
$opts = ['http' => [
'header' => "X-Marketplace-Key: YOUR_API_KEY"
]];
$ctx = stream_context_create($opts);
$response = file_get_contents(
"https://api.onchor.xyz/api/gateway/weather-api/forecast?city=paris",
false, $ctx
);
$data = json_decode($response, true);
print_r($data);Seller: Create a listing
Python
import requests
headers = {
"Authorization": f"Bearer {YOUR_JWT}",
"Content-Type": "application/json"
}
listing = requests.post("https://api.onchor.xyz/api/marketplace/seller/listings",
headers=headers,
json={
"name": "Weather API",
"category": "data",
"base_url": "https://api.weather.io/v1",
"pricing_model": "per_call",
"price_per_call_usdc": 0.01,
"monthly_call_limit": 10000,
"short_description": "Real-time weather data for any location",
"tags": ["weather", "forecast", "realtime"]
}
).json()
print(f"Listed: {listing['name']} ({listing['slug']})")Node.js
const listing = await fetch("https://api.onchor.xyz/api/marketplace/seller/listings", {
method: "POST",
headers: {
"Authorization": `Bearer ${YOUR_JWT}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "Weather API",
category: "data",
base_url: "https://api.weather.io/v1",
pricing_model: "per_call",
price_per_call_usdc: 0.01,
monthly_call_limit: 10000,
short_description: "Real-time weather data for any location",
tags: ["weather", "forecast", "realtime"]
})
}).then(r => r.json());
console.log(`Listed: ${listing.name} (${listing.slug})`);Checkout
Checkout endpoints are used internally by the marketplace purchase flow. Each payment generates a unique Solana deposit address. When USDC arrives, it's automatically swept to the seller's wallet.
Get Checkout Info
Retrieve details of a payment session. Used by the checkout page to display payment info.
Response
{
"payment_id": "c3f8a2b1-...",
"merchant_name": "My Store",
"amount_eur": 25.00,
"amount_usdc": 27.00,
"deposit_address": "7xKXtg2Cw...",
"description": "Order #1234",
"status": "awaiting_payment",
"currency": "USDC",
"success_url": "https://mystore.com/success",
"cancel_url": "https://mystore.com/cancel",
"created_at": "2026-03-08T14:00:00",
"expires_at": "2026-03-08T14:30:00"
}Submit Payment
Customer submits their email before paying. Transitions the payment to awaiting_payment.
Request Body
Response
{
"payment_id": "c3f8a2b1-...",
"status": "awaiting_payment",
"amount_usdc": 27.00,
"deposit_address": "7xKXtg2Cw..."
}Check Payment Status
Poll this endpoint to detect when USDC arrives. When the full amount is received, the payment is marked as completed and the sweep is triggered automatically.
Response
{
"payment_id": "c3f8a2b1-...",
"status": "completed",
"amount_usdc": 27.00,
"deposit_address": "7xKXtg2Cw...",
"success_url": "https://mystore.com/success"
}status becomes completed or swept, the success_url is returned for redirect.Authentication & Merchants
Wallet Auth (recommended)
Two-step flow: request a nonce, then sign it with your wallet.
Request a nonce message to sign with your Solana wallet.
Request Body
Response
{
"nonce": "a1b2c3d4...",
"message": "Sign in to Onchor\nNonce: a1b2c3d4..."
}Submit the signed message. If the wallet is new, an account is created automatically. Returns JWT + API key.
Request Body
Response
{
"access_token": "eyJhbGciOi...",
"token_type": "bearer",
"merchant_id": "uuid-here",
"api_key": "a1b2c3d4...64chars",
"is_new": true
}is_new: true means the account was just created. The api_key is only returned on first connection — save it immediately. Your wallet address is automatically set as your merchant wallet.Register (email fallback)
Create a new merchant account. Returns a JWT token and a one-time API key.
Request Body
Response — 201 Created
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"merchant_id": "f47ac10b-...",
"api_key": "a1b2c3d4e5f6...64chars"
}Login
Authenticate with email and password. Returns a JWT token valid for 24 hours.
Request Body
Get Profile
Retrieve authenticated merchant's profile.
Update Profile
Update merchant settings. All fields are optional — only provided fields are updated.
Request Body
Regenerate API Key
Generate a new API key. The previous key is immediately invalidated.
Response
{
"api_key": "new64charkey...",
"message": "Save this key now. It will not be shown again."
}Transactions
List Transactions
Paginated list of your transactions, newest first.
Query Parameters
Response
{
"transactions": [
{
"id": "c3f8a2b1-...",
"amount_eur": 25.00,
"amount_usdc": 27.00,
"status": "swept",
"platform_fee": 0.25,
"net_amount_usdc": 26.73,
"sweep_tx_signature": "5xYz...",
"created_at": "2026-03-08T14:00:00",
"completed_at": "2026-03-08T14:05:32",
"swept_at": "2026-03-08T14:05:34"
}
],
"total": 42,
"page": 1,
"per_page": 20
}Get Transaction
Retrieve a single transaction with full details.
Dashboard
Stats
Aggregated metrics for your account.
Response
{
"total_transactions": 142,
"completed_transactions": 128,
"failed_transactions": 3,
"pending_transactions": 11,
"total_volume_eur": 12540.00,
"total_revenue_eur": 12289.20,
"total_platform_fees_eur": 125.40
}Recent Transactions
Returns the 10 most recent transactions.
Webhooks
Set your webhook_url in your merchant profile. Onchor sends a POST request whenever a payment is completed.
Event: payment.completed
Sent when USDC is detected on the deposit address and the sweep to your wallet is initiated.
POST https://your-server.com/webhook
Content-Type: application/json
X-Webhook-Signature: sha256=...
{
"event": "payment.completed",
"data": {
"payment_id": "c3f8a2b1-...",
"amount_eur": 25.00,
"amount_usdc": 27.00,
"net_amount_usdc": 26.73,
"currency": "USDC",
"status": "swept",
"customer_email": "customer@example.com",
"sweep_tx": "5xYzAbc...",
"metadata": { "order_id": "1234" }
}
}X-Webhook-Signature header contains an HMAC-SHA256 signature of the request body, signed with your API key. Always verify this signature to ensure the webhook is from Onchor.Payment Statuses
Error Handling
All errors return a JSON object with a detail field:
{
"detail": "Payment not found"
}HTTP Status Codes
Authentication errors
Checkout errors
Merchant errors
Marketplace errors
Gateway proxy errors
detail field in error responses — it contains a human-readable description of what went wrong.API Marketplace
The Onchor marketplace lets sellers list their APIs and buyers (including AI agents) discover, purchase, and consume them. All requests go through the Onchor gateway for authentication, metering, and billing. Onchor takes a 5% fee on marketplace sales.
Browse Listings
Search and filter API listings. No auth required.
// Response (200)
{
"listings": [
{
"id": "uuid",
"name": "Weather API",
"slug": "weather-api",
"category": "data",
"pricing_model": "per_call",
"price_per_call_usdc": 0.01,
"monthly_call_limit": 1000,
"daily_call_limit": 100,
"total_subscriptions": 42,
"total_calls_served": 15000
}
],
"total": 1,
"page": 1,
"per_page": 20
}Get Listing by Slug
Get a single listing by its slug.
Purchase API Access
Purchase access to an API listing. Returns a deposit address to send USDC to.
// Response (201)
{
"subscription_id": "sub_uuid",
"listing_name": "Weather API",
"pricing_model": "per_call",
"price_usdc": 10.0,
"status": "pending_payment",
"payment_id": "tx_uuid",
"deposit_address": "7xKXtg2Cw...",
"amount_usdc": 10.0
}Check Purchase Status
Poll this endpoint after sending USDC. When payment is confirmed, the response includes your API key.
// Response when active (API key returned once)
{
"subscription_id": "sub_uuid",
"status": "active",
"api_key": "a1b2c3d4e5f6...64chars",
"listing_name": "Weather API",
"listing_slug": "weather-api",
"gateway_base_url": "https://api.onchor.xyz/api/gateway/weather-api",
"calls_limit": 1000,
"daily_call_limit": 100,
"expires_at": null
}Gateway Proxy
Proxy requests to the seller's API. Supports GET, POST, PUT, PATCH, DELETE. All headers, query params, and body are forwarded.
The gateway validates your key, checks scopes and quotas, forwards the request, logs usage, and returns the response.
# Example: Call the Weather API through the gateway curl https://api.onchor.xyz/api/gateway/weather-api/forecast?city=paris \ -H "X-Marketplace-Key: a1b2c3d4e5f6..."
Quota enforcement
Create Listing (Seller)
Create a new API listing.
List My Listings
List all your API listings.
Update Listing
Update a listing. All fields optional.
Delete Listing
Soft-delete (deactivate) a listing. Existing subscriptions remain active.
Seller Revenue
Get total marketplace revenue summary.
// Response
{
"total_revenue_usdc": 1542.00,
"total_subscriptions": 23,
"total_calls": 15420
}Seller Analytics
Detailed analytics: daily breakdown, per-listing stats, top buyers.
// Response
{
"period_from": "2026-02-07",
"period_to": "2026-03-09",
"summary": {
"total_calls": 15420,
"total_revenue_usdc": 1542.00,
"active_subscribers": 23,
"total_listings": 5
},
"daily": [
{ "date": "2026-03-09", "calls": 523, "revenue_usdc": 52.30, "unique_callers": 12 }
],
"by_listing": [
{ "listing_id": "...", "name": "Weather API", "calls": 8000, "revenue_usdc": 800.00, "subscribers": 15 }
],
"top_buyers": [
{ "buyer_identifier": "agent@ai.com", "calls": 3000, "revenue_usdc": 300.00 }
]
}Create API Key (Buyer)
Create an additional API key for one of your subscriptions. Supports HTTP method scoping.
// Request: Create a read-only key
{
"subscription_id": "sub_uuid",
"name": "readonly-production",
"scopes": ["GET"]
}
// Response (201) — api_key only returned once
{
"id": "key_uuid",
"subscription_id": "sub_uuid",
"name": "readonly-production",
"api_key_prefix": "a1b2c3d4",
"scopes": ["GET"],
"is_active": true,
"api_key": "a1b2c3d4e5f6...64chars"
}List API Keys
List all API keys for a subscription you own.
Revoke API Key
Revoke an API key immediately. The key becomes unusable. Other keys on the same subscription are not affected.
Marketplace Webhook Events
Set your webhook_url in your merchant profile. The following events are sent for marketplace activity:
// Example: subscription.created webhook
{
"event": "subscription.created",
"data": {
"listing_id": "uuid",
"listing_name": "Weather API",
"subscription_id": "sub_uuid",
"buyer_identifier": "agent@ai.com",
"pricing_model": "per_call",
"price_usdc": 10.0,
"calls_used": 0,
"calls_limit": 1000
}
}AI Agents
Any AI agent can self-register on Onchor, fund itself, discover APIs, purchase access, and start consuming — all autonomously. No human account needed.
Discover (LLM-readable)
Returns a plain-text guide that any LLM can read and understand. Contains all endpoints, auth instructions, pricing, and a complete workflow. Give this single URL to any AI agent.
Usage
curl https://api.onchor.xyz/api/agents/discover
https://api.onchor.xyz/api/agents/discover and it will know exactly how to register, fund, browse, purchase, and consume APIs.Self-Register (for agents)
An agent calls this once and gets back everything it needs: a token, a wallet address, and a list of endpoints. No human setup required.
Request
{
"name": "Claude Code Agent"
}Response (201)
{
"agent_token": "oat_a1b2c3...",
"wallet_address": "7xK9...",
"wallet_explorer_url": "https://solscan.io/account/7xK9...",
"balance_usdc": 0.0,
"endpoints": {
"check_balance": "GET /api/balance/me",
"browse_apis": "GET /api/marketplace/listings?q=QUERY",
"purchase_api": "POST /api/balance/me/purchase?listing_id=ID",
"call_api": "ANY /api/gateway/SLUG/PATH (header: X-Marketplace-Key)",
...
}
}Detect Deposit
Check your wallet for USDC and credit your balance. Call this after sending USDC to your wallet address.
Agent Info
Get your wallet address, balance, and status.
Create Token (for merchants)
Create a new agent token. The raw token is returned once — save it securely.
Request
{
"name": "My Claude Agent"
}Response (201)
{
"id": "uuid...",
"name": "My Claude Agent",
"token": "oat_a1b2c3...",
"token_prefix": "oat_a1b2c3d4",
"is_active": true,
"created_at": "2026-03-09T..."
}List Tokens
List all your agent tokens (names, prefixes, status). Raw tokens are never shown again.
Revoke Token
Revoke a token immediately. Any agent using it will get 401.
Authenticated Balance Endpoints
These endpoints let your agent manage its balance without needing to know the buyer_identifier — it is derived from the authenticated merchant.
Check your current USDC balance.
Create a deposit — returns a USDC address to fund.
Purchase API access from your balance. Returns the API key and gateway URL immediately.
View your balance transaction history.
List your active API subscriptions with gateway URLs.
Full Agent Workflow
Here's how an AI agent uses Onchor from zero, completely autonomously:
# 1. Agent self-registers (no human needed)
curl -X POST https://api.onchor.xyz/api/agents/register \
-H "Content-Type: application/json" \
-d '{"name": "My AI Agent"}'
# -> { "agent_token": "oat_abc...", "wallet_address": "7xK9...", "endpoints": {...} }
# 2. Fund the wallet (send USDC to wallet_address)
# Then detect the deposit:
curl -X POST https://api.onchor.xyz/api/agents/deposit \
-H "X-API-Key: oat_abc..."
# 3. Agent discovers APIs it needs
curl "https://api.onchor.xyz/api/marketplace/listings?q=sentiment+analysis"
# 4. Agent purchases API access (instant, from balance)
curl -X POST "https://api.onchor.xyz/api/balance/me/purchase?listing_id=LISTING_ID" \
-H "X-API-Key: oat_abc..."
# -> { "api_key": "mkt_...", "gateway_base_url": "https://api.onchor.xyz/api/gateway/sentiment" }
# 5. Agent consumes the API
curl https://api.onchor.xyz/api/gateway/sentiment/analyze \
-H "X-Marketplace-Key: mkt_..." \
-H "Content-Type: application/json" \
-d '{"text": "This product is amazing!"}'• Self-registration — agent calls
POST /api/agents/register and gets its own token. No human involved.• Merchant-created — merchant creates a token in Dashboard → Settings → Agent Tokens and gives it to the agent.
Both produce an
oat_... token that works everywhere.X-API-Key: oat_... = agent identity (balance, purchases, management). X-Marketplace-Key: ... = consume a purchased API through the gateway.Rate Limiting
When rate limited, the API returns 429 Too Many Requests. Wait and retry.