# API Reference

Complete reference for the `arrow` package (`github.com/arrow-trade/go-arrow/arrow`), current as of **v1.8.0**.

## Client

### NewClient / NewClientWithTimeout

```go
client := arrow.NewClient("YOUR_APP_ID", "YOUR_APP_SECRET")
client := arrow.NewClientWithTimeout("YOUR_APP_ID", "YOUR_APP_SECRET", 30*time.Second)
```

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `appID` | string | ✓ | Application identifier |
| `appSecret` | string | ✓ | Application secret (used for `Authenticate` checksums) |
| `timeout` | `time.Duration` | - | REST timeout; zero or negative falls back to `DefaultHTTPTimeout` (10s) |

`Config` fields: `AppID`, `AppSecret`, `Token`, `BaseURL` (default `https://edge.arrow.trade`), `Debug`, `Timeout`.

---

### SetHTTPTimeout / HTTPTimeout

```go
client.SetHTTPTimeout(30 * time.Second)
d := client.HTTPTimeout()
```

`SetHTTPTimeout(≤0)` is ignored. Do not assign `client.HTTPClient.ReadTimeout` yourself.

---

### SetDebug / IsDebug

```go
client.SetDebug(true)
if client.IsDebug() { /* verbose zerolog lifecycle logs */ }
```

---

## Authentication Methods

### Authenticate

```go
token, err := client.Authenticate(requestToken)
```

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `requestToken` | string | ✓ | Token from OAuth callback |

**Returns:** `(string, error)` — access token. Also sets `Config.Token`.

---

### AutoLogin

```go
err := client.AutoLogin(username, password, totpSecret)
```

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `username` | string | ✓ | User ID |
| `password` | string | ✓ | Account password |
| `totpSecret` | string | ✓ | Base32 TOTP secret |

App secret comes from `NewClient`. **Returns:** `error`.

---

### Login

```go
client.Login()
```

Prints `https://app.arrow.trade/app/login?appId=...`, reads a request token from stdin, then calls `Authenticate`. No return value.

---

### SetToken / GetToken

```go
client.SetToken("access_token")
token := client.GetToken()
```

Clear a session with `client.SetToken("")`.

---

### GenerateChecksum

```go
sum := arrow.GenerateChecksum(appID, appSecret, requestToken)
```

SHA256 hex of `appId:appSecret:request-token`.

---

## Order Methods

### PlaceOrder

```go
resp, err := client.PlaceOrder("regular", arrow.OrderRequest{ /* ... */ })
orderNo := resp.Data.OrderNo
```

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `orderType` | string | ✓ | Variety, typically `"regular"` |
| `order` | `OrderRequest` | ✓ | See fields below |

**`OrderRequest`:** `Exchange`, `Quantity`, `DisclosedQty`, `Product`, `Symbol`, `TransactionType`, `OrderType` (JSON `order`), `Price`, `Validity`, `Remarks`, `MarketProtection` (`mpp`), `TriggerPrice`. All quantity/price fields are strings.

**Returns:** `(*OrderResponse, error)`

---

### ModifyOrder

```go
resp, err := client.ModifyOrder("regular", orderID, arrow.OrderRequest{ /* ... */ })
```

**Returns:** `(*OrderResponse, error)`

---

### CancelOrder

```go
err := client.CancelOrder("regular", orderID)
```

**Returns:** `error`

---

### CancelAllOrders

```go
err := client.CancelAllOrders()
```

Cancels `OPEN`, `TRIGGER_PENDING`, `PARTIALLY_FILLED`. Skips `PENDING` / `PENDINGNEW` / `PENDING_NEW` and returns an error if any remain pending.

**Returns:** `error`

---

### GetOrder

```go
details, err := client.GetOrder(orderID)
```

**Returns:** `(*OrderDetailsResponse, error)` — events in `details.Data`.

---

### GetOrderBook

```go
orders, err := client.GetOrderBook()
```

**Returns:** `([]OrderDetails, error)`

