> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rails.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Place and cancel your first perpetuals order with the Go SDK.

In this quickstart you write a Go program that places a post-only bid on `BTC-USDT`, cancels it, and prints how long the exchange took to acknowledge and to answer each command.

[Source on GitHub](https://github.com/rails-xyz/exchange-go-sdk) · [Package reference on pkg.go.dev](https://pkg.go.dev/github.com/rails-xyz/exchange-go-sdk/perps)

## Before You Begin

* A Rails account and an API key: see [Get Set Up with Rails](/latest/get-set-up-with-rails).
* Go 1.25 or later.

<Steps>
  <Step title="Install the SDK">
    ```bash theme={null}
    go get github.com/rails-xyz/exchange-go-sdk
    ```
  </Step>

  <Step title="Create a client">
    The client takes your API key and secret ([Credentials and Environments](/latest/go-sdk#credentials-and-environments)).

    ```go theme={null}
    client, err := perps.NewClient(rails.Credentials{
    	APIKey:    os.Getenv("RAILS_API_KEY"),
    	APISecret: os.Getenv("RAILS_API_SECRET"),
    })
    if err != nil {
    	return err
    }
    defer client.Close()
    ```
  </Step>

  <Step title="Connect to a market">
    `Connect` opens a WebSocket connection for one market, and returns once it is up. The connection always receives the [Order Creation Stream](/latest/perps/websocket-api/order-creation-stream), which carries the answers to your commands.

    ```go theme={null}
    conn, err := client.Connect(ctx, "BTC-USDT")
    if err != nil {
    	return err
    }
    defer conn.Close()
    ```
  </Step>

  <Step title="Place and cancel an order">
    `CreateOrder` returns a `*perps.OrderResult` once the exchange has answered, after the [acknowledgment and the confirmation](/latest/perps/guides/order-creation#order-creation-workflow): the order as the exchange last described it, and both moments as `Ack.At` and `TerminalAt`.

    ```go theme={null}
    created, err := conn.CreateOrder(ctx, perps.CreateOrderRequest{
    	OrderType: perps.OrderTypeBuy,
    	TradeType: perps.TradeTypeLimit,
    	Price:     "50000",
    	Quantity:  "0.0001",
    	PostOnly:  true,
    })
    if err != nil {
    	return err
    }

    cancel := perps.CancelOrderRequest{OrderID: created.Order.OrderID}
    if _, err := conn.CancelOrder(ctx, cancel); err != nil {
    	return err
    }
    ```
  </Step>

  <Step title="Run it">
    The program reads the market, price and quantity from its `-market`, `-price` and `-quantity` flags. Pass a price well below the market, so the bid rests on the book instead of trading.

    ```bash theme={null}
    RAILS_API_KEY=<key> RAILS_API_SECRET=<secret> go run . -price 50000
    ```

    ```text theme={null}
    created 01M3Z1DCBT0R5N3E7MMBNNWPQ1: acknowledged in 30.870917ms, active in 48.975417ms
    cancelled: acknowledged in 28.793416ms, cancelled in 45.082291ms
    ```
  </Step>
</Steps>

## Full Program

```go main.go expandable theme={null}
package main

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"os"
	"time"

	"github.com/rails-xyz/exchange-go-sdk/perps"
	"github.com/rails-xyz/exchange-go-sdk/rails"
)

func main() {
	if err := run(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func run() error {
	market := flag.String("market", "BTC-USDT", "market to trade")
	price := flag.String("price", "",
		"limit price, well below the market so the bid rests")
	quantity := flag.String("quantity", "0.0001", "order size")
	flag.Parse()
	if *price == "" {
		return errors.New("-price is required")
	}

	client, err := perps.NewClient(
		rails.Credentials{
			APIKey:    os.Getenv("RAILS_API_KEY"),
			APISecret: os.Getenv("RAILS_API_SECRET"),
		},
	)
	if err != nil {
		return err
	}
	defer client.Close()

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	conn, err := client.Connect(ctx, *market)
	if err != nil {
		return err
	}
	defer conn.Close()

	start := time.Now()
	created, err := conn.CreateOrder(ctx, perps.CreateOrderRequest{
		OrderType: perps.OrderTypeBuy,
		TradeType: perps.TradeTypeLimit,
		Price:     *price,
		Quantity:  *quantity,
		PostOnly:  true,
	})
	if err != nil {
		return err
	}
	fmt.Printf("created %s: acknowledged in %s, %s in %s\n",
		created.Order.OrderID, created.Ack.At.Sub(start),
		created.Order.OrderStatus, created.TerminalAt.Sub(start))

	start = time.Now()
	cancelled, err := conn.CancelOrder(ctx, perps.CancelOrderRequest{
		OrderID: created.Order.OrderID,
	})
	if err != nil {
		return err
	}
	fmt.Printf("cancelled: acknowledged in %s, %s in %s\n",
		cancelled.Ack.At.Sub(start), cancelled.Order.OrderStatus,
		cancelled.TerminalAt.Sub(start))
	return nil
}
```

## SDK and API Names

Where each SDK name is documented in the API reference:

| In the SDK | In the API reference |
| - | - |
| `client.Connect(ctx, market)`, `perps.MarketAll` | The `market` connection parameter, `ALL` for every market ([WebSocket overview](/latest/perps/websocket-api/overview)) |
| `perps.SubscriptionOrders`; `conn.CreateOrder`, `ModifyOrder`, `CancelOrder`, `UpdateMargin`; `perps.OrderFilled`, `perps.OrderRejected` | [Order Creation Stream](/latest/perps/websocket-api/order-creation-stream) (`orders`) |
| `perps.SubscriptionTrades`, `perps.Trades` | [Account Trades Stream](/latest/perps/websocket-api/account-trades-stream) (`trades`) |
| `perps.SubscriptionPublicTrades`, `perps.PublicTrades`, `conn.EmitPublicTrades` | [Public Trades Stream](/latest/perps/websocket-api/public-trades-stream) (`publicTrades`, `emitPublicCompletedOrders`) |
| `perps.WithSessionID`, `perps.SessionBackfill` | [WebSocket Session](/latest/websocket-session) (`sessionId`, `sessionBackfill`) |
| `client.OrderByID`, `client.OrderByClientRequestID` | [Get Order By ID](/latest/perps/rest-api/get-order-by-id) |
| `client.CompletedOrders` | [Get Completed Orders](/latest/perps/rest-api/get-completed-orders) |
| `client.CancelAllOrders` | [Cancel Orders](/latest/perps/rest-api/cancel-orders) |

## Next Steps

<CardGroup cols={2}>
  <Card title="Orders" icon="list-check" href="/latest/perps/go-sdk/orders">
    Modify and cancel orders, and recover from a command that got no answer.
  </Card>

  <Card title="Streams & Account" icon="tower-broadcast" href="/latest/perps/go-sdk/streams-and-account">
    Read your account, follow fills and market data, and keep a local order book.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.