OpenAPI supports trading in the US pre-market and post-market sessions, known as Extended Trading Hours (ETH). Use the new fields and parameters described in this article to:
- see whether a client is allowed to trade in extended hours
- see whether an instrument supports extended hours, and when its sessions run
- show ETH prices, charts and balances
- control whether an order may execute in extended hours
Contents
- Typical integration flow
- 1. Check whether a client can trade in extended hours
- 2. Check whether an instrument supports extended hours
- 3. Get ETH prices
- 4. Place and modify orders for extended hours
- 5. Order behaviour by order type and instrument
- 6. Read the trading session on orders
- 7. Balances
- 8. Positions, net positions and orders: price type
- 9. Event notifications (ENS)
- 10. Charts
- New enum values
- FAQ
Typical integration flow
- Client: call GET /port/v1/clients/me and check AllowedTradingSessions = All.
- Instrument: call GET /ref/v1/instruments/details/{Uic}/{AssetType} and check IsExtendedTradingHoursEnabled = true. Use TradingSessions to see when pre- and post-market run.
- Prices: request FieldGroups=InstrumentPriceDetails and show ExtendedTradingHoursPriceData while the instrument is in pre- or post-market (Quote.MarketState = PreMarket / PostMarket).
- Order: place a limit order with ExecuteAtTradingSession = All. Use POST /trade/v2/orders/precheck first if you show costs or margin impact.
- Follow up: read ExecuteAtTradingSession on GET /port/v1/orders, and ExtendedTradingHoursData on GET /port/v1/balances.
1. Check whether a client can trade in extended hours
Call GET /port/v1/clients/{ClientKey} (or GET /port/v1/clients/me). The response includes AllowedTradingSessions:
Value | Meaning |
|---|---|
All | The client can trade in the regular and extended sessions |
Regular | Default. The client can trade in the regular session only |
Saxo sets this per client. A partner app cannot change it through OpenAPI.
GET /port/v1/clients/me
{
"AllowedTradingSessions": "All",
"ClientKey": "...",
...
}
2. Check whether an instrument supports extended hours
Call GET /ref/v1/instruments/details/{Uic}/{AssetType} (or GET /ref/v1/instruments/details for many instruments).
Field | Type | Description |
|---|---|---|
IsExtendedTradingHoursEnabled | Boolean | true if the instrument can be traded in extended hours |
TradingSessions.Sessions[] | InstrumentSession[] | Session schedule with StartTime, EndTime and State. Extended sessions have State = PreMarket or PostMarket |
Use TradingSessions to show the session times.
3. Get ETH prices
Request FieldGroups=InstrumentPriceDetails on /trade/v1/infoprices or on a /trade/v1/prices / /trade/v1/infoprices subscription. During pre- and post-market the response includes InstrumentPriceDetails.ExtendedTradingHoursPriceData:
Field | Type | Description |
|---|---|---|
Ask | Number | Extended trading hours ask price |
Bid | Number | Extended trading hours bid price |
LastTradedPrice | Number | Last traded price in the pre- or post-market session |
LastTradedPriceTime | UtcDateTime | Time of LastTradedPrice |
Mid | Number | Extended trading hours mid price |
NetChange | Number | Net change in the extended session |
PercentChange | Number | Percent change in the extended session |
Price | Number | For Stock and CfdOnStock, the same as LastTradedPrice |
GET /trade/v1/infoprices/?Uic={Uic}&AssetType=Stock&FieldGroups=Quote,InstrumentPriceDetails
{
"AssetType": "Stock",
"Uic": 211,
"Quote": {
"MarketState": "PreMarket",
...
},
"InstrumentPriceDetails": {
"ExtendedTradingHoursPriceData": {
"Ask": 150.12,
"Bid": 150.05,
"LastTradedPrice": 150.10,
"LastTradedPriceTime": "2026-10-22T12:15:03.000000Z",
"Mid": 150.085,
"NetChange": 0.85,
"PercentChange": 0.57,
"Price": 150.10
},
"IsMarketOpen": false,
...
}
}
4. Place and modify orders for extended hours
Set ExecuteAtTradingSession on POST /trade/v2/orders. The same field is accepted on POST /trade/v2/orders/precheck. It can't be changed after the order is placed: a PATCH /trade/v2/orders that changes it is rejected with ExtendedHoursTradingCannotBeChanged.
Value | Behavior |
|---|---|
All | The order can execute in the regular, pre-market and post-market sessions |
Regular | Default. The order executes in the regular session only, even if the price matches in extended hours |
If you leave out ExecuteAtTradingSession, the order is Regular.
POST /trade/v2/orders
{
"AccountKey": "...",
"Uic": 211,
"AssetType": "Stock",
"BuySell": "Buy",
"Amount": 10,
"OrderType": "Limit",
"OrderPrice": 150.00,
"OrderDuration": { "DurationType": "DayOrder" },
"ExecuteAtTradingSession": "All",
"ManualOrder": true
}
Rules:
- Only limit orders can use ExecuteAtTradingSession = All. Any other order type sent with All (for example market, stop-limit or stop-if-traded) is rejected with OnlyLimitOrderAllowedForExtendedHours.
- Orders without All work in the regular session only. Stop-type orders are never triggered by pre- or post-market prices.
- A related take-profit limit order can also be sent with All. A related stop-loss can't, because it isn't a limit order, so a stop-loss doesn't protect a position during extended hours.
- An order with ExecuteAtTradingSession = All stays eligible in the regular session too. It is not limited to extended hours.
- If the client's AllowedTradingSessions is Regular and you send All, the order is rejected with ClientNotEnabledForExtendedTradingHours.
- If the instrument is not enabled for extended hours (IsExtendedTradingHoursEnabled = false) and you send All, the order is rejected with InstrumentNotSupportedForExtendedHours. Precheck returns the same error.
5. Order behaviour by order type and instrument
How an order behaves depends on the order type, ExecuteAtTradingSession, and whether the instrument is ETH-enabled.
Order | Instrument ETH-enabled? | Behaviour |
|---|---|---|
Limit, All | Yes | Can execute in pre-market, regular and post-market |
Limit, All | No | Rejected with InstrumentNotSupportedForExtendedHours (on placement and on precheck). No order is created |
Limit, Regular (or field omitted) | Any | Works in the regular session only, as today |
Market, stop, stop-limit, trailing stop, All | Any | Rejected with OnlyLimitOrderAllowedForExtendedHours |
Market, stop, stop-limit, trailing stop, Regular (or field omitted) | Any | Works in the regular session only, as today. Stop-type orders are triggered by regular-session prices only |
6. Read the trading session on orders
GET /port/v1/orders (and order subscriptions) return ExecuteAtTradingSession with the value set when the order was placed. It can't be changed afterwards.
7. Balances
For clients enabled for ETH, GET /port/v1/balances (and balance subscriptions) return ExtendedTradingHoursData: balance values calculated with extended trading hours prices.
The fields below are returned inside the ExtendedTradingHoursData object.
Field in ExtendedTradingHoursData | Type | Description |
|---|---|---|
CostToClosePositions | Number | Estimated costs payable if all positions were closed. Negative for costs charged to the account |
InitialMarginUncertainty | Number | Initial margin uncertainty |
MaintenanceMarginUncertainty | Number | Maintenance margin uncertainty |
MarginAvailableForTrading | Number | Remaining collateral available for margin trading |
MarginUsedByCurrentPositions | Number | Maintenance margin used by current positions. Negative for margin charged to available margin |
NonMarginPositionsValue | Number | Sum of MarketValue for all non-margin instruments |
TotalValue | Number | Value of unrealized positions incl. costs, cash balance and transactions not booked |
UncertaintyValue | Number | Extended trading hours uncertainty value. Negative for margin charged to initial margin available |
UnrealizedMarginClosedProfitLoss | Number | P/L on the closed part of positions (intraday netting) |
UnrealizedMarginOpenProfitLoss | Number | P/L on the open part of positions (intraday netting) |
UnrealizedMarginProfitLoss | Number | P/L excl. costs for all margin instruments |
UnrealizedPositionsValue | Number | Unrealized P/L and face value of all positions excl. costs |
UnrealizedPositionsValueExcludingCostToClosePositions | Number | Unrealized P/L and face value of all positions excl. cost to close |
GET /port/v1/balances/me
{
"TotalValue": ...,
"MarginAvailableForTrading": ...,
...
"ExtendedTradingHoursData": {
"TotalValue": ...,
"MarginAvailableForTrading": ...,
"UncertaintyValue": ...,
...
}
}
8. Positions, net positions and orders: price type
During extended hours, CurrentPriceType on positions, net positions and orders can be one of these PriceType values. It shows that the current price and the values derived from it (P/L, market value, exposure) come from the extended session:
Value | Meaning |
|---|---|
EthAsk | Extended trading hours ask price |
EthBid | Extended trading hours bid price |
EthLastTradedPrice | Extended trading hours last traded price |
EthMarkToMarket | Extended trading hours mark-to-market price |
EthNetChange | Extended trading hours net change |
EthPercentChange | Extended trading hours percent change |
9. Event notifications (ENS)
ENS does not yet support the ETH-related order properties. Order events from /ens/v1/activities don't show which trading sessions an order can execute in.
We are planning to launch a new version of ENS soon that will support them. The release will be announced on the Developer Portal.
10. Charts
Add ExtendedHoursEnabled=true to GET /chart/v3/charts or POST /chart/v3/charts/subscriptions to include extended-hours samples for instruments configured for extended hours. The default is false (regular session only). Each sample then has MarketTradingState:
Value | Meaning |
|---|---|
PreMarket | Sample from the pre-market session |
Automated | Sample from the regular session. With ExtendedHoursEnabled=false (or not sent), all samples are Automated |
PostMarket | Sample from the post-market session |
None | No trading state available for the sample |
GET /chart/v3/charts/?Uic={Uic}&AssetType=Stock&Horizon=1&ExtendedHoursEnabled=true
New enum values
Type | New / relevant values | Where |
|---|---|---|
AllowedTradingSessions | All, Regular | Clients |
ExecuteAtTradingSession | All, Regular | Trade orders, portfolio orders |
MarketTradingState | PreMarket, Automated, PostMarket, None | Chart samples |
PriceType | EthAsk, EthBid, EthLastTradedPrice, EthMarkToMarket, EthNetChange, EthPercentChange | CurrentPriceType on orders, positions, net positions |
MarketState | PreMarket, PostMarket | Quote.MarketState on prices |
InstrumentSessionState | PreMarket, PostMarket | Instrument TradingSessions |
FAQ
General
Q1. Do I have to change anything if I don't want to support ETH?
No. All changes are additive, and orders default to Regular. Just make sure your enum parsing accepts the new values listed above.
Q2. How do I know which instruments support ETH?
IsExtendedTradingHoursEnabled = true on GET /ref/v1/instruments/details. Instruments with ETH also have PreMarket / PostMarket sessions in TradingSessions.
Q3. Which order types are supported in ETH?
Limit orders only. Any other order type sent with ExecuteAtTradingSession = All is rejected with OnlyLimitOrderAllowedForExtendedHours. A take-profit can: a related take-profit limit order can be sent with All and then works in extended hours too. A stop-loss can't: it isn't a limit order, so it can't use All, and stop-type orders are only triggered by regular-hours prices. A position is not protected by a stop-loss during pre- or post-market.
Q4. Can I change an existing order from Regular to All, or back?
No. Extended hour trading cannot be changed after the order is placed. You have to cancel and place a new order.
Q5. Does a DayOrder with ExecuteAtTradingSession = All keep working into post-market?
Yes. An unfilled ETH-enabled limit day order carries from the regular session into post-market unchanged.
Q6. What happens to a GTC order with All after post-market ends?
It stays working and can execute again from the next pre-market session. This behaviour may change in the future. Any change will be announced on the Developer Portal.
Q7. What happens to market, stop and stop-limit orders outside regular hours?
Sent with All, they are rejected with OnlyLimitOrderAllowedForExtendedHours. Sent with Regular (or without the field), they work, or trigger, in the regular session only. Pre- and post-market prices never trigger a stop.
Q8. Which balance values should I show during extended hours?
The top-level balance fields are calculated with regular-hours prices. ExtendedTradingHoursData contains the same figures calculated with extended trading hours prices.
- Maintenance margin is always calculated with regular-hours prices.
- Initial margin uses the less favourable of extended-hours and regular-hours prices. An extended-hours loss reduces initial margin available, shown as an uncertainty deduction (UncertaintyValue, InitialMarginUncertainty). An extended-hours gain does not increase it.
Q9. Do ENS order events show the trading session?
Not yet. A new ENS version with this support is planned.