Live on Solana Devnet

Micropay Bazaar Documentation

A micropayment gateway for AI agents. Pay per call in SOL, discover data services, and settle on-chain โ€” all with one API.

๐Ÿ’ณ

Add Micropay to your payment gateway

Monetize your API. Register it in the Bazaar, set a price, and get paid in SOL every time an AI agent calls it.

Start integrating
๐Ÿ”Œ

Use Micropay API to access other APIs

Pay for 26 data services โ€” stocks, weather, NLP, search โ€” with micro SOL payments. No subscriptions, no rate limits.

Start integrating
Prebuilt services

26 data services across 11 categories โ€” weather, finance, crypto, NLP, news, sports, travel, and more. Each costs fractions of a cent in SOL. View full catalog ↓

StocksWeatherCryptoNLPNewsSportsTravelSearchAI/GPTDeFiGitHub

Authentication

Pass your API key as a Bearer token in the Authorization header.

HeaderAuthorization: Bearer mp_live_demo_key
Demo key: mp_live_demo_key โ€” use this for all hackathon testing.

Auth requirements by endpoint

POST /api/v1/registry/register
Auth
GET /api/v1/registry/discover
Public
GET /api/v1/registry/services/:id
Public
POST /api/v1/charges
Auth
GET /api/v1/charges
Auth
GET /api/v1/charges/:id
Auth
POST /api/v1/chat/completions
Auth
POST /api/v1/chat/tool-result
Auth
POST /api/ai/chat
Public
GET /api/v1/balance/:wallet
Public
GET /api/v1/transactions/:wallet
Public
GET /api/v1/network/status
Public
GET /api/v1/health
Public
401 โ€” Missing header{ "error": "Unauthorized: Missing or invalid Authorization header format" }
401 โ€” Invalid key{ "error": "Unauthorized: Invalid API Key" }

Charges

Charges represent a payment for a registry service. Create one to get an unsigned Solana transaction, then sign and broadcast it.

Create a charge

POST/api/v1/chargesAuth required

Returns an unsigned Solana transaction. The backend fetches live SOL/USD price, calculates SOL amount, looks up the developer's wallet, and builds the transaction.

service_idstringrequired+
Registry service to pay for. Must exist in the Bazaar.
How to find valid IDs: Call GET /api/v1/registry/discover and use the id field. See the full catalog for all 26 IDs.
Type
Non-empty string
Examples
"finance_stocks", "weather_openmeteo", "openai_chat"
400: "'service_id' is required and must be a non-empty string."
404: "Service 'bad_id' not found in registry."
source_walletstringrequired+
Solana public key of the wallet paying. Set as feePayer.
Must match Phantom exactly. The backend embeds this as feePayer in the Solana transaction. If it doesn't match, Phantom rejects the signature.
Type
Base58 Solana public key
Example
"AuofYo21iiX8NQtgWBXLRFMiWfv83z2CbnhPNen6WNt5"
400: "'source_wallet' is required and must be a non-empty string."
Phantom error: "Transaction signature verification failure" if wallet mismatch.
curl -X POST https://micropay.up.railway.app/api/v1/charges \
     -H "Authorization: Bearer mp_live_demo_key" \
     -H "Content-Type: application/json" \
     -d '{
       "service_id": "finance_stocks",
       "source_wallet": "YOUR_PHANTOM_WALLET_ADDRESS"
     }'
const res = await fetch('https://micropay.up.railway.app/api/v1/charges', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer mp_live_demo_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    service_id: 'finance_stocks',
    source_wallet: 'YOUR_PHANTOM_WALLET_ADDRESS',
  }),
});
const charge = await res.json();
import requests

res = requests.post(
    "https://micropay.up.railway.app/api/v1/charges",
    headers={
        "Authorization": "Bearer mp_live_demo_key",
        "Content-Type": "application/json",
    },
    json={
        "service_id": "finance_stocks",
        "source_wallet": "YOUR_PHANTOM_WALLET_ADDRESS",
    },
)
charge = res.json()

List charges

GET/api/v1/chargesAuth required