---

### GetTradeBook

```go
trades, err := client.GetTradeBook()
```

**Returns:** `([]Trade, error)` — use `Trade.OrderID`.

---

## Portfolio / User Methods

### GetUserDetails

```go
user, err := client.GetUserDetails()
name := user.Data.Name
```

**Returns:** `(*User, error)`

Helpers: `user.HasDefaultBankAccount()`, `user.GetDefaultBankAccount()`, `user.HasExchangeAccess(exchange)`, `user.IsTotpEnabled()`.

---

### GetHoldings

```go
holdings, err := client.GetHoldings()
```

**Returns:** `([]Holding, error)`

---

### GetPositions

```go
positions, err := client.GetPositions()
```

**Returns:** `([]Position, error)`

---

### GetLimits

```go
limits, err := client.GetLimits()
usable := limits.Data.Margin["usableMargin"]
```

**Returns:** `(*Limits, error)`

---

## Margin Methods

### GetMargin

```go
margin, err := client.GetMargin(arrow.MarginRequest{
    Exchange:         arrow.ExchangeNSE,
    Symbol:           "RELIANCE-EQ",
    Quantity:         "1",
    Price:            "1450.0",
    Product:          arrow.ProductCNC,
    TransactionType:  arrow.TransactionTypeBuy,
    Order:            arrow.OrderTypeLimit,
    IncludePositions: true,
})
```

**Returns:** `(*MarginResponse, error)` — `Data.RequiredMargin`, `MinimumCashRequired`, `MarginUsedAfterTrade`, `Charge`.

---

### GetBasketMargin

```go
result, err := client.GetBasketMargin(arrow.BasketMarginRequest{
    Orders:           []arrow.MarginRequest{ /* ... */ },
    IncludePositions: false,
})
```

!!! note "Request body shape"
    Some REST curl examples show a top-level JSON **array** of orders.
    The Go client (and Python SDK) wrap the payload as `{ "orders": [...], "includePositions": bool }`.

**Returns:** `(map[string]any, error)`

---

## Market Data Methods

### GetQuote

```go
quote, err := client.GetQuote(arrow.ExchangeNSE, "RELIANCE-EQ", arrow.InfoQuoteLTP)
```

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `exchange` | `Exchange` | ✓ | Exchange |
| `symbol` | string | ✓ | Trading symbol |
| `mode` | `InfoQuoteMode` | ✓ | `InfoQuoteLTP`, `InfoQuoteOHLCV`, `InfoQuoteFull` |

**Returns:** `(map[string]any, error)`

---

### GetQuotes

```go
quotes, err := client.GetQuotes([]arrow.QuoteInstrument{
    {Exchange: "NSE", Symbol: "RELIANCE-EQ"},
}, arrow.InfoQuoteLTP)
```

**Returns:** `([]map[string]any, error)` — LTP rows are token-keyed (`token`, `ltp`, `close`).

---

### GetGreeks

```go
raw, err := client.GetGreeks([]arrow.GreeksInstrument{
    {Exchange: string(arrow.ExchangeNFO), Symbol: "NIFTY16JUN26C23150"},
})
```

**Returns:** `(json.RawMessage, error)`

---

### GetOptionChain

```go
raw, err := client.GetOptionChain(arrow.OptionChainRequest{
    Underlying: "NIFTY",
    Exchange:   arrow.ExchangeINDEX,
    Count:      "10",
    Expiry:     "16-JUN-2026",
})
```

**Returns:** `(json.RawMessage, error)`

---

### GetAllOptionChainSymbols

```go
symbols, err := client.GetAllOptionChainSymbols()
expiries := symbols["indices"]["INDEX:NIFTY"]
```

**Returns:** `(OptionChainSymbolsByCategory, error)` — `map[string]map[string][]string`

---

### GetHolidays

```go
data, err := client.GetHolidays()
```

**Returns:** `(*HolidaysData, error)` — `Holidays`, `SpecialTradingDays`

