Operate

Agent payments

An agent creates its own account and pays with Solana USDC or any Solana token.

How it works

JUPSOLMINIAny SPLUSDCAgent credit$10.25
  1. Sign upOne POST returns a key and a deposit address.
  2. PaySend USDC, or swap any Solana token into it.
  3. 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.js for 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.

Terminal
curl -X POST https://api.minirouter.sh/accounts/agent

2. Send USDC

Send at least $0.50 of Solana USDC to depositProvisioning.address.

Terminal
spl-token transfer --fund-recipient \
  EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v 5 <depositProvisioning.address>

3. Check the balance

availableNano turns positive once the payment finalizes.

Terminal
curl https://api.minirouter.sh/balance \
  -H "Authorization: Bearer $MINIROUTER_KEY"

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.

Terminal
curl -X POST https://api.minirouter.sh/accounts/agent

2. Quote

inputAmount is in whole tokens. minimumNano is the least credit you receive.

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

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

Terminal
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

sign.ts
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");
Terminal
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.

Terminal
curl https://api.minirouter.sh/balance \
  -H "Authorization: Bearer $MINIROUTER_KEY"

Full example

Signup, JUP swap, balance wait and a first paid request. Run with npx tsx agent-e2e.ts.

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
string Account ID.
key.key
string API key. Shown once.
key.dailyLimitNano
string Daily spend cap in nano-USD. Default $25.
accessToken
string Dashboard access token. Shown once.
accessPath
string Append to https://minirouter.sh to open the dashboard.
depositProvisioning.status
string ready, pending or unconfigured.
depositProvisioning.address
string Solana deposit address, when ready.
Quote
POST/deposits/solana-wallet/quote
Auth: Bearer API key

Request

inputMint
string Token mint address.
inputAmount
string Whole tokens.

Response

inputSymbol
string Token symbol.
inputAmount
string Amount in base units.
expectedNano
string Expected credit in nano-USD.
minimumNano
string Least credit you receive.
meetsMinimum
boolean Whether it clears the $0.50 minimum.
Create an intent
POST/deposits/intents
Auth: Bearer API key

Request

rail
string solana-usdc.
requestedNano
string The quote's minimumNano.
idempotencyKey
string Unique per payment. Retries return the same intent.

Response

intentId
string Pass to order and execute.
stage
string created, waiting, detected, confirming, then settled.
payTo
string The account's deposit address.
Build the swap
POST/deposits/solana-wallet/order
Auth: Bearer API key

Request

intentId
string From the intent.
wallet
string Paying wallet's public key.
inputMint
string Same as the quote.
inputAmount
string Same as the quote.

Response

requestId
string Pass to execute.
transaction
string Unsigned versioned transaction, base64.
lastValidBlockHeight
string Pass to execute.
minimumUsdcMicros
string Least USDC that lands, in micro-USDC.
expiresAt
string Execute before this time.
Execute
POST/deposits/solana-wallet/execute
Auth: Bearer API key

Request

intentId
string From the intent.
requestId
string From the order.
signedTransaction
string Signed transaction, base64.
lastValidBlockHeight
string From the order. Optional.

Response

status
string Success. Failures return an error.
signature
string Solana transaction signature.
outputUsdcMicros
string USDC delivered, in micro-USDC.
Check the balance
GET/balance
Auth: Bearer API key

Request

No body.

Response

availableNano
string Spendable credit in nano-USD.
availableUsd
string The same, in USD.
reservedNano
string Held 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.

More resources

Esc