# Sandbox quickstart

Go from an empty organization to a drawn card in about ten minutes. Everything here runs in the sandbox, so no real money or cards are involved.

## 1. Create an organization and a key

1. Sign in at [sandbox.partner.packflip.xyz](https://sandbox.partner.packflip.xyz/dashboard). The sandbox and production share one login, but their data is separate.
2. Create or select an organization. API keys, balance, and customers belong to the organization, not to you.
3. Open **API keys**, create a key, and copy it. It starts with `pk_` and is shown only once.

```bash
export PACKFLIP_BASE_URL=https://sandbox.partner.packflip.xyz
export PACKFLIP_API_KEY=pk_...
```

Keep the key on your server. Every request sends it as a bearer token.

## 2. Add test credit

Operations draw from a prepaid USD balance. In the sandbox you can add test credit instead of sending testnet USDC, either with **Add $100 test credit** in the console or through the API:

```bash
curl -X POST "$PACKFLIP_BASE_URL/api/v2/sandbox/credits" \
  -H "Authorization: Bearer $PACKFLIP_API_KEY"
```

```json
{
  "ledgerEntryId": "…",
  "creditedUsd": "100.000000",
  "balance": { "currency": "USD", "cash": "100.000000", "bonus": "0.000000", "total": "100.000000" }
}
```

Test credit can be added once an hour, up to a $1,000 balance. The endpoint returns `404` in production.

## 3. Pick a vending machine

A vending machine is a pack you can sell. Note its `id` and `priceUsd`.

```bash
curl "$PACKFLIP_BASE_URL/api/v2/vending-machines" \
  -H "Authorization: Bearer $PACKFLIP_API_KEY"
```

## 4. Create a customer

A customer represents one of your users and owns the cards they draw. Set `externalUserId` to your own user ID so you can look the customer up later.

```bash
curl -X POST "$PACKFLIP_BASE_URL/api/v2/customers" \
  -H "Authorization: Bearer $PACKFLIP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "externalUserId": "user_123" }'
```

The response contains the customer ID, for example `cus_…`.

## 5. Draw a pack

Orders are commerce writes, so they need an `Idempotency-Key`. Generate a new one for each purchase and reuse it only when retrying that same purchase.

```bash
curl -X POST "$PACKFLIP_BASE_URL/api/v2/operations" \
  -H "Authorization: Bearer $PACKFLIP_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-user_123-0001" \
  -d '{
    "kind": "order",
    "customerId": "cus_…",
    "vendingMachineId": 1,
    "quantity": 1
  }'
```

The response is an operation with `status: "completed"`, the amount charged in `chargedUsd`, and the drawn cards in `cards`. Send the same request again and you get the same operation with `replayed: true`, and no second charge.

## 6. Show the cards

```bash
curl "$PACKFLIP_BASE_URL/api/v2/customers/cus_…/cards" \
  -H "Authorization: Bearer $PACKFLIP_API_KEY"
```

Each card has a `name`, an `image` URL with an `imageSrcset` for responsive images, and `buybackUsd`, its current buyback value.

## 7. Buy a card back

If your user does not want a card, buy it back. The value is credited to your balance.

```bash
curl -X POST "$PACKFLIP_BASE_URL/api/v2/operations" \
  -H "Authorization: Bearer $PACKFLIP_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: buyback-user_123-0001" \
  -d '{
    "kind": "buyback",
    "mode": "offchain",
    "customerId": "cus_…",
    "cardIds": ["card_…"]
  }'
```

## Next steps

- [Core concepts](/docs/concepts): accounts, customers, cards, and operations.
- [Cards and operations](/docs/cards): sealed packs, refunds, redemption, and shipping.
- [Webhooks](/docs/webhooks): react to deposits and operations without polling.
- [Going live](/docs/going-live): what changes in production.
