Operate
Agent payments
An agent creates its own account and pays with Solana USDC or any Solana token.
How it works
- Sign upOne POST returns a key and a deposit address.
- PaySend USDC, or swap any Solana token into it.
- SpendCall any paid model once credit lands.
Prerequisites
- A Solana wallet holding USDC or the token you pay with.
- SOL in that wallet for network fees.
- Node.js 20 or later with
@solana/web3.jsfor the TypeScript examples.
Pay with USDC
No swap. USDC credits one for one.
1. Create an account
No body. Save the key; it is shown once.
curl -X POST https://api.minirouter.sh/accounts/agentconst signup = await fetch("https://api.minirouter.sh/accounts/agent", { method: "POST" })
.then((res) => res.json());
const key = signup.key.key;
const address = signup.depositProvisioning.address;2. Send USDC
Send at least $0.50 of Solana USDC to depositProvisioning.address.
spl-token transfer --fund-recipient \
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v 5 <depositProvisioning.address>3. Check the balance
availableNano turns positive once the payment finalizes.
curl https://api.minirouter.sh/balance \
-H "Authorization: Bearer $MINIROUTER_KEY"const balance = await fetch("https://api.minirouter.sh/balance", {
headers: { Authorization: `Bearer ${key}` },
}).then((res) => res.json());
console.log(balance.availableUsd);Pay with any Solana token
Any token Jupiter can price converts to USDC in one transaction. Credit is the USDC that lands.
1. Create an account
No body. Save the key; it is shown once.
curl -X POST https://api.minirouter.sh/accounts/agentconst signup = await fetch("https://api.minirouter.sh/accounts/agent", { method: "POST" })
.then((res) => res.json());
const key = signup.key.key;
const address = signup.depositProvisioning.address;2. Quote
inputAmount is in whole tokens. minimumNano is the least credit you receive.
curl https://api.minirouter.sh/deposits/solana-wallet/quote \
-H "Authorization: Bearer $MINIROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{"inputMint":"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN","inputAmount":"20"}'3. Create an intent
Set requestedNano to the quote's minimumNano.
curl https://api.minirouter.sh/deposits/intents \
-H "Authorization: Bearer $MINIROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{"rail":"solana-usdc","requestedNano":"<minimumNano>","idempotencyKey":"<uuid>"}'4. Build the swap
Returns an unsigned transaction that pays your deposit address.
curl https://api.minirouter.sh/deposits/solana-wallet/order \
-H "Authorization: Bearer $MINIROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{"intentId":"<intentId>","wallet":"<public key>","inputMint":"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN","inputAmount":"20"}'5. Sign and execute
import { VersionedTransaction } from "@solana/web3.js";
const tx = VersionedTransaction.deserialize(Buffer.from(order.transaction, "base64"));
tx.sign([wallet]);
const signedTransaction = Buffer.from(tx.serialize()).toString("base64");curl https://api.minirouter.sh/deposits/solana-wallet/execute \
-H "Authorization: Bearer $MINIROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{"intentId":"<intentId>","requestId":"<requestId>","signedTransaction":"<base64>","lastValidBlockHeight":"<height>"}'6. Check the balance
availableNano turns positive once the payment finalizes.
curl https://api.minirouter.sh/balance \
-H "Authorization: Bearer $MINIROUTER_KEY"const balance = await fetch("https://api.minirouter.sh/balance", {
headers: { Authorization: `Bearer ${key}` },
}).then((res) => res.json());
console.log(balance.availableUsd);Full example
Signup, JUP swap, balance wait and a first paid request. Run with npx tsx agent-e2e.ts.
import { Keypair, VersionedTransaction } from "@solana/web3.js";
const api = "https://api.minirouter.sh";
const inputMint = "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN";
const inputAmount = process.env.INPUT_AMOUNT ?? "20";
const wallet = Keypair.fromSecretKey(Uint8Array.from(JSON.parse(process.env.SOLANA_SECRET_KEY!)));
const signup = await fetch(`${api}/accounts/agent`, { method: "POST" }).then((res) => res.json());
const key: string = signup.key.key;
console.log("Save these:", key, `https://minirouter.sh${signup.accessPath}`);
const call = async (path: string, body?: unknown) => {
const res = await fetch(api + path, {
method: body === undefined ? "GET" : "POST",
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
...(body === undefined ? {} : { body: JSON.stringify(body) }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
};
const quote = await call("/deposits/solana-wallet/quote", { inputMint, inputAmount });
const intent = await call("/deposits/intents", {
rail: "solana-usdc",
requestedNano: quote.minimumNano,
idempotencyKey: crypto.randomUUID(),
});
const order = await call("/deposits/solana-wallet/order", {
intentId: intent.intentId,
wallet: wallet.publicKey.toBase58(),
inputMint,
inputAmount,
});
const tx = VersionedTransaction.deserialize(Buffer.from(order.transaction, "base64"));
tx.sign([wallet]);
await call("/deposits/solana-wallet/execute", {
intentId: intent.intentId,
requestId: order.requestId,
signedTransaction: Buffer.from(tx.serialize()).toString("base64"),
lastValidBlockHeight: order.lastValidBlockHeight,
});
let balance = await call("/balance");
for (let tries = 0; BigInt(balance.availableNano) === 0n && tries < 60; tries += 1) {
await new Promise((resolve) => setTimeout(resolve, 5_000));
balance = await call("/balance");
}
console.log("Credit:", balance.availableUsd);
const reply = await call("/v1/chat/completions", {
model: "minirouter/auto",
messages: [{ role: "user", content: "Say hi from an agent that paid in JUP." }],
max_tokens: 64,
});
console.log(reply.choices[0].message.content);API reference
Base URL https://api.minirouter.sh.
Create an account
- POST/
accounts/ agent - Auth: none
Request
No body.
Response
- accountId
stringAccount ID.- key.
key stringAPI key. Shown once.- key.
dailyLimitNano stringDaily spend cap in nano-USD. Default $25.- accessToken
stringDashboard access token. Shown once.- accessPath
stringAppend to https://minirouter.sh to open the dashboard.- depositProvisioning.
status stringready,pendingorunconfigured.- depositProvisioning.
address stringSolana deposit address, when ready.
Quote
- POST/
deposits/ solana-wallet/ quote - Auth: Bearer API key
Request
- inputMint
stringToken mint address.- inputAmount
stringWhole tokens.
Response
- inputSymbol
stringToken symbol.- inputAmount
stringAmount in base units.- expectedNano
stringExpected credit in nano-USD.- minimumNano
stringLeast credit you receive.- meetsMinimum
booleanWhether it clears the $0.50 minimum.
Create an intent
- POST/
deposits/ intents - Auth: Bearer API key
Request
- rail
stringsolana-usdc.- requestedNano
stringThe quote'sminimumNano.- idempotencyKey
stringUnique per payment. Retries return the same intent.
Response
- intentId
stringPass to order and execute.- stage
stringcreated,waiting,detected,confirming, thensettled.- payTo
stringThe account's deposit address.
Build the swap
- POST/
deposits/ solana-wallet/ order - Auth: Bearer API key
Request
- intentId
stringFrom the intent.- wallet
stringPaying wallet's public key.- inputMint
stringSame as the quote.- inputAmount
stringSame as the quote.
Response
- requestId
stringPass to execute.- transaction
stringUnsigned versioned transaction, base64.- lastValidBlockHeight
stringPass to execute.- minimumUsdcMicros
stringLeast USDC that lands, in micro-USDC.- expiresAt
stringExecute before this time.
Execute
- POST/
deposits/ solana-wallet/ execute - Auth: Bearer API key
Request
- intentId
stringFrom the intent.- requestId
stringFrom the order.- signedTransaction
stringSigned transaction, base64.- lastValidBlockHeight
stringFrom the order. Optional.
Response
- status
stringSuccess. Failures return an error.- signature
stringSolana transaction signature.- outputUsdcMicros
stringUSDC delivered, in micro-USDC.
Check the balance
- GET/
balance - Auth: Bearer API key
Request
No body.
Response
- availableNano
stringSpendable credit in nano-USD.- availableUsd
stringThe same, in USD.- reservedNano
stringHeld for requests in flight.
Limits
- Signups
- 5 per IP per hour.
- Key spend
- $25 per day until raised in key limits.
- Minimum payment
- $0.50.
- Quotes
- 30 per minute per account.
- Orders and executes
- 10 per minute each, per account.
- Auto Free and chat trial
- Not available, even after claiming.
Errors
- 400 invalid_request
- Unknown, unpriced or suspicious mint; USDC sent to the swap; wallet lacks the token or SOL.
- 403 forbidden
- Auto Free or the chat trial on an agent account.
- 429 rate_limited
- A limit above. Wait for
Retry-After. - 503 payment_unavailable
- Jupiter or the Solana RPC is unreachable. Retry.