---

### GetIndexList

```go
indices, err := client.GetIndexList()
```

**Returns:** `([]map[string]any, error)`

---

### GetInstruments / GetInstrumentsCSV

```go
csvText, err := client.GetInstrumentsCSV(arrow.InstrumentSegmentAll)
rows, err := client.GetInstruments(arrow.InstrumentSegmentMCX)
```

| Segment | Path |
|---------|------|
| `InstrumentSegmentAll` | `/all` |
| `InstrumentSegmentNSE` | `/nse` |
| `InstrumentSegmentBSE` | `/bse` |
| `InstrumentSegmentMCX` | `/mcx` |
| `InstrumentSegmentIndices` | `/indices` |

---

### GetCandleData

```go
raw, err := client.GetCandleData(arrow.ExchangeNSE, "3045", "5min", from, to, false)
```

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `exchange` | `Exchange` | ✓ | Path segment; `MCXFO` is sent as `mcx` |
| `token` | string | ✓ | Instrument token |
| `interval` | string | ✓ | `min`, `5min`, `day`, … |
| `fromTimestamp` / `toTimestamp` | string | ✓ | `YYYY-MM-DDTHH:MM:SS` |
| `oi` | bool | ✓ | Adds `oi=1` (NFO only) |

Host: `https://historical-api.arrow.trade`. **Returns:** `(json.RawMessage, error)` — JSON array of candle rows.

---

## Streaming Methods

### NewStreams / NewStreamsOrderOnly / NewStreamsWithHFT

```go
streams, err := client.NewStreams()
streams, err := client.NewStreamsOrderOnly()
streams, err := client.NewStreamsWithHFT()
defer streams.Close()
```

`ArrowStreams` fields: `Client`, `OrderStream`, `DataStream` (nil with HFT factory), `HFTDataStream` (nil with `NewStreams`).

---

### ConnectOrderStream / ConnectDataStream / ConnectHFTDataStream

```go
orders, err := client.ConnectOrderStream()
data, err := client.ConnectDataStream()
hft, err := client.ConnectHFTDataStream()
```

---

### DataStream.Subscribe / Unsubscribe

```go
err := streams.DataStream.Subscribe(arrow.StreamModeQuote, []int32{3045, 1594})
err := streams.DataStream.Unsubscribe(arrow.StreamModeQuote, []int32{3045})
```

---

### DataStream.ReadTicks / ParseMarketTick

```go
streams.DataStream.ReadTicks(ctx, onTick, onError)
tick, err := arrow.ParseMarketTick(raw)
```

---

### OrderStream.ReadUpdates

```go
streams.OrderStream.ReadUpdates(ctx, onUpdate, onError)
```

---

### HFT subscribe / unsubscribe

```go
err := hft.SubscribeHFTSymbols(mode, symbols, latencyMs)
err := hft.SubscribeHFTTokens(mode, exchSeg, ids, latencyMs)
err := hft.SubscribeHFTBySegment(mode, map[int][]int32{arrow.HFTExchNSEFO: {5042}}, latencyMs)
err := hft.UnsubscribeHFTSymbols(mode, symbols)
err := hft.UnsubscribeHFTTokens(mode, exchSeg, ids)
```

`mode`: `"ltpc"` / `"l"`, `"full"` / `"f"`, `"cas"` (CAS omits `latency` on the wire).

---

### HFTDataStream.ReadHFT

```go
hft.ReadHFT(ctx, onLTP, onFull, onCAS, onResponse, onError)
```

---

### StartKeepAlive

```go
go arrow.StartKeepAlive(ctx, conn, 3*time.Second)
```

Sends `"PONG"` text frames on a ticker.

---

## Constants

### Exchange