Paginated list of all charges. Filter by wallet or status.

limitintegeroptional+
Max records per page. Default: 10, max: 100.
Use limit + offset together. Response includes has_more: true if more pages exist.
Type
Integer, 1โ€“100
Default
10
offsetintegeroptional+
Records to skip. Default: 0.
Zero-indexed. ?limit=5&offset=10 returns records 11โ€“15.
statusstringoptional+
Filter by charge status.
Valid values
"requires_signature"
source_walletstringoptional+
Filter to charges from a specific wallet address.
Type
Base58 Solana address
curl https://micropay.up.railway.app/api/v1/charges?limit=5 \
     -H "Authorization: Bearer mp_live_demo_key"
const res = await fetch('https://micropay.up.railway.app/api/v1/charges?limit=5', {
  headers: { 'Authorization': 'Bearer mp_live_demo_key' },
});
const data = await res.json();
import requests

res = requests.get(
    "https://micropay.up.railway.app/api/v1/charges",
    headers={"Authorization": "Bearer mp_live_demo_key"},
    params={"limit": 5},
)
data = res.json()

Get a charge

GET/api/v1/charges/:idAuth required

Retrieve full details of a single charge.

idstringrequired+
Charge ID from POST /api/v1/charges. Prefix: ch_.
Example
"ch_wb4bedrhxh1q"
404: "Charge 'ch_badid' not found."
curl https://micropay.up.railway.app/api/v1/charges/ch_wb4bedrhxh1q \
     -H "Authorization: Bearer mp_live_demo_key"
const res = await fetch('https://micropay.up.railway.app/api/v1/charges/ch_wb4bedrhxh1q', {
  headers: { 'Authorization': 'Bearer mp_live_demo_key' },
});
const charge = await res.json();
import requests

res = requests.get(
    "https://micropay.up.railway.app/api/v1/charges/ch_wb4bedrhxh1q",
    headers={"Authorization": "Bearer mp_live_demo_key"},
)
charge = res.json()

Registry

The registry is the discovery index for all paid services in the Bazaar.

Register a service

POST/api/v1/registry/registerAuth required

See the Accept Payments guide for complete instructions and all 5 required parameters with error details.

curl -X POST https://micropay.up.railway.app/api/v1/registry/register \
     -H "Authorization: Bearer mp_live_demo_key" \
     -H "Content-Type: application/json" \
     -d '{
       "name": "My Weather API",
       "description": "Real-time weather data",
       "endpoint": "https://myapi.com/weather",
       "developer_wallet": "YOUR_WALLET_ADDRESS",
       "tags": ["weather", "forecast"]
     }'
const res = await fetch('https://micropay.up.railway.app/api/v1/registry/register', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer mp_live_demo_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'My Weather API',
    description: 'Real-time weather data',
    endpoint: 'https://myapi.com/weather',
    developer_wallet: 'YOUR_WALLET_ADDRESS',
    tags: ['weather', 'forecast'],
  }),
});
const service = await res.json();
import requests

res = requests.post(
    "https://micropay.up.railway.app/api/v1/registry/register",
    headers={
        "Authorization": "Bearer mp_live_demo_key",
        "Content-Type": "application/json",
    },
    json={
        "name": "My Weather API",
        "description": "Real-time weather data",
        "endpoint": "https://myapi.com/weather",
        "developer_wallet": "YOUR_WALLET_ADDRESS",
        "tags": ["weather", "forecast"],
    },
)
service = res.json()

Discover services

GET/api/v1/registry/discoverPublic

Search all registered services. 26 preloaded. No auth required.

querystringquery param ยท optional+
Search by intent. Matches name, description, and tags.
How search works: Case-insensitive substring match across name, description, and tags. Omit to get all 26 services.
Examples
?query=weather โ†’ 3 results. ?query=crypto โ†’ 1 result.
# Get all services
curl https://micropay.up.railway.app/api/v1/registry/discover

