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

> Find an options contract and place and cancel your first order on it with the Go SDK.

In this quickstart you write a Go program that finds a contract over HTTP, places a post-only bid on it well below its book over the WebSocket, 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/options)

## 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 := options.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="Find a contract">
    [Get Expirations](/latest/options/rest-api/get-expirations) lists a market's expiry dates, and [Get Contracts](/latest/options/rest-api/get-contracts) the contracts of one of them. The program picks the most expensive one, where a small bid rests instead of trading.

    ```go theme={null}
    expirations, err := client.Expirations(ctx, "BTC-USDT")
    if err != nil {
    	return err
    }
    if len(expirations) == 0 {
    	return errors.New("no expirations")
    }
    contracts, err := client.Contracts(ctx, "BTC-USDT", expirations[0].ExpiryDate)
    if err != nil {
    	return err
    }
    if len(contracts) == 0 {
    	return errors.New("no contracts")
    }
    contract, highest := contracts[0].ContractName, 0.0
    for _, c := range contracts {
    	if mark, _ := strconv.ParseFloat(c.MarkPrice, 64); mark > highest {
    		contract, highest = c.ContractName, mark
    	}
    }
    ```
  </Step>

  <Step title="Connect to the contract's expiry">
    `Connect` opens a WebSocket connection for the contracts of an `options.Scope`, the SDK's [contract filter](/latest/options/websocket-api/overview#contract-filter), and returns once it is up. Contract names spell the expiry second, as in `BTC-7FEB26-100000-C`. The connection always receives the [Order Management Stream](/latest/options/websocket-api/order-management-stream), which carries the answers to your commands.

    ```go theme={null}
    expiry := strings.Split(contract, "-")[1]
    conn, err := client.Connect(ctx, options.Scope{Market: "BTC-USDT", Expiration: expiry})
    if err != nil {
    	return err
    }
    defer conn.Close()
    ```
  </Step>

  <Step title="Place and cancel an order">
    `CreateOrder` returns an `*options.OrderResult` once the exchange has answered, after the [acknowledgment and the answer](/latest/options/guides/order-lifecycle#placing-orders-over-websocket): the order as the exchange last described it, and both moments as `AckAt` and `TerminalAt`.

    ```go theme={null}
    created, err := conn.CreateOrder(ctx, options.CreateOrderRequest{
    	Contract:  contract,
    	OrderType: options.OrderTypeBuy,
    	TradeType: options.TradeTypeLimit,
    	Price:     "10",
    	Quantity:  "1",
    	PostOnly:  true,
    })
    if err != nil {
    	return err
    }

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

  <Step title="Run it">
    The program reads the market and price from its `-market` and `-price` flags.

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

    ```text theme={null}
    created 538bb4ad-30dc-4baa-841a-3b04d96b4fe1 on BTC-9OCT26-74000-C: acknowledged in 30.393541ms, open in 40.862416ms
    cancelled in 24.813334ms
    ```
  </Step>
</Steps>

## Full Program

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

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

	"github.com/rails-xyz/exchange-go-sdk/options"
	"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", "underlying market")
	price := flag.String("price", "10",
		"limit price, well below the contract's book so the bid rests")
	flag.Parse()

	client, err := options.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()

	expirations, err := client.Expirations(ctx, *market)
	if err != nil {
		return err
	}
	if len(expirations) == 0 {
		return errors.New("no expirations on " + *market)
	}
	contracts, err := client.Contracts(ctx, *market, expirations[0].ExpiryDate)
	if err != nil {
		return err
	}
	if len(contracts) == 0 {
		return errors.New("no contracts on " + *market)
	}
	// A small bid rests on the most expensive contract.
	contract, highest := contracts[0].ContractName, 0.0
	for _, c := range contracts {
		if mark, _ := strconv.ParseFloat(c.MarkPrice, 64); mark > highest {
			contract, highest = c.ContractName, mark
		}
	}

	// One connection follows the whole expiry, which contract names spell second.
	expiry := strings.Split(contract, "-")[1]
	conn, err := client.Connect(ctx, options.Scope{Market: *market, Expiration: expiry})
	if err != nil {
		return err
	}
	defer conn.Close()

	start := time.Now()
	created, err := conn.CreateOrder(ctx, options.CreateOrderRequest{
		Contract:  contract,
		OrderType: options.OrderTypeBuy,
		TradeType: options.TradeTypeLimit,
		Price:     *price,
		Quantity:  "1",
		PostOnly:  true,
	})
	if err != nil {
		return err
	}
	fmt.Printf("created %s on %s: acknowledged in %s, %s in %s\n",
		created.Order.OrderID, contract, created.AckAt.Sub(start),
		created.Order.Status, created.TerminalAt.Sub(start))

	start = time.Now()
	cancelled, err := conn.CancelOrder(ctx, options.CancelOrderRequest{
		Contract: contract,
		OrderID:  created.Order.OrderID,
	})
	if err != nil {
		return err
	}
	fmt.Printf("%s in %s\n", cancelled.Order.Status, cancelled.TerminalAt.Sub(start))
	return nil
}
```

## SDK and API Names

Where each SDK name is documented in the API reference; [Streams & Account](/latest/options/go-sdk/streams-and-account) lists every stream with its event and snapshot:

| In the SDK | In the API reference |
| - | - |
| `options.Scope`, `options.ScopeAll()` | The [Contract Filter](/latest/options/websocket-api/overview#contract-filter): `market`, `expiration`, `strike` and `type`, or `market=ALL` |
| `options.SubscriptionOrders`; `conn.CreateOrder`, `ModifyOrder`, `CancelOrder`; `options.OrderFilled`, `OrderRejected`, `OrderCancelled`, `Liquidation` | [Order Management Stream](/latest/options/websocket-api/order-management-stream) (`optionsOrders`) |
| `conn.CancelAllOrders`, `client.CancelAllOrders` | The `cancelAllOrders` command on the Order Management Stream, and [Cancel All Orders](/latest/options/rest-api/cancel-all-orders) over HTTP |
| `options.SubscriptionPublicTrades`, `options.PublicTrades`, `conn.EmitPublicTrades` | [Public Trades Stream](/latest/options/websocket-api/public-trades-stream) (`optionsPublicTrades`, `emitPublicCompletedOrders`) |
| `options.WithSessionID`, `options.SessionBackfill` | [WebSocket Session](/latest/websocket-session) (`sessionId`, `sessionBackfill`) |
| `client.RecentOrders` | [Get Recent Orders](/latest/options/rest-api/get-account-orders) |
| `client.OrderStatus` | [Get Order Status](/latest/options/rest-api/get-order-status) |

## Next Steps

<CardGroup cols={2}>
  <Card title="Orders" icon="list-check" href="/latest/options/go-sdk/orders">
    Place, modify and cancel orders, and sweep a contract with a cancel-all.
  </Card>

  <Card title="Streams & Account" icon="tower-broadcast" href="/latest/options/go-sdk/streams-and-account">
    Read your account, and follow quotes, Greeks, positions and open orders.
  </Card>
</CardGroup>


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