# Quickstart

From nothing to a protected order on a sandbox account in five minutes, in the language you use.

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.

:::steps
### 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.

> [!WARNING]
> The key is shown once. Copy it into your password manager or your environment before you close the window. If you lose it, revoke it and create another.

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

```bash title="macOS and Linux"
export PHOENIXPERPS_API_KEY="ppk_test_..."
```

```powershell title="Windows"
$env:PHOENIXPERPS_API_KEY = "ppk_test_..."
```

### Install an SDK

Pick your language once: every sample on every page of these docs follows it.

```curl
# curl is all you need; skip this step
```

```python
pip install phoenixperps
```

```typescript
npm install @phoenixperps/sdk
```

```csharp
dotnet add package PhoenixPerps.Sdk
```

```go
go get github.com/phoenixperps/sdk/go
```

```java
implementation("com.phoenixperpsfunding:phoenixperps-sdk:1.0.0")
```

```rust
cargo add phoenixperps
```

```php
composer require phoenixperps/sdk
```

### List 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
curl https://sandbox-api.phoenixperpsfunding.com/v1/accounts \
  -H "Authorization: Bearer $PHOENIXPERPS_API_KEY"
```

```python
from phoenixperps import PhoenixPerps

client = PhoenixPerps()  # reads PHOENIXPERPS_API_KEY

for account in client.accounts.list():
    print(account.id, account.status, account.equity)
```

```typescript
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);
}
```

```csharp
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}");
}
```

```go
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)
}
```

```java
var client = PhoenixPerpsClient.builder().build(); // reads PHOENIXPERPS_API_KEY

for (var account : client.accounts().list()) {
    System.out.println(account.id() + " " + account.status() + " " + account.equity());
}
```

```rust
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);
}
```

```php
$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
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" }
  }'
```

```python
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... working
```

```typescript
const 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... working
```

```csharp
var 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}");
```

```go
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)
```

```java
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());
```

```rust
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);
```

```php
$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-Key` for 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.

## Where to go next

:::cards
- [The sandbox](/sandbox) Ten accounts for life, how they reset, and what they never touch.
- [Keys and limits](/authentication) Read or trade keys, per-key loss stops, IP allowlists.
- [Orders](/guides/orders) Every type, time in force, and how the engine fills them.
- [API reference](/reference) Every endpoint and field, with samples in your language.
:::