# Search for weather services
curl "https://micropay.up.railway.app/api/v1/registry/discover?query=weather"
// Get all services
const res = await fetch('https://micropay.up.railway.app/api/v1/registry/discover');
const all = await res.json();

// Search for weather services
const weather = await fetch(
  'https://micropay.up.railway.app/api/v1/registry/discover?query=weather'
).then(r => r.json());
import requests

# Get all services
all_svc = requests.get("https://micropay.up.railway.app/api/v1/registry/discover").json()

# Search for weather services
weather = requests.get(
    "https://micropay.up.railway.app/api/v1/registry/discover",
    params={"query": "weather"},
).json()

Get a service

GET/api/v1/registry/services/:idPublic

Retrieve a single service by exact ID. Returns 404 if not found.

curl https://micropay.up.railway.app/api/v1/registry/services/finance_stocks
const res = await fetch(
  'https://micropay.up.railway.app/api/v1/registry/services/finance_stocks'
);
const service = await res.json();
import requests

service = requests.get(
    "https://micropay.up.railway.app/api/v1/registry/services/finance_stocks"
).json()

AI Gateway

Natural language interface to the Bazaar. The AI decides whether to answer directly or request a paid tool call. See the Access APIs guide Step 5 for the full agentic flow with code.

Chat completions

POST/api/v1/chat/completionsAuth required

Send a natural language message. The AI decides whether to answer directly or request a paid tool call from the Bazaar.

messagestringrequired+
Natural language message to the AI.
What happens: The AI analyzes your message and decides if it needs live data from a Bazaar service. If yes โ†’ type: "tool_call" with the service_id. If no โ†’ type: "message" with a plain answer.
Example
"What is the current price of AAPL?"
400 if missing: {"error":"message is required"}
conversation_idstringoptional+
Continue an existing conversation. Omit to start a new one.
How conversations work: Each response returns a conversation_id. Pass it back to continue with full context. Up to 20 messages per conversation. Stored in-memory โ€” resets on server restart.
Format
conv_ + random ID
Example
"conv_a8f2k9x1b3"
If wrong/expired: AI starts a fresh conversation without any prior context. The response will be valid but may lack the context from previous messages.
source_walletstringoptional+
Informational only โ€” not used to build the transaction.
Why optional: The chat endpoint doesn't create charges. It only tells you what service to pay for. The actual charge (where source_wallet is required) is created via POST /api/v1/charges.
curl -X POST https://micropay.up.railway.app/api/v1/chat/completions \
     -H "Authorization: Bearer mp_live_demo_key" \
     -H "Content-Type: application/json" \
     -d '{
       "message": "What is the current price of AAPL?",
       "source_wallet": "YOUR_WALLET_ADDRESS"
     }'
const res = await fetch('https://micropay.up.railway.app/api/v1/chat/completions', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer mp_live_demo_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    message: 'What is the current price of AAPL?',
    source_wallet: 'YOUR_WALLET_ADDRESS',
  }),
});
const data = await res.json();
import requests

res = requests.post(
    "https://micropay.up.railway.app/api/v1/chat/completions",
    headers={
        "Authorization": "Bearer mp_live_demo_key",
        "Content-Type": "application/json",
    },
    json={
        "message": "What is the current price of AAPL?",
        "source_wallet": "YOUR_WALLET_ADDRESS",
    },
)
data = res.json()

Submit tool result

POST/api/v1/chat/tool-resultAuth required

After paying for a tool call, send the real data back. AI generates a natural language answer.

conversation_idstringrequired+
Must match the conversation_id from the tool_call response.
Links the data to the AI's request. Without a matching conversation context, the AI doesn't know what question it asked or what tool was called.
Example
"conv_a8f2k9x1b3"
If mismatched: AI loses context about what it asked for. Response will be vague or nonsensical.
tool_resultstringrequired+
Raw data from the service. JSON-stringified or plain text.
The AI interprets and summarizes this into a human-readable answer.
Example
"{\"AAPL\":{\"price\":189.42}}"
If empty: AI returns a generic "I couldn't retrieve the data" response.
service_idstringoptional+
Fallback if conversation context was lost (e.g. server restart).
Under normal operation, conversation_id carries all the context needed. Only pass this if the server restarted and the conversation was lost.
curl -X POST https://micropay.up.railway.app/api/v1/chat/tool-result \
     -H "Authorization: Bearer mp_live_demo_key" \
     -H "Content-Type: application/json" \
     -d '{
       "conversation_id": "conv_a8f2k9x1b3",
       "tool_result": "{\"AAPL\":{\"price\":189.42,\"change\":\"+1.2%\"}}",
       "service_id": "finance_stocks"
     }'