| Constant | Value |
|----------|-------|
| `ExchangeNSE` | `NSE` |
| `ExchangeBSE` | `BSE` |
| `ExchangeNFO` | `NFO` |
| `ExchangeNCD` | `NCD` |
| `ExchangeBFO` | `BFO` |
| `ExchangeBCD` | `BCD` |
| `ExchangeMCX` | `MCX` |
| `ExchangeMCXFO` | `MCXFO` |
| `ExchangeNSESLBM` | `NSESLBM` |
| `ExchangeINDEX` | `INDEX` |

### Product

| Constant | Value |
|----------|-------|
| `ProductCNC` | `C` |
| `ProductMIS` | `I` |
| `ProductNRML` | `M` |

### TransactionType

| Constant | Value |
|----------|-------|
| `TransactionTypeBuy` | `B` |
| `TransactionTypeSell` | `S` |

### OrderType

| Constant | Value |
|----------|-------|
| `OrderTypeLimit` | `LMT` |
| `OrderTypeMarket` | `MKT` |
| `OrderTypeSL` | `SL` |
| `OrderTypeSLM` | `SL-M` |
| `OrderTypeSLLMT` | `SL-LMT` |
| `OrderTypeSLMKT` | `SL-MKT` |

### Validity

| Constant | Value |
|----------|-------|
| `ValidityDAY` | `DAY` |
| `ValidityIOC` | `IOC` |
| `ValidityGTC` | `GTC` |

### InfoQuoteMode (REST)

| Constant | Value |
|----------|-------|
| `InfoQuoteLTP` | `ltp` |
| `InfoQuoteOHLCV` | `ohlcv` |
| `InfoQuoteFull` | `full` |

### StreamMode (WebSocket)

| Constant | Value |
|----------|-------|
| `StreamModeLTP` | `ltp` |
| `StreamModeLTPC` | `ltpc` |
| `StreamModeQuote` | `quote` |
| `StreamModeFull` | `full` |

### HFT segments

| Constant | Value |
|----------|-------|
| `HFTExchNSECM` | `0` |
| `HFTExchNSEFO` | `1` |
| `HFTExchBSECM` | `2` |
| `HFTExchBSEFO` | `3` |
| `HFTExchMCXFO` | `4` |

---

## MarketTick Properties

See [WebSocket Streaming](websocket-streaming.md#markettick-fields) for the full field table, including `IsCAS`, `ImbalanceQty`, `IndicativeClose`, and `RefPrice`.

---

## Errors

REST helpers return `error` for transport failures, HTTP ≥ 400 (`request failed with status %d: %s`), and API envelopes where `status != "success"`.

`PlaceOrder` / `ModifyOrder` may return a generic `"order placement failed"` even when `OrderResponse.Message` / `ErrorCode` are populated — inspect the response when the pointer is non-nil.

Stream readers call `onError` for parse or socket errors and return when the context is cancelled or the socket closes.

See [Error codes](../rest-api/error-codes.md) for application codes.

---

## Python → Go mapping

| Python | Go |
|--------|-----|
| `ArrowClient(app_id)` | `NewClient(appID, appSecret)` |
| `login(request_token, api_secret)` | `Authenticate(requestToken)` |
| `auto_login(...)` | `AutoLogin(username, password, totpSecret)` |
| `place_order(...)` | `PlaceOrder("regular", OrderRequest{...})` |
| `modify_order` / `cancel_order` | `ModifyOrder` / `CancelOrder` (variety argument) |
| `cancel_all_orders()` | `CancelAllOrders()` |
| `get_order_details` | `GetOrder` |
| `get_user_limits` | `GetLimits` |
| `order_margin` / `basket_margin` | `GetMargin` / `GetBasketMargin` |
| `get_quote(mode, symbol, exchange)` | `GetQuote(exchange, symbol, mode)` |
| `get_greeks` | `GetGreeks([]GreeksInstrument)` |
| `candle_data` | `GetCandleData` |
| `get_instruments()` | `GetInstruments(InstrumentSegmentAll)` |
| `ArrowStreams(...)` | `client.NewStreams()` |
| `DataMode.*` | `StreamMode*` |
| `MarketTick.is_cas` | `MarketTick.IsCAS` |
