Get started
Quickstart.
From nothing to a protected order on a sandbox account in five minutes, in the language you use.
On this page
You will create a sandbox key, read your accounts, and place a limit order with its stop loss and take profit held on our servers. Everything here runs on paper money: nothing touches your evaluation or funded accounts.
Create a sandbox key
In your dashboard, open Developers and choose Create API key. Pick Sandbox, then Read and trade, and give the key a name you will recognise, like the bot that will use it.
Sandbox keys need no email code. Your first one also opens a sandbox account of $100,000 for you, so there is something to trade on straight away.
Put the key in your environment
Every SDK and every example in these docs reads the key from
PHOENIXPERPS_API_KEY. Keeping it out of your code means it never ends up in a repository.export PHOENIXPERPS_API_KEY="ppk_test_..."$env:PHOENIXPERPS_API_KEY = "ppk_test_..."Install an SDK
Pick your language once: every sample on every page of these docs follows it.
# curl is all you need; skip this steppip install phoenixperpsnpm install @phoenixperps/sdkdotnet add package PhoenixPerps.Sdkgo get github.com/phoenixperps/sdk/goimplementation("com.phoenixperpsfunding:phoenixperps-sdk:1.0.0")cargo add phoenixperpscomposer require phoenixperps/sdkList your accounts
The key decides the host: a
ppk_test_key works on the sandbox host only, so the SDKs pick it for you. With curl, use the sandbox host.curl https://sandbox-api.phoenixperpsfunding.com/v1/accounts \ -H "Authorization: Bearer $PHOENIXPERPS_API_KEY"from phoenixperps import PhoenixPerps client = PhoenixPerps() # reads PHOENIXPERPS_API_KEY for account in client.accounts.list(): print(account.id, account.status, account.equity)import { PhoenixPerps } from "@phoenixperps/sdk"; const client = new PhoenixPerps(); // reads PHOENIXPERPS_API_KEY for await (const account of client.accounts.list()) { console.log(account.id, account.status, account.equity); }using PhoenixPerps; var client = new PhoenixPerpsClient(); // reads PHOENIXPERPS_API_KEY await foreach (var account in client.Accounts.ListAsync()) { Console.WriteLine($"{account.Id} {account.Status} {account.Equity}"); }client, err := phoenixperps.NewClient() // reads PHOENIXPERPS_API_KEY if err != nil { log.Fatal(err) } for account, err := range client.Accounts.List(context.Background(), nil) { if err != nil { log.Fatal(err) } fmt.Println(account.ID, account.Status, account.Equity) }var client = PhoenixPerpsClient.builder().build(); // reads PHOENIXPERPS_API_KEY for (var account : client.accounts().list()) { System.out.println(account.id() + " " + account.status() + " " + account.equity()); }let client = phoenixperps::Client::builder().build()?; // reads PHOENIXPERPS_API_KEY let mut accounts = client.accounts().list(Default::default()); while let Some(account) = accounts.next().await { let account = account?; println!("{} {} {}", account.id, account.status, account.equity); }$client = new PhoenixPerps\Client(); // reads PHOENIXPERPS_API_KEY foreach ($client->accounts->list() as $account) { echo $account->id, ' ', $account->status, ' ', $account->equity, PHP_EOL; }You get your sandbox account, named like
SANDBOX-00042-001. That name is its id in every path.Place an order with its exits
This buys 0.010 BTC with a limit at 62,500, a take profit at 64,000 and a stop loss at 61,800. The exits wait on our servers as reduce-only orders: they protect the position even if your bot stops.
curl -X POST https://sandbox-api.phoenixperpsfunding.com/v1/accounts/SANDBOX-00042-001/orders \ -H "Authorization: Bearer $PHOENIXPERPS_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "market": "BTC-USD", "side": "buy", "type": "limit", "size": "0.010", "limit_price": "62500.00", "take_profit": { "price": "64000.00" }, "stop_loss": { "price": "61800.00" } }'order = client.orders.create( account_id="SANDBOX-00042-001", market="BTC-USD", side="buy", type="limit", size="0.010", limit_price="62500.00", take_profit={"price": "64000.00"}, stop_loss={"price": "61800.00"}, ) print(order.id, order.status) # ord_01JAB7Q8XK... workingconst order = await client.orders.create({ account_id: "SANDBOX-00042-001", market: "BTC-USD", side: "buy", type: "limit", size: "0.010", limit_price: "62500.00", take_profit: { price: "64000.00" }, stop_loss: { price: "61800.00" }, }); console.log(order.id, order.status); // ord_01JAB7Q8XK... workingvar order = await client.Orders.CreateAsync(new CreateOrderParams { AccountId = "SANDBOX-00042-001", Market = "BTC-USD", Side = "buy", Type = "limit", Size = 0.010m, LimitPrice = 62500.00m, TakeProfit = new TakeProfit { Price = 64000.00m }, StopLoss = new StopLoss { Price = 61800.00m }, }); Console.WriteLine($"{order.Id} {order.Status}");order, err := client.Orders.Create(context.Background(), &phoenixperps.CreateOrderParams{ AccountID: "SANDBOX-00042-001", Market: "BTC-USD", Side: "buy", Type: "limit", Size: "0.010", LimitPrice: "62500.00", TakeProfit: &phoenixperps.TakeProfit{Price: "64000.00"}, StopLoss: &phoenixperps.StopLoss{Price: "61800.00"}, }) if err != nil { log.Fatal(err) } fmt.Println(order.ID, order.Status)var order = client.orders().create(CreateOrderParams.builder() .accountId("SANDBOX-00042-001") .market("BTC-USD") .side("buy") .type("limit") .size(new BigDecimal("0.010")) .limitPrice(new BigDecimal("62500.00")) .takeProfit(TakeProfit.builder().price(new BigDecimal("64000.00")).build()) .stopLoss(StopLoss.builder().price(new BigDecimal("61800.00")).build()) .build()); System.out.println(order.id() + " " + order.status());let order = client.orders().create(CreateOrderParams { account_id: "SANDBOX-00042-001".into(), market: "BTC-USD".into(), side: "buy".into(), r#type: "limit".into(), size: Some(dec!(0.010)), limit_price: Some(dec!(62500.00)), take_profit: Some(TakeProfit { price: dec!(64000.00), ..Default::default() }), stop_loss: Some(StopLoss { price: dec!(61800.00), ..Default::default() }), ..Default::default() }).await?; println!("{} {}", order.id, order.status);$order = $client->orders->create([ 'account_id' => 'SANDBOX-00042-001', 'market' => 'BTC-USD', 'side' => 'buy', 'type' => 'limit', 'size' => '0.010', 'limit_price' => '62500.00', 'take_profit' => ['price' => '64000.00'], 'stop_loss' => ['price' => '61800.00'], ]); echo $order->id, ' ', $order->status, PHP_EOL;The SDKs send an
Idempotency-Keyfor you and reuse it if they retry, so a dropped connection never places the order twice. With curl, send your own.
What you just did#
You traded through the same engine, with the same prices and the same rules as your real accounts, on a sandbox account that will never count towards a payout. When your bot behaves, create a live key and change nothing else: the SDKs move to the live host by themselves.