const res = await fetch('https://micropay.up.railway.app/api/v1/chat/tool-result', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer mp_live_demo_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    conversation_id: 'conv_a8f2k9x1b3',
    tool_result: JSON.stringify({ AAPL: { price: 189.42, change: '+1.2%' } }),
    service_id: 'finance_stocks',
  }),
});
const answer = await res.json();
import requests, json

res = requests.post(
    "https://micropay.up.railway.app/api/v1/chat/tool-result",
    headers={
        "Authorization": "Bearer mp_live_demo_key",
        "Content-Type": "application/json",
    },
    json={
        "conversation_id": "conv_a8f2k9x1b3",
        "tool_result": json.dumps({"AAPL": {"price": 189.42, "change": "+1.2%"}}),
        "service_id": "finance_stocks",
    },
)
answer = res.json()

Direct AI chat

POST/api/ai/chatPublic

One-shot pass-through to OpenAI. No tools, no registry, no conversation state.

messagestringrequired+
Prompt to send to OpenAI.
Behavior: Fires a tiny on-chain Devnet transaction as proof-of-payment, then forwards your prompt to OpenAI. Response includes the reply, model, token usage, and the Solana tx signature.
400: {"error":"message is required"}
modelstringoptional+
OpenAI model. Default: gpt-4o-mini.
Valid values
gpt-4o, gpt-4o-mini, o1-mini, o3-mini
Default
gpt-4o-mini
Invalid model: Silently falls back to gpt-4o-mini. No error thrown.
curl -X POST https://micropay.up.railway.app/api/ai/chat \
     -H "Content-Type: application/json" \
     -d '{
       "message": "Explain quantum computing in one sentence",
       "model": "gpt-4o-mini"
     }'
const res = await fetch('https://micropay.up.railway.app/api/ai/chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    message: 'Explain quantum computing in one sentence',
    model: 'gpt-4o-mini',
  }),
});
const data = await res.json();
import requests

res = requests.post(
    "https://micropay.up.railway.app/api/ai/chat",
    json={
        "message": "Explain quantum computing in one sentence",
        "model": "gpt-4o-mini",
    },
)
data = res.json()

Network

Public endpoints for wallet balances, transaction history, and Devnet health.

Get balance

GET/api/v1/balance/:walletPublic

Real-time SOL balance for any Solana wallet on Devnet.

curl https://micropay.up.railway.app/api/v1/balance/AuofYo21iiX8NQtgWBXLRFMiWfv83z2CbnhPNen6WNt5
const wallet = 'AuofYo21iiX8NQtgWBXLRFMiWfv83z2CbnhPNen6WNt5';
const res = await fetch(
  `https://micropay.up.railway.app/api/v1/balance/${wallet}`
);
const data = await res.json();
import requests

wallet = "AuofYo21iiX8NQtgWBXLRFMiWfv83z2CbnhPNen6WNt5"
data = requests.get(f"https://micropay.up.railway.app/api/v1/balance/{wallet}").json()

Get transactions

GET/api/v1/transactions/:walletPublic

Last 5 Solana transactions for a wallet. Each has a signature verifiable on Solana Explorer.

curl https://micropay.up.railway.app/api/v1/transactions/AuofYo21iiX8NQtgWBXLRFMiWfv83z2CbnhPNen6WNt5
const wallet = 'AuofYo21iiX8NQtgWBXLRFMiWfv83z2CbnhPNen6WNt5';
const res = await fetch(
  `https://micropay.up.railway.app/api/v1/transactions/${wallet}`
);
const txns = await res.json();
import requests

