Trading API
Place orders from your own program, in any language. One key, three endpoints, and the same fill engine a click on this site goes through. A record made this way ranks beside a record made by hand, because there is nothing different about how it was made.
Get a key
Mint one on the strategies page. It is shown once and only its hash is stored, so it cannot be recovered. Send it on every request:
Authorization: Bearer pk_live_...Never in a query string. A key in a URL ends up in access logs, in browser history and in the referrer sent to the next site you visit.
The endpoints
POST /api/v1/orders{ mint, side: "buy" | "sell", size, slippageBps? }. Size is lamports on a buy and token base units on a sell, always as a string, because a JSON number cannot hold a lamport balance without rounding it. Answersfilledorrejected, and a rejection is a real outcome at 200: a reverted transaction is not an error.GET /api/v1/account- Balance, open positions, the season you are in, and how much of today’s allowance is left. Positions come back marked at the last known price, which is what a chart says and not what a sell would fetch. Do not size an exit off it.
GET /api/v1/tokens- What there is to trade, with age, depth and market cap where they are known, plus whether the token names an X account or a website and how many launches this site has indexed from its creator. Nothing here reads the chain, so it can be polled freely. Those last three are
nullwhere they are not known, which is not the same as false: a token seconds old has no metadata read yet.
A whole bot
Save it as bot.mjs and run it with node bot.mjs on Node 18 or newer. The extension matters: this uses await at the top level, which a plain .js file is not allowed to do unless the project is already a module.
const KEY = process.env.PROBATIO_KEY; // from /strategies
const BASE = 'https://probatiotrade.com/api/v1';
const call = async (path, init = {}) =>
(await fetch(BASE + path, {
...init,
headers: { authorization: `Bearer ${KEY}`, 'content-type': 'application/json' },
})).json();
// Buy the first fresh, liquid launch we are not already holding.
const me = await call('/account');
const { tokens } = await call('/tokens?limit=50');
const held = new Set(me.positions.map((p) => p.mint));
for (const token of tokens) {
if (held.has(token.mint)) continue;
if (token.graduated) continue;
if (token.ageSeconds > 90) continue;
if (BigInt(token.liquidityLamports ?? '0') < 20_000_000_000n) continue;
const fill = await call('/orders', {
method: 'POST',
body: JSON.stringify({
mint: token.mint,
side: 'buy',
size: '250000000', // 0.25 SOL, in lamports, as a string
}),
});
console.log(fill.status, fill.filled?.solAmount, fill.filled?.priceImpactBps + 'bps');
break;
}And to close it:
// Sell all of it. Sizes are token base units on a sell, lamports on a buy.
const [position] = (await call('/account')).positions;
await call('/orders', {
method: 'POST',
body: JSON.stringify({
mint: position.mint,
side: 'sell',
size: position.tokenAmount,
}),
});Three things that surprise people
- The latency is real. Your order reads the pool, waits out the season’s delay, reads again, and is quoted against what the pool actually became. It is not a simulated pause over one reading. Sometimes the price moves against you in that window, and sometimes the order fails. That is the whole point of this simulator.
- There is a daily cap. Two hundred automated orders a day, across this API and any hosted strategy together. Every fill reads the chain twice, so this is what stops one runaway loop spending a month of the site’s allowance in a day. Past it you get a 429 that says how many you have used.
- Your program has to be running. If your machine sleeps, your bot stops. If that is a problem, write the same rules in the form instead and this site runs them for the whole season with your laptop shut.
What a key can and cannot do
It places orders on the account you already entered the season with. It is not a second entrant and pays no second entry. It cannot mint another key, cannot move real money, cannot read anything but your own account, and stops working the instant you revoke it.
If you want an entrant that is nothing but the algorithm, with no human hands on it at all, enter with a second wallet and give that one the key.