Orders Endpoint¶
OANDA Reference: Order Endpoints
Order creation, modification, and management.
The examples below illustrate calls and response access. Helpers run only when called. Examples that create, update, cancel or close resources change account state; use a dedicated practice account and inspect each response. Local validation and HTTPX transport exceptions can occur in addition to the API errors listed.
post_order¶
Create a new order using any order request type.
OANDA Endpoint: POST /v3/accounts/{accountID}/orders
import asyncio
from decimal import Decimal
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.endpoints.orders import OrderResponse
from fivetwenty.models import InstrumentName, MarketOrderRequest
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Create a market order using the generic post_order method
order_response: OrderResponse = await client.orders.post_order(
account_id=client.account_id,
order_request=MarketOrderRequest(
instrument=InstrumentName.EUR_USD,
units=Decimal(1000),
),
client_request_id="my-order-123",
)
print(f"Last Transaction ID: {order_response['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Create Order
🔗 Source: orders.post_order
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Target account identifier |
order_request |
OrderRequest | dict[str, Any] | ✅ | Order specification |
* |
Keyword-only parameters below | ||
timeout |
float | None | âž– | Request timeout override |
client_request_id |
str | None | âž– | Client-provided request ID for debugging and correlation |
Returns: OrderResponse TypedDict containing:
lastTransactionID: Transaction ID stringorderCreateTransaction: Transaction details for the created orderorderFillTransaction: Transaction details if order was filled (optional)relatedTransactionIDs: List of related transaction IDs
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after) -
400: Invalid order parameters (inspect
e.codeande.details) -
ValueError- If order_request is invalid or missing required fields
post_market_order¶
Create a market order (convenience method for immediate execution at current market price).
OANDA Endpoint: POST /v3/accounts/{accountID}/orders
import asyncio
from decimal import Decimal
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.endpoints.orders import OrderResponse
from fivetwenty.models import InstrumentName
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Create a market order with take profit and stop loss
order: OrderResponse = await client.orders.post_market_order(
account_id=client.account_id,
instrument=InstrumentName.EUR_USD,
units=1000,
take_profit=Decimal("1.1500"),
stop_loss=Decimal("1.1200"),
)
print(f"Last Transaction ID: {order['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Create Order
🔗 Source: orders.post_market_order
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Account to create order for |
instrument |
InstrumentName | ✅ | Instrument to trade |
units |
int | Decimal | str | ✅ | Number of units (positive = buy, negative = sell) |
* |
Keyword-only parameters below | ||
take_profit |
Decimal | None | âž– | Take profit price (creates takeProfitOnFill order) |
stop_loss |
Decimal | None | âž– | Stop loss price (creates stopLossOnFill order) |
timeout |
float | None | âž– | Request timeout override |
client_request_id |
str | None | âž– | Client-provided request ID for debugging and correlation |
Returns: OrderResponse TypedDict containing:
lastTransactionID: Transaction ID stringorderCreateTransaction: Transaction details for the created orderorderFillTransaction: Transaction details if order was filled (optional)relatedTransactionIDs: List of related transaction IDs
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after) - 400: Invalid parameters or insufficient margin (inspect
e.codeande.details)
post_limit_order¶
Create a limit order (convenience method for order execution at specified price or better).
OANDA Endpoint: POST /v3/accounts/{accountID}/orders
import asyncio
from decimal import Decimal
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.endpoints.orders import OrderResponse
from fivetwenty.models import InstrumentName
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Create a limit order to buy EUR/USD at 1.1350
order: OrderResponse = await client.orders.post_limit_order(
account_id=client.account_id,
instrument=InstrumentName.EUR_USD,
units=1000,
price=Decimal("1.1350"),
)
print(f"Last Transaction ID: {order['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Create Order
🔗 Source: orders.post_limit_order
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Account to create order for |
instrument |
InstrumentName | ✅ | Instrument to trade |
units |
int | Decimal | str | ✅ | Number of units (positive = buy, negative = sell) |
price |
Decimal | ✅ | Limit price |
* |
Keyword-only parameters below | ||
time_in_force |
str | âž– | Order time in force (GTC, GTD, GFD, FOK, IOC) - default: "GTC" |
take_profit |
Decimal | None | âž– | Take profit price (creates takeProfitOnFill order) |
stop_loss |
Decimal | None | âž– | Stop loss price (creates stopLossOnFill order) |
timeout |
float | None | âž– | Request timeout override |
client_request_id |
str | None | âž– | Client-provided request ID for debugging and correlation |
Returns: OrderResponse TypedDict containing:
lastTransactionID: Transaction ID stringorderCreateTransaction: Transaction details for the created orderrelatedTransactionIDs: List of related transaction IDs
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after) - 400: Invalid parameters (inspect
e.codeande.details)
post_stop_order¶
Create a stop order (convenience method for order execution when market reaches trigger price).
OANDA Endpoint: POST /v3/accounts/{accountID}/orders
import asyncio
from decimal import Decimal
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.endpoints.orders import OrderResponse
from fivetwenty.models import InstrumentName
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Create a stop order triggered when EUR/USD reaches 1.1200
order: OrderResponse = await client.orders.post_stop_order(
account_id=client.account_id,
instrument=InstrumentName.EUR_USD,
units=1000,
price=Decimal("1.1200"),
)
print(f"Last Transaction ID: {order['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Create Order
🔗 Source: orders.post_stop_order
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Account to create order for |
instrument |
InstrumentName | ✅ | Instrument to trade |
units |
int | Decimal | str | ✅ | Number of units (positive = buy, negative = sell) |
price |
Decimal | ✅ | Stop trigger price |
* |
Keyword-only parameters below | ||
price_bound |
Decimal | None | âž– | Maximum slippage price after trigger |
time_in_force |
str | âž– | Order time in force (GTC, GTD, GFD, FOK, IOC) - default: "GTC" |
take_profit |
Decimal | None | âž– | Take profit price (creates takeProfitOnFill order) |
stop_loss |
Decimal | None | âž– | Stop loss price (creates stopLossOnFill order) |
timeout |
float | None | âž– | Request timeout override |
client_request_id |
str | None | âž– | Client-provided request ID for debugging and correlation |
Returns: OrderResponse TypedDict containing:
lastTransactionID: Transaction ID stringorderCreateTransaction: Transaction details for the created orderrelatedTransactionIDs: List of related transaction IDs
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after) - 400: Invalid parameters (inspect
e.codeande.details)
post_market_if_touched_order¶
Create a market-if-touched order (convenience method for market order execution when price reaches trigger level).
OANDA Endpoint: POST /v3/accounts/{accountID}/orders
import asyncio
from decimal import Decimal
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.endpoints.orders import OrderResponse
from fivetwenty.models import InstrumentName
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Create market-if-touched order triggered at 1.1400
order: OrderResponse = await client.orders.post_market_if_touched_order(
account_id=client.account_id,
instrument=InstrumentName.EUR_USD,
units=1000,
price=Decimal("1.1400"),
)
print(f"Last Transaction ID: {order['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Create Order
🔗 Source: orders.post_market_if_touched_order
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Account to create order for |
instrument |
InstrumentName | ✅ | Instrument to trade |
units |
int | Decimal | str | ✅ | Number of units (positive = buy, negative = sell) |
price |
Decimal | ✅ | Trigger price |
* |
Keyword-only parameters below | ||
price_bound |
Decimal | None | âž– | Maximum slippage price after trigger |
time_in_force |
str | âž– | Order time in force (GTC, GTD, GFD, FOK, IOC) - default: "GTC" |
take_profit |
Decimal | None | âž– | Take profit price (creates takeProfitOnFill order) |
stop_loss |
Decimal | None | âž– | Stop loss price (creates stopLossOnFill order) |
timeout |
float | None | âž– | Request timeout override |
client_request_id |
str | None | âž– | Client-provided request ID for debugging and correlation |
Returns: OrderResponse TypedDict containing:
lastTransactionID: Transaction ID stringorderCreateTransaction: Transaction details for the created orderrelatedTransactionIDs: List of related transaction IDs
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after) - 400: Invalid parameters (inspect
e.codeande.details)
get_orders¶
Get a list of orders for an account with optional filtering.
OANDA Endpoint: GET /v3/accounts/{accountID}/orders
Beta Compatibility
get_orders() returns OANDA's response envelope, not a bare list. Code written against older beta versions should change from orders = await client.orders.get_orders(account_id) to:
result = await client.orders.get_orders(account_id)
orders = result["orders"]
last_transaction_id = result["lastTransactionID"]
The synchronous Client uses the same response shape.
import asyncio
from dotenv import load_dotenv
from fivetwenty import AsyncClient
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Get pending orders for the account
result = await client.orders.get_orders(
account_id=client.account_id,
state="PENDING",
count=50,
)
orders = result["orders"]
print(f"Found {len(orders)} orders")
print(f"Last Transaction ID: {result['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Get Orders
🔗 Source: orders.get_orders
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Target account identifier |
* |
Keyword-only parameters below | ||
ids |
list[str] | None | âž– | List of specific order IDs to retrieve |
state |
OrderStateFilter | str | âž– | Filter by order state - default: "PENDING" |
instrument |
str | None | âž– | Filter by instrument |
count |
int | âž– | Maximum number of orders to return - default: 50, max: 500 |
before_id |
str | None | âž– | Maximum order ID to return |
Returns: GetOrdersResponse TypedDict containing:
orders: List of Order modelslastTransactionID: Transaction ID string
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after) - 400: Invalid filter parameters (inspect
e.codeande.details)
ValueError - If count is outside 1-500
get_order¶
Get details for a specific order by order ID or specifier.
OANDA Endpoint: GET /v3/accounts/{accountID}/orders/{orderSpecifier}
import asyncio
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.endpoints.orders import GetOrderResponse
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Get details for a specific order
# Replace with your actual order ID
result: GetOrderResponse = await client.orders.get_order(
account_id=client.account_id,
order_specifier="12345",
)
order = result["order"]
print(f"Order type: {order.type}")
print(f"Last Transaction ID: {result['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Get Order
🔗 Source: orders.get_order
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Target account identifier |
order_specifier |
str | ✅ | Order identifier or specifier |
Returns: GetOrderResponse TypedDict containing:
order: Order model with full order detailslastTransactionID: Transaction ID string
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Order or account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after)
cancel_order¶
Cancel a pending order by order ID or specifier.
OANDA Endpoint: PUT /v3/accounts/{accountID}/orders/{orderSpecifier}/cancel
import asyncio
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.endpoints.orders import CancelOrderResponse
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Cancel a pending order
# Replace with your actual order ID
result: CancelOrderResponse = await client.orders.cancel_order(
account_id=client.account_id,
order_specifier="12345",
)
print(f"Last Transaction ID: {result['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Cancel Order
🔗 Source: orders.cancel_order
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Target account identifier |
order_specifier |
str | ✅ | Order identifier to cancel |
* |
Keyword-only parameters below | ||
timeout |
float | None | âž– | Request timeout override |
client_request_id |
str | None | âž– | Client-provided request ID for debugging and correlation |
Returns: CancelOrderResponse TypedDict containing:
orderCancelTransaction: Transaction details for the cancellationrelatedTransactionIDs: List of related transaction IDslastTransactionID: Transaction ID string
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Order or account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after) - 400: Order not cancellable (already filled or cancelled) (inspect
e.codeande.details)
get_pending_orders¶
Get all pending orders for an account.
OANDA Endpoint: GET /v3/accounts/{accountID}/pendingOrders
import asyncio
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.endpoints.orders import PendingOrdersResponse
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Get all pending orders
result: PendingOrdersResponse = await client.orders.get_pending_orders(
account_id=client.account_id
)
pending_orders = result["orders"]
print(f"Found {len(pending_orders)} pending orders")
print(f"Last Transaction ID: {result['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Get Pending Orders
🔗 Source: orders.get_pending_orders
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Target account identifier |
Returns: PendingOrdersResponse TypedDict containing:
orders: List of pending Order modelslastTransactionID: Transaction ID string
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after)
put_order¶
Replace an existing order by cancelling it and creating a new order with updated parameters.
OANDA Endpoint: PUT /v3/accounts/{accountID}/orders/{orderSpecifier}
import asyncio
from decimal import Decimal
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.endpoints.orders import ReplaceOrderResponse
from fivetwenty.models import InstrumentName, LimitOrderRequest
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Replace an existing limit order with new price
# Replace with your actual order ID
result: ReplaceOrderResponse = await client.orders.put_order(
account_id=client.account_id,
order_specifier="12345",
order_request=LimitOrderRequest(
instrument=InstrumentName.EUR_USD,
units=Decimal("1000"),
price=Decimal("1.1400"),
),
)
print(f"Last Transaction ID: {result['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Replace Order
🔗 Source: orders.put_order
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Target account identifier |
order_specifier |
str | ✅ | Order identifier to replace |
order_request |
OrderRequest | dict[str, Any] | ✅ | New order specification |
* |
Keyword-only parameters below | ||
client_request_id |
str | None | âž– | Client-provided request ID for debugging and correlation |
Returns: ReplaceOrderResponse TypedDict containing:
orderCancelTransaction: Transaction details for cancelled order (optional)orderCreateTransaction: Transaction details for new orderorderFillTransaction: Transaction details if new order filled (optional)relatedTransactionIDs: List of related transaction IDslastTransactionID: Transaction ID string
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Order or account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after) - 400: Invalid order specification or replacement failed (inspect
e.codeande.details)
put_order_client_extensions¶
Modify client extensions for an existing order without replacing the order.
OANDA Endpoint: PUT /v3/accounts/{accountID}/orders/{orderSpecifier}/clientExtensions
import asyncio
from dotenv import load_dotenv
from fivetwenty import AsyncClient
from fivetwenty.endpoints.orders import OrderClientExtensionsResponse
from fivetwenty.models import ClientExtensions
load_dotenv()
async def main() -> None:
async with AsyncClient() as client:
# Update client extensions for an order
# Replace with your actual order ID
result: OrderClientExtensionsResponse = (
await client.orders.put_order_client_extensions(
account_id=client.account_id,
order_specifier="12345",
client_extensions=ClientExtensions(comment="Updated order"),
)
)
print(f"Last Transaction ID: {result['lastTransactionID']}")
if __name__ == "__main__":
asyncio.run(main())
🔗 OANDA Documentation: Update Order Client Extensions
🔗 Source: orders.put_order_client_extensions
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
account_id |
AccountID | ✅ | Target account identifier |
order_specifier |
str | ✅ | Order identifier to modify |
* |
Keyword-only parameters below | ||
client_extensions |
ClientExtensions | None | âž– | New order client extensions |
trade_client_extensions |
ClientExtensions | None | âž– | New trade client extensions |
Returns: OrderClientExtensionsResponse TypedDict containing:
orderClientExtensionsModifyTransaction: Transaction details for the modificationrelatedTransactionIDs: List of related transaction IDslastTransactionID: Transaction ID string
Raises:
FiveTwentyError - API errors:
- 401/403: Authentication failed (check
e.is_authentication_error) - 404: Order or account not found (check
e.is_not_found) - 429: Rate limit exceeded (check
e.is_rate_limited, usee.retry_after) - 400: Invalid client extensions or modification failed (inspect
e.codeande.details)