wallet = "AuofYo21iiX8NQtgWBXLRFMiWfv83z2CbnhPNen6WNt5"
txns = requests.get(f"https://micropay.up.railway.app/api/v1/transactions/{wallet}").json()

Network status

GET/api/v1/network/statusPublic

Devnet status โ€” slot height, block height, SOL price, RPC health.

curl https://micropay.up.railway.app/api/v1/network/status
const res = await fetch('https://micropay.up.railway.app/api/v1/network/status');
const status = await res.json();
import requests

status = requests.get("https://micropay.up.railway.app/api/v1/network/status").json()

Health check

GET/api/v1/healthPublic

Returns 200 if the server is up.

curl https://micropay.up.railway.app/api/v1/health
const res = await fetch('https://micropay.up.railway.app/api/v1/health');
const data = await res.json();
// { status: "ok", version: "1.0.0" }
import requests

data = requests.get("https://micropay.up.railway.app/api/v1/health").json()
# {"status": "ok", "version": "1.0.0"}

Service catalog

26 preloaded services. Click any to see details. Pricing is by category โ€” the backend auto-resolves the price when you create a charge.

Weather $0.01 / call
weather_openmeteoLive Weather (Open-Meteo)

Description: Real-time temperature, humidity, and precipitation data from Open-Meteo for any city worldwide.

Endpoint: GET /tools/weather/openmeteo

weathertemperaturehumidityprecipitationopen-meteo
weather_openweatherLive Weather (OpenWeather)

Description: Real-time weather including wind speed, visibility, and UV index via OpenWeather API.

Endpoint: GET /tools/weather/openweather

weatherwinduvopenweather
weather_forecast7-Day Forecast

Description: Extended 7-day forecast with daily highs, lows, and precipitation probability.

Endpoint: GET /tools/weather/forecast

forecastweekly7day
Finance $0.01 / call
finance_stocksStock Price Feed

Description: Live equity prices, volume, and market cap from NYSE and NASDAQ.

Endpoint: GET /tools/finance/stocks

stocksequityNYSENASDAQ
finance_cryptoCrypto Price Oracle

Description: Live SOL/USD, BTC/USD, ETH/USD price feeds with 1-minute granularity.

Endpoint: GET /tools/finance/crypto

cryptobitcoinsolanaethereum
finance_forexForex Exchange Rates

Description: Real-time foreign exchange rates for 170+ currency pairs.

Endpoint: GET /tools/finance/forex

forexcurrencyUSDEUR
NLP $0.01 / call
nlp_sentimentSentiment Analysis

Description: Analyze sentiment of any text. Returns positive, negative, or neutral with confidence.

Endpoint: GET /tools/nlp/sentiment

nlpsentimentanalysis
nlp_summarizeText Summarizer

Description: Summarize long articles into concise key points.

Endpoint: GET /tools/nlp/summarize

nlpsummarizetldr
nlp_translateLanguage Translator

Description: Translate between 100+ languages with auto-detection.

Endpoint: GET /tools/nlp/translate

nlptranslatei18n
nlp_extractEntity Extractor

Description: Extract named entities (people, places, orgs, dates) from text.

Endpoint: GET /tools/nlp/extract

nlpentitiesner
Food $0.01 / call
food_recipesRecipe Search

Description: Search recipes by ingredient, cuisine, or dietary restriction.

Endpoint: GET /tools/food/recipes

foodrecipescooking
food_nutritionNutrition Data

Description: Nutritional info including macros, vitamins, and minerals.

Endpoint: GET /tools/food/nutrition

foodnutritioncalories
Blockchain $0.01 / call
blockchain_walletWallet Balance Checker

Description: Check SOL, ETH, and major token balances across chains.

Endpoint: GET /tools/blockchain/wallet

blockchainwalletbalance
blockchain_nftNFT Metadata Lookup

Description: Metadata, ownership history, and floor price for any NFT.

Endpoint: GET /tools/blockchain/nft

