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

# Orders

> Place, modify, and cancel options orders with the Go SDK, sweep a contract with a cancel-all, and pace your requests.

This page builds a program that places a post-only bid, modifies it and cancels it, then places two more and sweeps the contract with a cancel-all. Every command is [paced](/latest/go-sdk/configuration#pacing) to the budget of your account's type. It picks up from the [Quickstart](/latest/options/go-sdk/quickstart).

## Place an Order

`CreateOrder` takes an `OrderID` of your own, a ULID minted when empty. The program sets one and records it in `live` before the command goes out, so an order whose answer never arrives can still be found and cancelled. A refusal, or a command that never left, placed nothing:

```go theme={null}
func place(
	ctx context.Context,
	conn *options.Conn,
	bid options.CreateOrderRequest,
	live map[string]bool,
) (*options.OrderResult, error) {
	bid.OrderID = ulid.Make().String()
	live[bid.OrderID] = true
	created, err := conn.CreateOrder(ctx, bid)
	if err != nil {
		// Only a command that got no answer may still have been applied.
		if !errors.Is(err, rails.ErrTimeout) && !errors.Is(err, rails.ErrConnClosed) {
			delete(live, bid.OrderID)
		}
		return nil, err
	}
	return created, nil
}
```

```go theme={null}
live := map[string]bool{} // orders that may be on the book
bid := options.CreateOrderRequest{
	Contract:  contract,
	OrderType: options.OrderTypeBuy,
	TradeType: options.TradeTypeLimit,
	Price:     "10",
	Quantity:  "1",
	PostOnly:  true,
}
created, err := place(ctx, conn, bid, live)
if err != nil {
	return err
}
```

An answer is not always a resting order, so read `Order.Status`. A command on a contract outside the connection's scope is refused before it is sent, with `options.ErrOutOfScope`.

## Modify an Order

A modify changes the order's price and quantity in place, and keeps its id:

```go theme={null}
modify := options.ModifyOrderRequest{
	Contract: contract,
	OrderID:  created.Order.OrderID,
	Price:    "10",
	Quantity: "2",
}
if _, err := conn.ModifyOrder(ctx, modify); err != nil {
	return err
}
```

## Cancel an Order

`CancelOrder` is answered without an acknowledgment, so its `AckAt` is zero. An order already gone is refused with `options.CodeOrderNotFound`. `ViaHTTP` is explained [below](#when-the-socket-is-down).

```go theme={null}
cancelled, err := conn.CancelOrder(ctx, options.CancelOrderRequest{
	Contract: contract,
	OrderID:  created.Order.OrderID,
})
if err != nil {
	return err
}
if !cancelled.ViaHTTP {
	delete(live, created.Order.OrderID) // answered, so the order is gone
}
```

## Cancel Every Order

`conn.CancelAllOrders` sweeps one contract, or the connection's whole scope when `Contract` is empty, and returns once the exchange has [taken the sweep on](/latest/options/websocket-api/order-management-stream); each cancel is then answered as its own `options.OrderCancelled` or `options.OrderRejected` event, and `Count` says how many to expect. The program matches them to its orders by id; the example also handles one filled before the sweep reached it:

```go theme={null}
sweep, err := conn.CancelAllOrders(ctx, options.CancelAllOrdersRequest{
	Contract: contract,
})
if err != nil {
	return err
}
```

```go theme={null}
for len(live) > 0 {
	select {
	case <-ctx.Done():
		return ctx.Err()
	case event, ok := <-conn.Events():
		if !ok {
			return nil
		}
		switch e := event.(type) {
		case options.OrderCancelled:
			if live[e.Order.OrderID] {
				delete(live, e.Order.OrderID)
				fmt.Printf("swept %s\n", e.Order.OrderID)
			}
		case options.OrderRejected:
			switch {
			case !live[e.Order.OrderID]:
			case e.Code == options.CodeOrderNotFound:
				delete(live, e.Order.OrderID)
				fmt.Printf("%s was already gone\n", e.Order.OrderID)
			default:
				return fmt.Errorf("could not cancel %s: %s",
					e.Order.OrderID, e.Code)
			}
		}
	}
}
```

With no connection at all, `client.CancelAllOrders` sweeps one contract, or the whole account when `Contract` is empty, over HTTP.

## When the Socket Is Down

Cancels and reduce-only creates matter most when the connection is lost, so while the socket is down the SDK can send them over HTTP instead; other creates, and modifies, fail with the connection's error. A command sent over HTTP has `ViaHTTP` set and is only queued: its outcome arrives as an event, as for a command another connection sent. The [README](https://github.com/rails-xyz/exchange-go-sdk/blob/main/options/README.md#when-the-socket-is-down) has the exact conditions.

```go theme={null}
if sweep.ViaHTTP {
	fmt.Printf("sweep of %d orders queued over HTTP\n", sweep.Count)
} else {
	fmt.Printf("sweeping %d orders\n", sweep.Count)
}
```

## When a Command Gets No Answer

After `rails.ErrTimeout` or `rails.ErrConnClosed` a command may still have been applied, and its error carries the `clientRequestId`, a create's also the `OrderID` it went out under. Either look the order up, as the example does, or send the command again with that `ClientRequestID` set: within 60 seconds the exchange [refuses a repeat](/latest/options/websocket-api/overview#request-envelope) with a `409` instead of executing it twice. Only the lookup says what happened to the order.

## Clean Up After a Failure

Closing a connection doesn't cancel its orders. The program cancels any it may still have on the book when it stops. Each cancel gets a context of its own, since the program's may be what ran out:

```go theme={null}
defer func() {
	for orderID := range live {
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		req := options.CancelOrderRequest{Contract: contract, OrderID: orderID}
		_, err := conn.CancelOrder(ctx, req)
		cancel()
		if err != nil {
			fmt.Fprintf(os.Stderr, "cancelling %s: %v\n", orderID, err)
		}
	}
}()
```

## Run the Example

The complete program is [`examples/options-orders`](https://github.com/rails-xyz/exchange-go-sdk/tree/main/examples/options-orders) in the SDK repository. Run it with a price well below the contract's book:

```bash theme={null}
RAILS_API_KEY=<key> RAILS_API_SECRET=<secret> go run ./examples/options-orders -price 10
```

```text theme={null}
created 01M3Z7DPF83ZA8BAY0BTQ0N3B4 on BTC-9OCT26-74000-C: open
modified 01M3Z7DPF83ZA8BAY0BTQ0N3B4: quantity 2
cancelled 01M3Z7DPF83ZA8BAY0BTQ0N3B4
created 01M3Z7DPJ6DPNVYABBFF16RZVG
created 01M3Z7DPK1EF0G4AXJD59RNC04
sweeping 2 orders
swept 01M3Z7DPK1EF0G4AXJD59RNC04
swept 01M3Z7DPJ6DPNVYABBFF16RZVG
```

## Related

* [Order Lifecycle](/latest/options/guides/order-lifecycle)
* [Order Management Stream](/latest/options/websocket-api/order-management-stream), [Cancel Order](/latest/options/rest-api/cancel-order) and [Cancel All Orders](/latest/options/rest-api/cancel-all-orders)
* [Rate Limits](/latest/options/guides/rate-limits) and [Error Codes](/latest/options/guides/error-codes)


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