Enums & Types
This page documents all enum values, type constants, and data format conventions used across the TestMax API. Use this as a quick reference when building strategies or integrating with the API.
OrderType
The type of order to place. Used in the type field of Order/place.
| Value | Name | Description | Required price fields |
|---|---|---|---|
1 | Limit | Executes at the specified price or better. Rests in the book until filled or canceled. | limitPrice |
2 | Market | Executes immediately at the current market price. | None |
3 | StopLimit | Becomes a limit order when the stop price is triggered. | stopPrice, limitPrice |
4 | Stop | Becomes a market order when the stop price is triggered. | stopPrice |
When to use each type
- Market (2): Fast entries and exits where execution certainty matters more than price. Used for scalping, emergency flatten, and momentum entries.
- Limit (1): Entries at a specific price or better. Used for pullback entries, take-profit orders, and scaling into positions.
- Stop (4): Breakout entries and stop-loss protection. Triggers when the market trades through the stop price.
- StopLimit (3): Combines a stop trigger with a limit price to avoid slippage on breakout entries. The limit price controls the worst acceptable fill price.
OrderSide
The direction of the order. Used in the side field of Order/place.
| Value | Name | Description |
|---|---|---|
0 | Buy | Buy to open a long position or close a short position |
1 | Sell | Sell to open a short position or close a long position |
OrderStatus
The current state of an order. Returned in the status field of Order/search and Order/searchOpen.
| Value | Name | Description |
|---|---|---|
1 | Partial | Order is partially filled — some contracts executed, remaining are still working |
2 | Filled | Order is completely filled — all contracts executed |
3 | Canceled | Order was canceled before being fully filled |
6 | Pending | Order is active and waiting to be filled (limit/stop orders resting in the book) |
Status transitions
Pending (6) → Partial (1) → Filled (2)Pending (6) → Filled (2) (fully filled immediately)Pending (6) → Canceled (3) (manually canceled)Partial (1) → Canceled (3) (canceled with partial fill)PositionType
The direction of an open position. Returned in the type field of Position/searchOpen.
| Value | Name | Description |
|---|---|---|
1 | Long | Holding a long position (bought contracts, profit when price rises) |
2 | Short | Holding a short position (sold contracts, profit when price falls) |
Usage in strategy code
positions = get_positions(ACCOUNT_ID)for pos in positions: if pos["type"] == 1: print(f"LONG {pos['size']} @ {pos['averagePrice']}") elif pos["type"] == 2: print(f"SHORT {pos['size']} @ {pos['averagePrice']}")AggregateBarUnit
The time unit for bar aggregation. Used in the unit field of History/retrieveBars.
| Value | Name | Description |
|---|---|---|
1 | Second | Bars aggregated by seconds |
2 | Minute | Bars aggregated by minutes |
3 | Hour | Bars aggregated by hours |
4 | Day | Bars aggregated by days |
Combine unit with unitNumber to define the bar timeframe:
| Timeframe | unit | unitNumber |
|---|---|---|
| 1-second | 1 | 1 |
| 30-second | 1 | 30 |
| 1-minute | 2 | 1 |
| 5-minute | 2 | 5 |
| 15-minute | 2 | 15 |
| 30-minute | 2 | 30 |
| 1-hour | 3 | 1 |
| 4-hour | 3 | 4 |
| Daily | 4 | 1 |
Contract ID format
Contract identifiers follow the gateway-schema convention:
CON.F.US.{symbol}.{monthYear}| Component | Description | Example |
|---|---|---|
CON | Fixed prefix (contract) | CON |
F | Asset class (futures) | F |
US | Exchange/region | US |
{symbol} | Internal instrument symbol | ENQ, EP, GC |
{monthYear} | Month code + 2-digit year | H25 (March 2025) |
The simulator maps symbols as follows: NQ→ENQ, ES→EP, MNQ→MENQ, MES→MEP, MCL→MCL; CL, GC, YM, and RTY keep their own symbols. Generated IDs always carry the current front-month code (e.g. .N26 in July 2026), and the month/year segment is ignored when the simulator resolves an ID you send.
Full examples
| Contract ID | Instrument | Expiry |
|---|---|---|
CON.F.US.ENQ.H25 | Nasdaq 100 E-mini | March 2025 |
CON.F.US.EP.H25 | S&P 500 E-mini | March 2025 |
CON.F.US.GC.J25 | Gold Futures | April 2025 |
CON.F.US.CL.F25 | Crude Oil Futures | January 2025 |
Month codes
| Code | Month | Code | Month |
|---|---|---|---|
F | January | N | July |
G | February | Q | August |
H | March | U | September |
J | April | V | October |
K | May | X | November |
M | June | Z | December |
Standard response format
Every API endpoint returns a response with these three fields:
{ "success": true, "errorCode": 0, "errorMessage": null}| Field | Type | Description |
|---|---|---|
success | boolean | true if the request succeeded |
errorCode | number | 0 for success, non-zero for errors |
errorMessage | string or null | Human-readable error message, or null on success |
Additional data fields are included alongside these fields depending on the endpoint. For example:
{ "success": true, "errorCode": 0, "errorMessage": null, "accounts": [...]}Error codes
Error codes are contextual — the same number can mean different things on different endpoints, so always read errorMessage. Rough taxonomy:
| Code | Typical meaning |
|---|---|
0 | Success |
1 | Not found (account, contract) or invalid session on Auth/validate |
2 | Invalid state or parameter (order/position not found, no active replay session, missing startDate, invalid unit or time range) |
3 | Auth failure (invalid credentials/token), unsupported operation (Order/modify), or invalid amount/unit number |
4 | Account violation (terminal challenge), withdrawal not eligible, or invalid limit |
5–7 | Endpoint-specific: invalid close size, engine rejections, invalid order size/type |
9 | Pro subscription required |
99 | Internal server error |
429 | Rate limited — arrives as a real HTTP 429 with a Retry-After header |
The full per-endpoint list is in Error Codes. Note that simulator errors (other than 429) are returned with HTTP 200 and success: false.
Bar data format
OHLCV bars returned by Replay/step and History/retrieveBars use this format:
{ "t": "2025-01-15T14:30:00Z", "o": 21500.25, "h": 21505.50, "l": 21498.75, "c": 21503.00, "v": 150}| Field | Type | Description |
|---|---|---|
t | string | ISO 8601 UTC timestamp for the bar’s open time |
o | number | Open price (first traded price in the bar period) |
h | number | High price (highest traded price in the bar period) |
l | number | Low price (lowest traded price in the bar period) |
c | number | Close price (last traded price in the bar period) |
v | number | Volume (total contracts traded in the bar period) |
Timeframe strings
Timeframe strings are used in Replay/start and Playground API endpoints. A
timeframe is a positive count followed by a unit letter:
^([1-9]\d{0,4})(s|m|h|d|w|M|y)$| Unit | Meaning | Bucketing |
|---|---|---|
s | seconds | Fixed width, bucketed on the epoch grid |
m | minutes | Fixed width, bucketed on the epoch grid |
h | hours | Fixed width, bucketed on the epoch grid |
d | days | Fixed width, bucketed on the epoch grid |
w | weeks | Calendar, ISO Monday weeks in UTC |
M | months | Calendar, UTC calendar months |
y | years | Calendar, UTC calendar years |
The grammar is the whole validation surface — leading zeros ("01m"), empty
counts ("m"), unknown units ("1D", "5x") and anything else that fails the
pattern is rejected with an Invalid timeframe error.
Free presets
These 12 timeframes are available on every plan:
| String | Description |
|---|---|
"1s" | 1-second bars |
"5s" | 5-second bars |
"10s" | 10-second bars |
"15s" | 15-second bars |
"30s" | 30-second bars |
"1m" | 1-minute bars |
"5m" | 5-minute bars |
"15m" | 15-minute bars |
"30m" | 30-minute bars |
"1h" | 1-hour bars |
"4h" | 4-hour bars |
"1d" | Daily bars |
Pro timeframes
Every other value the grammar accepts — "7m", "90m", "2h", "3d" — plus
the calendar presets "1w", "1M", "3M" and "1y" is a custom timeframe.
On the platform surfaces — the replay WebSocket and the /api/data candle and
volume-profile endpoints — a custom timeframe requires a Pro subscription:
requests for one from a free account are refused with
Timeframe "<label>" requires a Pro subscription. Custom timeframes on those
surfaces are also behind a platform feature switch, and while it is off every
non-preset value is refused with Custom timeframes are currently disabled,
whatever the plan. The Playground endpoints require Pro before they look at the
timeframe at all, so only the switch refusal reaches them.
The Simulator API applies neither check — a Pro plan is already required
to hold a simulator token — so Replay/start and the bar endpoints validate
only the grammar and the per-instrument availability rule below.
Admin and research endpoints accept any parseable timeframe without the subscription check.
Canonicalization
A timeframe is promoted to the largest unit that divides it evenly before it is
used, echoed or cached, so "60m" and "1h" are the same request:
| Sent | Canonical |
|---|---|
"120s" | "2m" |
"60m" | "1h" |
"1440m" | "1d" |
"48h" | "2d" |
"90m" | "90m" |
"12M" | "1y" |
"24M" | "2y" |
Promotion never crosses the fixed/calendar boundary: "7d" is not "1w",
"30d" is not "1M", "365d" is not "1y". All 12 free presets are already
canonical. Responses echo the canonical label, so read the timeframe back from
the response rather than assuming the string you sent.
Bounds
Checked on the canonical form, so "24M" is accepted as "2y" while "13M" is
rejected:
| Family | Maximum |
|---|---|
s / m / h / d | 30 days |
w | 52 |
M | 12 |
y | 5 |
Availability per instrument
Bars are aggregated up from each instrument’s stored resolution, so a timeframe is only available when it lines up with that resolution:
- Fixed (
s/m/h/d): the timeframe in seconds must be an exact multiple of the stored resolution in seconds. - Calendar (
w/M/y): the stored resolution must divide a whole day (86400 seconds) evenly.
Gold (GC) is stored at 10-second resolution, for example, so "30s" is
available on it but "15s" is not. A timeframe that does not line up is
rejected rather than silently rounded.
Quick reference card
| Enum | Values |
|---|---|
| OrderType | 1=Limit, 2=Market, 3=StopLimit, 4=Stop |
| OrderSide | 0=Buy, 1=Sell |
| OrderStatus | 1=Partial, 2=Filled, 3=Canceled, 6=Pending |
| PositionType | 1=Long, 2=Short |
| AggregateBarUnit | 1=Second, 2=Minute, 3=Hour, 4=Day |
Copy-paste this into the top of your strategy for quick reference:
# === Enum Constants ===# OrderTypeLIMIT, MARKET, STOP_LIMIT, STOP = 1, 2, 3, 4
# OrderSideBUY, SELL = 0, 1
# OrderStatusPARTIAL, FILLED, CANCELED, PENDING = 1, 2, 3, 6
# PositionTypeLONG, SHORT = 1, 2
# AggregateBarUnitSECOND, MINUTE, HOUR, DAY = 1, 2, 3, 4