nftmetadatamint
blockchain_defiDeFi Protocol Stats

Description: TVL, APY, and pool data for DeFi protocols on Solana and Ethereum.

Endpoint: GET /tools/blockchain/defi

defitvlapyyield
News $0.02 / call
news_breakingBreaking News Headlines

Description: Breaking news across 50+ categories and 30+ countries.

Endpoint: GET /tools/news/breaking

newsbreakingheadlines
news_searchNews Search

Description: Search millions of articles by keyword, date range, and source.

Endpoint: GET /tools/news/search

newssearcharticles
Sports $0.02 / call
sports_scoresLive Sports Scores

Description: Live scores for NFL, NBA, MLB, NHL, Premier League.

Endpoint: GET /tools/sports/scores

sportsscoreslive
sports_statsPlayer & Team Stats

Description: Historical and season statistics for players and teams.

Endpoint: GET /tools/sports/stats

sportsstatsanalytics
Data $0.02 / call
data_demographicsDemographics Data

Description: Population, income, education data for any US zip code.

Endpoint: GET /tools/data/demographics

demographicspopulationcensus
data_githubGitHub Repo Analytics

Description: Stars, forks, contributors, and language breakdown for any repo.

Endpoint: GET /tools/data/github

githubreposanalytics
Search $0.05 / call
search_webWeb Search API

Description: Top 10 search results with titles, URLs, and snippets.

Endpoint: GET /tools/search/web

searchwebgoogle
search_imagesImage Search API

Description: Image search with size, color, and license filters.

Endpoint: GET /tools/search/images

searchimagesphotos
Travel $0.05 / call
travel_flightsFlight Search

Description: Flight search with real-time pricing and availability.

Endpoint: GET /tools/travel/flights

flightsairlinesbooking
travel_hotelsHotel Search

Description: Hotel search by city, dates, and guest count.

Endpoint: GET /tools/travel/hotels

hotelsaccommodationbooking
AI $0.05 / call
openai_chatOpenAI Chat Completions

Description: GPT-4o chat completions. Pay per request, no subscription.

Endpoint: POST /tools/openai-chat

openaigptchataillm

Tech Stack

How Micropay Bazaar is built under the hood.

Component Technology Why
Runtime Node.js + Express.js Lightweight, fast JSON API server with middleware ecosystem
Blockchain @solana/web3.js (Devnet) Build unsigned transactions, query balances, parse on-chain data
Price Oracle CoinGecko API Live SOL/USD conversion with 60-second cache and hardcoded fallback
AI Gateway OpenAI GPT-4o-mini Function calling for tool selection, conversation context for multi-turn
Data Store In-memory (Map) Charges, registry, conversations, and idempotency โ€” resets on restart
Deployment Railway Auto-deploy from GitHub, HTTPS, environment variable management
Logging Morgan HTTP request logging in dev format
Wallet Phantom (client-side) Transaction signing and broadcasting via browser extension

Architecture

Developer / AI Agent Micropay API Express.js ยท Node.js Registry Store Map<id, service> Charges Store Map<id, charge> Chat History Map<id, messages> Idempotency Cache ยท 24h TTL SOL โ†” USD price conversion ยท 60s cache ยท fallback network.service.js Solana Devnet RPC @solana/web3.js CoinGecko API Price oracle OpenAI GPT-4o-mini Chat completions ยท function calling Phantom Wallet Client-side tx signing โ–ฒ Deployed on Railway Morgan logging

Errors

All errors return a consistent JSON object.

error.typestring+
Machine-readable error category.
Valid values
authentication_error (401), invalid_request_error (400), not_found_error (404), api_error (500), gateway_error (502)
error.messagestring+
Human-readable description. Safe to display to users.
Example
"'service_id' is required and must be a non-empty string."

HTTP status codes

CodeMeaning
200Success
201Created โ€” service registered
400Bad Request โ€” missing or invalid parameters
401Unauthorized โ€” missing or invalid API key
404Not Found โ€” resource doesn't exist
500Internal Server Error
502Gateway Error โ€” upstream AI down, retry