Broker API
OANDA trading API (v20)
v20 REST API with HTTP streaming for prices and transactions.
Risk warning: CFDs and spread bets are complex instruments and come with a high risk of losing money rapidly due to leverage. You can lose money on these products, and each provider publishes its own loss figure under FCA rules. You should consider whether you understand how they work and whether you can afford to take the high risk of losing your money. Automated and API trading can amplify losses through bugs, connectivity failures and runaway orders.
OANDA API rate limits and allowances
One record per limit. The scope is part of the limit: a figure without its scope is not a figure you can pace against.
| Limit | Value | Scope | Source |
|---|---|---|---|
| Headline limit | 120/s per IP address, HTTP 429 above it | ip | developer.oanda.comchecked |
OANDA API rate limits in full, with pacing advice and the related error codes.
Access, authentication and streaming
API types listed in the record: REST (v20), HTTP streaming.
- How you get a key
Account Management Portal > My Services > Manage API Access, accept licence, generate personal access token.
OANDA v20 Introductionchecked
- Who can use it
Needs a v20 account; available in all divisions except OANDA Global Markets and OANDA TMS Brokers S.A.
OANDA v20 Introductionchecked
- Demo
Yes: fxTrade Practice environment with its own token.
OANDA Development Guidechecked
- Authentication
Bearer personal access token, generated in the Account Management Portal after accepting the API licence.
- Streaming
HTTP chunked transfer encoding carrying JSON objects, not WebSocket. The development guide states at most 20 active streams, with requests above that rejected, and no more than 2 new connections a second. The best practices page advises no more than 100 requests a second on an established connection. Sources: https://developer.oanda.com/rest-live-v20/development-guide/ and https://developer.oanda.com/rest-live-v20/best-practices/, both read 23 September 2026, development guide re-read 24 September 2026.
OANDA Development Guidechecked
- History depth
Historical pricing back to 2005, on the introduction page. Candles: at most 5,000 per request, 500 by default, on the pricing endpoints page. Transactions: at most 365 days per request, in pages of up to 1,000.
OANDA v20: Introductionchecked OANDA v20: Pricing endpointschecked OANDA v20: Transaction endpointschecked
- Rate limits, as worded
OANDA publishes two figures, on two pages, in two units. The enforced one is on the development guide. The development guide states 120 requests a second per IP address, with HTTP 429 above that, and at most 20 active streams. The best practices page advises no more than 100 requests a second on an established connection and no more than 2 new connections a second. A request rate and an established connection rate are different units, so neither figure replaces or contradicts the other. Our inference and not OANDA's word: hold to the lower request rate and open no more than 2 new connections a second. Sources: https://developer.oanda.com/rest-live-v20/development-guide/ and https://developer.oanda.com/rest-live-v20/best-practices/, both read 23 September 2026, development guide re-read 24 September 2026.
OANDA v20 best practiceschecked
OANDA API endpoints
33 documented endpoints. Grouped by what they do
- GET/v3/accountsList every account your token can access. Start here to find your accountID.
- GET/v3/accounts/{accountID}Full account state: balance, NAV, margin, plus open trades, positions and pending orders.
- GET/v3/accounts/{accountID}/candles/latestThe candle still forming and the most recently completed ones, for several combinations of instrument, granularity and price component in one call.
- GET/v3/accounts/{accountID}/changesPoll an account for its current state and for what has changed since a transaction you name. This is the documented way to keep a local copy of an account up to date.
- PATCH/v3/accounts/{accountID}/configurationChange the parts of an account its owner may set: the alias and the margin rate.
- GET/v3/accounts/{accountID}/instrumentsInstruments this account can trade, with precision, pip location and margin rate.
- GET/v3/accounts/{accountID}/instruments/{instrument}/candlesHistorical candlesticks for one instrument, requested through an account. Up to 5000 candles per request.
- GET/v3/accounts/{accountID}/openPositionsPositions with open trades, netted per instrument with long and short sides.
- GET/v3/accounts/{accountID}/openTradesAll open trades on the account.
- GET/v3/accounts/{accountID}/ordersList orders, pending by default. Filter by ids, state or instrument; paginate with beforeID.
- POST/v3/accounts/{accountID}/ordersCreate an order. Market, limit, stop, market if touched and dependent orders all go through this one endpoint. Returns 201.
- GET/v3/accounts/{accountID}/orders/{orderSpecifier}The details of one order on the account, whatever its state.
- PUT/v3/accounts/{accountID}/orders/{orderSpecifier}Replace a pending order: the old order is cancelled and a new one created from the specification you send, in a single call. Returns 201.
- PUT/v3/accounts/{accountID}/orders/{orderSpecifier}/cancelCancel a pending order by ID or by your client ID prefixed with @.
- PUT/v3/accounts/{accountID}/orders/{orderSpecifier}/clientExtensionsUpdate the client extensions on an order: your own ID, tag and comment, for the order and for the trade it will open. OANDA says not to use them on an account linked to MT4.
- GET/v3/accounts/{accountID}/pendingOrdersEvery pending order on the account, in one call with no filters.
- GET/v3/accounts/{accountID}/positionsEvery position the account has ever held, one per instrument, including those now flat. For open positions only there is a separate call.
- GET/v3/accounts/{accountID}/positions/{instrument}The position in one instrument on the account, whether it is open or not.
- PUT/v3/accounts/{accountID}/positions/{instrument}/closeClose out the long side, the short side or both for one instrument.
- GET/v3/accounts/{accountID}/pricingCurrent bid and ask for a list of instruments. A snapshot, not a stream.
- GET/v3/accounts/{accountID}/pricing/streamStreaming prices over one long lived HTTP connection. Newline delimited JSON: PRICE and HEARTBEAT objects.
- GET/v3/accounts/{accountID}/summaryAccount summary without the trade, position and order lists. Cheap balance and margin check.
- GET/v3/accounts/{accountID}/tradesTrades on the account, filtered by state, instrument or ID. Open trades are returned unless you ask for another state.
- GET/v3/accounts/{accountID}/trades/{tradeSpecifier}The details of one trade on the account.
- PUT/v3/accounts/{accountID}/trades/{tradeSpecifier}/clientExtensionsUpdate the client extensions on a trade: your own ID, tag and comment. OANDA says not to use them on an account linked to MT4.
- PUT/v3/accounts/{accountID}/trades/{tradeSpecifier}/closeClose a trade in full or in part.
- PUT/v3/accounts/{accountID}/trades/{tradeSpecifier}/ordersCreate, replace or cancel the orders that hang off a trade: take profit, stop loss, trailing stop loss and guaranteed stop loss. This is how a stop or limit is moved on an open trade.
- GET/v3/accounts/{accountID}/transactionsTransaction history for a time range, returned as page URLs to fetch next.
- GET/v3/accounts/{accountID}/transactions/{transactionID}The details of one transaction on the account, by its ID.
- GET/v3/accounts/{accountID}/transactions/idrangeThe transactions between two transaction IDs, both included, returned in full.
- GET/v3/accounts/{accountID}/transactions/sinceidEvery transaction newer than the one you name, returned in full. Useful for catching up after a gap.
- GET/v3/accounts/{accountID}/transactions/streamStreaming account activity (fills, cancels, funding) from the moment you connect. Newline delimited JSON.
- GET/v3/instruments/{instrument}/candlesHistorical candlesticks (OHLC) for one instrument. Up to 5000 candles per request.
OANDA API error codes
242 decoded error codes. All OANDA errors
Account not tradableThe token is valid but the account cannot trade.ACCOUNT_The account is locked for configuration changes.CONFIGURATION_ LOCKED ACCOUNT_The account is locked for deposits.DEPOSIT_ LOCKED ACCOUNT_The account is locked.LOCKED ACCOUNT_The order was to be filled, but the account is configured not to allow new positions to be created.NEW_ POSITIONS_ LOCKED ACCOUNT_The account is not active.NOT_ ACTIVE ACCOUNT_The account is locked for order cancellation.ORDER_ CANCEL_ LOCKED ACCOUNT_The account is locked for order creation.ORDER_ CREATION_ LOCKED ACCOUNT_The order could not be filled because the account is locked for filling orders.ORDER_ FILL_ LOCKED ACCOUNT_Filling the order would have taken the account past the maximum position value it is allowed, so the order was cancelled.POSITION_ VALUE_ LIMIT_ EXCEEDED ACCOUNT_The account is locked for withdrawals.WITHDRAWAL_ LOCKED ADMIN_No configuration parameters were provided.CONFIGURE_ DATA_ MISSING ALIAS_The account alias string provided is not valid.INVALID AMOUNT_Funding is not possible because the transfer amount requested is not valid.INVALID AMOUNT_The funding amount was not specified.MISSING BOUNDS_Filling the order would have broken the order's price bound.VIOLATION CLIENT_No configuration parameters were provided.CONFIGURE_ DATA_ MISSING CLIENT_Neither order client extensions nor trade on fill client extensions were provided for the modification.EXTENSIONS_ DATA_ MISSING CLIENT_The client order comment specified is not valid.ORDER_ COMMENT_ INVALID CLIENT_The client order ID is already assigned to another pending order.ORDER_ ID_ ALREADY_ EXISTS CLIENT_The client order ID specified is not valid.ORDER_ ID_ INVALID CLIENT_The client order tag specified is not valid.ORDER_ TAG_ INVALID CLIENT_The client trade comment is not valid.TRADE_ COMMENT_ INVALID CLIENT_The client trade ID is already assigned to another open trade.TRADE_ ID_ ALREADY_ EXISTS CLIENT_The client trade ID specified is not valid.TRADE_ ID_ INVALID CLIENT_The client trade tag specified is not valid.TRADE_ TAG_ INVALID CLOSE_The request to close a trade partially did not give the number of units to close.TRADE_ PARTIAL_ UNITS_ MISSING CLOSE_The request to close a trade does not say whether the close is full or partial.TRADE_ TYPE_ MISSING CLOSE_The request to close part of a trade names more units than the trade currently has.TRADE_ UNITS_ EXCEED_ TRADE_ SIZE CLOSEOUT_The position asked to be closed out does not exist.POSITION_ DOESNT_ EXIST CLOSEOUT_The request to close out a position was specified incompletely.POSITION_ INCOMPLETE_ SPECIFICATION CLOSEOUT_The request to close out part of a position did not give the number of units to close.POSITION_ PARTIAL_ UNITS_ MISSING CLOSEOUT_The request to close out a position could not be fully satisfied.POSITION_ REJECT CLOSEOUT_A partial position closeout names more units than the position currently has.POSITION_ UNITS_ EXCEED_ POSITION_ SIZE FIFO_Filling the order would have resulted in a FIFO violation.VIOLATION FIFO_Filling the order would have reduced an existing trade so that the reduced trade breaks the FIFO violation safeguard constraints.VIOLATION_ SAFEGUARD_ PARTIAL_ CLOSE_ VIOLATION FIFO_Filling the order would have created a trade that breaks the FIFO violation safeguard constraints.VIOLATION_ SAFEGUARD_ VIOLATION FUNDING_The funding reason was not specified.REASON_ MISSING GUARANTEED_Filling the order would create a guaranteed stop loss order on a short trade, which would be long, while the ask side is halted.STOP_ LOSS_ ON_ FILL_ ASK_ HALTED GUARANTEED_Filling the order would create a guaranteed stop loss order on a long trade, which would be short, while the bid side is halted.STOP_ LOSS_ ON_ FILL_ BID_ HALTED GUARANTEED_The client order comment on the guaranteed stop loss on fill is not valid.STOP_ LOSS_ ON_ FILL_ CLIENT_ ORDER_ COMMENT_ INVALID GUARANTEED_Filling the order would have created a guaranteed stop loss order with a client order ID that is already in use.STOP_ LOSS_ ON_ FILL_ CLIENT_ ORDER_ ID_ ALREADY_ EXISTS GUARANTEED_The client order ID on the guaranteed stop loss on fill is not valid.STOP_ LOSS_ ON_ FILL_ CLIENT_ ORDER_ ID_ INVALID GUARANTEED_The client order tag on the guaranteed stop loss on fill is not valid.STOP_ LOSS_ ON_ FILL_ CLIENT_ ORDER_ TAG_ INVALID GUARANTEED_The guaranteed stop loss on fill distance is not valid.STOP_ LOSS_ ON_ FILL_ DISTANCE_ INVALID GUARANTEED_The guaranteed stop loss on fill distance carries more precision than the instrument allows.STOP_ LOSS_ ON_ FILL_ DISTANCE_ PRECISION_ EXCEEDED GUARANTEED_The guaranteed stop loss on fill gives a GTD timestamp that is in the past.STOP_ LOSS_ ON_ FILL_ GTD_ TIMESTAMP_ IN_ PAST GUARANTEED_The guaranteed stop loss on fill has a GTD TimeInForce but no GTD timestamp.STOP_ LOSS_ ON_ FILL_ GTD_ TIMESTAMP_ MISSING GUARANTEED_Filling the order would create a guaranteed stop loss order for a hedged trade, and the account's configuration does not allow that.STOP_ LOSS_ ON_ FILL_ HEDGING_ NOT_ ALLOWED GUARANTEED_Filling the order would create a guaranteed stop loss order whose trigger price breaks the account's level restriction price range for guaranteed stop loss orders.STOP_ LOSS_ ON_ FILL_ LEVEL_ RESTRICTION_ PRICE_ RANGE_ EXCEEDED GUARANTEED_Filling the order would create a guaranteed stop loss order whose number of units breaks the account's level restriction volume for guaranteed stop loss orders.STOP_ LOSS_ ON_ FILL_ LEVEL_ RESTRICTION_ VOLUME_ EXCEEDED GUARANTEED_Filling the order would create a guaranteed stop loss order that would be filled immediately, closing the new trade at a loss.STOP_ LOSS_ ON_ FILL_ LOSS GUARANTEED_The distance between the guaranteed stop loss on fill's price and the pending order's price is less than the account's configured minimum guaranteed stop loss distance.STOP_ LOSS_ ON_ FILL_ MINIMUM_ DISTANCE_ NOT_ MET GUARANTEED_A guaranteed stop loss on fill was sent, but the account's configuration does not allow guaranteed stop loss orders.STOP_ LOSS_ ON_ FILL_ NOT_ ALLOWED GUARANTEED_The guaranteed stop loss on fill contains neither the price field nor the distance field.STOP_ LOSS_ ON_ FILL_ PRICE_ AND_ DISTANCE_ BOTH_ MISSING GUARANTEED_The guaranteed stop loss on fill contains both the price field and the distance field.STOP_ LOSS_ ON_ FILL_ PRICE_ AND_ DISTANCE_ BOTH_ SPECIFIED GUARANTEED_The guaranteed stop loss on fill price distance is more than the maximum allowed.STOP_ LOSS_ ON_ FILL_ PRICE_ DISTANCE_ MAXIMUM_ EXCEEDED GUARANTEED_The guaranteed stop loss on fill gives a price that is not valid.STOP_ LOSS_ ON_ FILL_ PRICE_ INVALID GUARANTEED_The guaranteed stop loss on fill does not give a price.STOP_ LOSS_ ON_ FILL_ PRICE_ MISSING GUARANTEED_The guaranteed stop loss on fill gives a price with more precision than the order's instrument allows.STOP_ LOSS_ ON_ FILL_ PRICE_ PRECISION_ EXCEEDED GUARANTEED_The account's configuration requires guaranteed stop loss orders and the order did not provide one on fill.STOP_ LOSS_ ON_ FILL_ REQUIRED GUARANTEED_A pending order was sent with no guaranteed stop loss on fill, and the account's configuration requires every trade to have a guaranteed stop loss order.STOP_ LOSS_ ON_ FILL_ REQUIRED_ FOR_ PENDING_ ORDER GUARANTEED_The guaranteed stop loss on fill gives a TimeInForce that is not valid.STOP_ LOSS_ ON_ FILL_ TIME_ IN_ FORCE_ INVALID GUARANTEED_The guaranteed stop loss on fill does not give a TimeInForce.STOP_ LOSS_ ON_ FILL_ TIME_ IN_ FORCE_ MISSING GUARANTEED_The guaranteed stop loss on fill gives a TriggerCondition that is not valid.STOP_ LOSS_ ON_ FILL_ TRIGGER_ CONDITION_ INVALID GUARANTEED_The guaranteed stop loss on fill does not give a TriggerCondition.STOP_ LOSS_ ON_ FILL_ TRIGGER_ CONDITION_ MISSING GUARANTEED_A guaranteed stop loss order already exists for the trade specified.STOP_ LOSS_ ORDER_ ALREADY_ EXISTS GUARANTEED_A guaranteed stop loss order was sent while the market was open, which OANDA's page lists as a violation.STOP_ LOSS_ ORDER_ CREATE_ VIOLATION GUARANTEED_A guaranteed stop loss order was sent while the market was halted.STOP_ LOSS_ ORDER_ HALTED_ CREATE_ VIOLATION GUARANTEED_A guaranteed stop loss order could not be cancelled while the market is halted, because the account's configuration requires every trade to have one.STOP_ LOSS_ ORDER_ HALTED_ NOT_ CANCELABLE GUARANTEED_A guaranteed stop loss order could not be cancelled and replaced while the market is halted, because the account's configuration prevents guaranteed stop loss orders from being modified.STOP_ LOSS_ ORDER_ HALTED_ NOT_ REPLACEABLE GUARANTEED_A guaranteed stop loss order was sent again with a tighter fill price while the market was halted.STOP_ LOSS_ ORDER_ HALTED_ TIGHTEN_ VIOLATION GUARANTEED_A guaranteed stop loss order was sent for a hedged trade, meaning an open trade exists in the opposite direction, and the account's configuration does not allow that.STOP_ LOSS_ ORDER_ HEDGING_ NOT_ ALLOWED GUARANTEED_A guaranteed stop loss order was sent that would take the account past its configured level restriction price range for guaranteed stop loss orders.STOP_ LOSS_ ORDER_ LEVEL_ RESTRICTION_ PRICE_ RANGE_ EXCEEDED GUARANTEED_A guaranteed stop loss order was sent that would take the account past its configured level restriction volume for guaranteed stop loss orders.STOP_ LOSS_ ORDER_ LEVEL_ RESTRICTION_ VOLUME_ EXCEEDED GUARANTEED_A guaranteed stop loss order was sent whose trigger price is closer to the current price than the account's configured minimum guaranteed stop loss distance.STOP_ LOSS_ ORDER_ MINIMUM_ DISTANCE_ NOT_ MET GUARANTEED_A guaranteed stop loss order was sent, but the account's configuration does not allow guaranteed stop loss orders.STOP_ LOSS_ ORDER_ NOT_ ALLOWED GUARANTEED_A guaranteed stop loss order could not be cancelled while the market is open, because the account's configuration requires every trade to have one.STOP_ LOSS_ ORDER_ NOT_ CANCELABLE GUARANTEED_A guaranteed stop loss order could not be cancelled and replaced while the market is open, because the account's configuration prevents guaranteed stop loss orders from being modified.STOP_ LOSS_ ORDER_ NOT_ REPLACEABLE GUARANTEED_The guaranteed stop loss order request contains neither the price field nor the distance field.STOP_ LOSS_ ORDER_ PRICE_ AND_ DISTANCE_ BOTH_ MISSING GUARANTEED_The guaranteed stop loss order request contains both the price field and the distance field.STOP_ LOSS_ ORDER_ PRICE_ AND_ DISTANCE_ BOTH_ SPECIFIED GUARANTEED_A guaranteed stop loss order was sent with a price inside the current tradeable spread.STOP_ LOSS_ ORDER_ PRICE_ WITHIN_ SPREAD GUARANTEED_A stop loss order that is not guaranteed was sent on an account that requires every stop loss order to be guaranteed.STOP_ LOSS_ ORDER_ REQUIRED GUARANTEED_The guaranteed stop loss order would break the account's rule that a trade with a guaranteed stop loss order can carry no other risk management order.STOP_ LOSS_ ORDER_ RMO_ MUTUAL_ EXCLUSIVITY_ GSLO_ EXCLUDES_ OTHERS_ VIOLATION GUARANTEED_The guaranteed stop loss order would break the account's rule that only one risk management order can be attached to a trade.STOP_ LOSS_ ORDER_ RMO_ MUTUAL_ EXCLUSIVITY_ MUTUALLY_ EXCLUSIVE_ VIOLATION GUARANTEED_A guaranteed stop loss order was sent again with a tighter fill price while the market was open, which OANDA's page lists as a violation.STOP_ LOSS_ ORDER_ TIGHTEN_ VIOLATION GUARANTEED_The guaranteed stop loss order would put its trade in breach of the FIFO violation safeguard constraints.STOP_ LOSS_ ORDER_ WOULD_ VIOLATE_ FIFO_ VIOLATION_ SAFEGUARD HEDGING_Filling the order would create a trade while an opposing, hedged trade already carries a guaranteed stop loss order.GSLO_ VIOLATION HTTP 401 (invalid or missing token)The access token is invalid or missing.HTTP 405The endpoint was called with the wrong HTTP method.HTTP 429OANDA returned HTTP 429 because requests arrived faster than it would accept them.INSTRUMENT_Filling the order would use the ask, but asks are halted on the instrument, so no long orders can be filled.ASK_ HALTED INSTRUMENT_Filling the order would need a new long trade, but the instrument is configured so that orders filled at ask prices can only reduce existing positions.ASK_ REDUCE_ ONLY INSTRUMENT_Filling the order would use the bid, but bids are halted on the instrument, so no short orders can be filled.BID_ HALTED INSTRUMENT_Filling the order would need a new short trade, but the instrument is configured so that orders filled at bid prices can only reduce existing positions.BID_ REDUCE_ ONLY INSTRUMENT_The order's instrument was not specified.MISSING INSTRUMENT_The instrument specified cannot be traded by this account.NOT_ TRADEABLE INSTRUMENT_OANDA's system could not determine the current price for the order's instrument.PRICE_ UNKNOWN INSTRUMENT_The instrument specified is unknown.UNKNOWN Insufficient authorization to perform request.Usually the host (practice or live) does not match your token or account.INSUFFICIENT_The account does not have enough balance to complete the funding request.FUNDS INSUFFICIENT_The order could not be filled for want of liquidity.LIQUIDITY INSUFFICIENT_The account had too little margin for the action.MARGIN INTERNAL_An unexpected internal server error happened on OANDA's side.SERVER_ ERROR Invalid value specified for 'instrument'Instrument name malformed.INVALID_An order that was partially filled straight away could not be reissued as a correct pending order.REISSUE_ IMMEDIATE_ PARTIAL_ FILL LOSING_Filling the order would create a take profit order that would close the new trade at a loss when filled.TAKE_ PROFIT MARGIN_The margin rate provided is not valid.RATE_ INVALID MARGIN_The margin rate provided would cause an immediate margin closeout, so the change was refused.RATE_ WOULD_ TRIGGER_ CLOSEOUT MARGIN_The margin rate provided would put the account into a margin call state, so the change was refused.RATE_ WOULD_ TRIGGER_ MARGIN_ CALL MARKET_The order could not be filled because its instrument was halted.HALTED MARKUP_The markup group ID provided is not valid.GROUP_ ID_ INVALID NO_The order ID specified does not exist.SUCH_ ORDER NO_Trade ID does not exist or is no longer in the recent list.SUCH_ TRADE NO_The transaction ID specified does not exist.SUCH_ TRANSACTION OCA_The list of order identifiers for a One Cancels All order includes a stop loss order.ORDER_ IDS_ STOP_ LOSS_ NOT_ ALLOWED OPEN_Filling the order would take the account past the maximum number of open trades it is allowed.TRADES_ ALLOWED_ EXCEEDED ORDER_Cancelling the order would cause an immediate margin closeout.CANCEL_ WOULD_ TRIGGER_ CLOSEOUT ORDER_The order specified does not exist.DOESNT_ EXIST ORDER_The OrderFillPositionAction specified is not valid.FILL_ POSITION_ ACTION_ INVALID ORDER_The OrderFillPositionAction field was not specified.FILL_ POSITION_ ACTION_ MISSING ORDER_Neither the order ID nor the client order ID was specified.ID_ UNSPECIFIED ORDER_The order ID and the client order ID given do not identify the same order.IDENTIFIER_ INCONSISTENCY ORDER_The order's partial fill option is not valid.PARTIAL_ FILL_ OPTION_ INVALID ORDER_The order's partial fill option was not specified.PARTIAL_ FILL_ OPTION_ MISSING ORDERS_More than one of the orders to be created on fill carries the same client order ID.ON_ FILL_ DUPLICATE_ CLIENT_ ORDER_ IDS ORDERS_The orders on fill would break the account's rule that a trade with a guaranteed stop loss order can carry no other risk management order.ON_ FILL_ RMO_ MUTUAL_ EXCLUSIVITY_ GSLO_ EXCLUDES_ OTHERS_ VIOLATION ORDERS_The orders on fill would break the account's rule that only one risk management order can be attached to a trade.ON_ FILL_ RMO_ MUTUAL_ EXCLUSIVITY_ MUTUALLY_ EXCLUSIVE_ VIOLATION PENDING_Creating or filling the order would take the account past the maximum number of pending orders it is allowed.ORDERS_ ALLOWED_ EXCEEDED POSITION_The PositionAggregationMode provided is not supported or not valid.AGGREGATION_ MODE_ INVALID POSITION_Closing out a position was not fully possible.CLOSEOUT_ FAILED POSITION_Filling the order would have taken the account past its maximum position size for the order's instrument.SIZE_ EXCEEDED PRICE_The price bound specified is not valid.BOUND_ INVALID PRICE_The price bound carries more precision than the order's instrument allows.BOUND_ PRECISION_ EXCEEDED PRICE_The price distance specified is not valid.DISTANCE_ INVALID PRICE_The price distance is more than the maximum amount allowed.DISTANCE_ MAXIMUM_ EXCEEDED PRICE_The price distance is less than the minimum amount allowed.DISTANCE_ MINIMUM_ NOT_ MET PRICE_The price distance was not specified.DISTANCE_ MISSING PRICE_The price distance carries more precision than the instrument allows.DISTANCE_ PRECISION_ EXCEEDED PRICE_The price specified is not valid.INVALID PRICE_The price was not specified.MISSING PRICE_The price carries more precision than the instrument allows.PRECISION_ EXCEEDED REPLACING_The order to be replaced is of a different type from the replacing order.ORDER_ INVALID REPLACING_The replacing order refers to a different trade from the order being replaced.TRADE_ ID_ INVALID STOP_The client order comment on the stop loss on fill is not valid.LOSS_ ON_ FILL_ CLIENT_ ORDER_ COMMENT_ INVALID STOP_Filling the order would have created a stop loss order with a client order ID that is already in use.LOSS_ ON_ FILL_ CLIENT_ ORDER_ ID_ ALREADY_ EXISTS STOP_The client order ID on the stop loss on fill is not valid.LOSS_ ON_ FILL_ CLIENT_ ORDER_ ID_ INVALID STOP_The client order tag on the stop loss on fill is not valid.LOSS_ ON_ FILL_ CLIENT_ ORDER_ TAG_ INVALID STOP_The stop loss on fill distance is not valid.LOSS_ ON_ FILL_ DISTANCE_ INVALID STOP_The stop loss on fill distance carries more precision than the instrument allows.LOSS_ ON_ FILL_ DISTANCE_ PRECISION_ EXCEEDED STOP_The stop loss on fill gives a GTD timestamp that is in the past.LOSS_ ON_ FILL_ GTD_ TIMESTAMP_ IN_ PAST STOP_The stop loss on fill has a GTD TimeInForce but no GTD timestamp.LOSS_ ON_ FILL_ GTD_ TIMESTAMP_ MISSING STOP_Filling the order would create a guaranteed stop loss order on a short trade, which would be long, while the ask side is halted.LOSS_ ON_ FILL_ GUARANTEED_ ASK_ HALTED STOP_Filling the order would create a guaranteed stop loss order on a long trade, which would be short, while the bid side is halted.LOSS_ ON_ FILL_ GUARANTEED_ BID_ HALTED STOP_Filling the order would create a guaranteed stop loss order for a hedged trade, and the account's configuration does not allow that.LOSS_ ON_ FILL_ GUARANTEED_ HEDGING_ NOT_ ALLOWED STOP_A guaranteed stop loss on fill was configured and the order's units are more than the account's configured level restriction volume for guaranteed stop loss orders.LOSS_ ON_ FILL_ GUARANTEED_ LEVEL_ RESTRICTION_ EXCEEDED STOP_The distance between the guaranteed stop loss on fill's price and the pending order's price is less than the account's configured minimum guaranteed stop loss distance.LOSS_ ON_ FILL_ GUARANTEED_ MINIMUM_ DISTANCE_ NOT_ MET STOP_A stop loss on fill was explicitly set to be guaranteed, but the account's configuration does not allow guaranteed stop loss orders.LOSS_ ON_ FILL_ GUARANTEED_ NOT_ ALLOWED STOP_A stop loss on fill was explicitly set to be not guaranteed, but the account's configuration requires guaranteed stop loss orders.LOSS_ ON_ FILL_ GUARANTEED_ REQUIRED STOP_Filling the order would create a stop loss order that would be filled immediately, closing the new trade at a loss.LOSS_ ON_ FILL_ LOSS STOP_The stop loss on fill contains neither the price field nor the distance field.LOSS_ ON_ FILL_ PRICE_ AND_ DISTANCE_ BOTH_ MISSING STOP_The stop loss on fill contains both the price field and the distance field.LOSS_ ON_ FILL_ PRICE_ AND_ DISTANCE_ BOTH_ SPECIFIED STOP_The stop loss on fill price distance is more than the maximum allowed.LOSS_ ON_ FILL_ PRICE_ DISTANCE_ MAXIMUM_ EXCEEDED STOP_The stop loss on fill gives a price that is not valid.LOSS_ ON_ FILL_ PRICE_ INVALID STOP_The stop loss on fill does not give a price.LOSS_ ON_ FILL_ PRICE_ MISSING STOP_Price has more decimal places than the instrument allows.LOSS_ ON_ FILL_ PRICE_ PRECISION_ EXCEEDED STOP_Filling the order would not create a stop loss order, and the account's configuration requires every trade to have one.LOSS_ ON_ FILL_ REQUIRED STOP_A pending order was sent with no stop loss on fill, and the account's configuration requires every trade to have a stop loss order.LOSS_ ON_ FILL_ REQUIRED_ FOR_ PENDING_ ORDER STOP_The stop loss on fill gives a TimeInForce that is not valid.LOSS_ ON_ FILL_ TIME_ IN_ FORCE_ INVALID STOP_The stop loss on fill does not give a TimeInForce.LOSS_ ON_ FILL_ TIME_ IN_ FORCE_ MISSING STOP_The stop loss on fill gives a TriggerCondition that is not valid.LOSS_ ON_ FILL_ TRIGGER_ CONDITION_ INVALID STOP_The stop loss on fill does not give a TriggerCondition.LOSS_ ON_ FILL_ TRIGGER_ CONDITION_ MISSING STOP_A stop loss order already exists for the trade specified.LOSS_ ORDER_ ALREADY_ EXISTS STOP_A guaranteed stop loss order was sent while the market was halted.LOSS_ ORDER_ GUARANTEED_ HALTED_ CREATE_ VIOLATION STOP_A guaranteed stop loss order was sent again with a tighter fill price while the market was halted.LOSS_ ORDER_ GUARANTEED_ HALTED_ TIGHTEN_ VIOLATION STOP_A guaranteed stop loss order was sent for a hedged trade, meaning an open trade exists in the opposite direction, and the account's configuration does not allow that.LOSS_ ORDER_ GUARANTEED_ HEDGING_ NOT_ ALLOWED STOP_A guaranteed stop loss order was sent that would take the account past its configured level restriction volume for guaranteed stop loss orders.LOSS_ ORDER_ GUARANTEED_ LEVEL_ RESTRICTION_ EXCEEDED STOP_A guaranteed stop loss order was sent whose trigger price is closer to the current price than the account's configured minimum guaranteed stop loss distance.LOSS_ ORDER_ GUARANTEED_ MINIMUM_ DISTANCE_ NOT_ MET STOP_A guaranteed stop loss order was sent, but the account's configuration does not allow guaranteed stop loss orders.LOSS_ ORDER_ GUARANTEED_ NOT_ ALLOWED STOP_A guaranteed stop loss order was sent with a price inside the current tradeable spread.LOSS_ ORDER_ GUARANTEED_ PRICE_ WITHIN_ SPREAD STOP_A stop loss order that is not guaranteed was sent on an account that requires every stop loss order to be guaranteed.LOSS_ ORDER_ GUARANTEED_ REQUIRED STOP_A stop loss order could not be cancelled because the account's configuration requires every trade to have one.LOSS_ ORDER_ NOT_ CANCELABLE STOP_A stop loss order could not be cancelled and replaced because the account's configuration prevents stop loss orders from being modified.LOSS_ ORDER_ NOT_ REPLACEABLE STOP_The stop loss order request contains neither the price field nor the distance field.LOSS_ ORDER_ PRICE_ AND_ DISTANCE_ BOTH_ MISSING STOP_The stop loss order request contains both the price field and the distance field.LOSS_ ORDER_ PRICE_ AND_ DISTANCE_ BOTH_ SPECIFIED STOP_The stop loss order would break the account's rule that a trade with a guaranteed stop loss order can carry no other risk management order.LOSS_ ORDER_ RMO_ MUTUAL_ EXCLUSIVITY_ GSLO_ EXCLUDES_ OTHERS_ VIOLATION STOP_The stop loss order would break the account's rule that only one risk management order can be attached to a trade.LOSS_ ORDER_ RMO_ MUTUAL_ EXCLUSIVITY_ MUTUALLY_ EXCLUSIVE_ VIOLATION STOP_The stop loss order would put its trade in breach of the FIFO violation safeguard constraints.LOSS_ ORDER_ WOULD_ VIOLATE_ FIFO_ VIOLATION_ SAFEGUARD TAKE_The client order comment on the take profit on fill is not valid.PROFIT_ ON_ FILL_ CLIENT_ ORDER_ COMMENT_ INVALID TAKE_Filling the order would have created a take profit order with a client order ID that is already in use.PROFIT_ ON_ FILL_ CLIENT_ ORDER_ ID_ ALREADY_ EXISTS TAKE_The client order ID on the take profit on fill is not valid.PROFIT_ ON_ FILL_ CLIENT_ ORDER_ ID_ INVALID TAKE_The client order tag on the take profit on fill is not valid.PROFIT_ ON_ FILL_ CLIENT_ ORDER_ TAG_ INVALID TAKE_The take profit on fill gives a GTD timestamp that is in the past.PROFIT_ ON_ FILL_ GTD_ TIMESTAMP_ IN_ PAST TAKE_The take profit on fill has a GTD TimeInForce but no GTD timestamp.PROFIT_ ON_ FILL_ GTD_ TIMESTAMP_ MISSING TAKE_Filling the order would create a take profit order that would be filled immediately, closing the new trade at a loss.PROFIT_ ON_ FILL_ LOSS TAKE_Filling the order would create a take profit order whose price would be zero or negative because of the distance specified.PROFIT_ ON_ FILL_ PRICE_ DISTANCE_ MAXIMUM_ EXCEEDED TAKE_The take profit on fill contains a price that is not valid.PROFIT_ ON_ FILL_ PRICE_ INVALID TAKE_The take profit on fill does not give a price.PROFIT_ ON_ FILL_ PRICE_ MISSING TAKE_The take profit on fill gives a price with more precision than the order's instrument allows.PROFIT_ ON_ FILL_ PRICE_ PRECISION_ EXCEEDED TAKE_The take profit on fill gives a TimeInForce that is not valid.PROFIT_ ON_ FILL_ TIME_ IN_ FORCE_ INVALID TAKE_The take profit on fill does not give a TimeInForce.PROFIT_ ON_ FILL_ TIME_ IN_ FORCE_ MISSING TAKE_The take profit on fill gives a TriggerCondition that is not valid.PROFIT_ ON_ FILL_ TRIGGER_ CONDITION_ INVALID TAKE_The take profit on fill does not give a TriggerCondition.PROFIT_ ON_ FILL_ TRIGGER_ CONDITION_ MISSING TAKE_A take profit order already exists for the trade specified.PROFIT_ ORDER_ ALREADY_ EXISTS TAKE_The take profit order would put its trade in breach of the FIFO violation safeguard constraints.PROFIT_ ORDER_ WOULD_ VIOLATE_ FIFO_ VIOLATION_ SAFEGUARD The provided request was forbidden.The account ID given is not valid.The request was missing required dataOne or more parameters that the request requires are missing or not valid.TIME_The TimeInForce is GTD but the GTD timestamp is in the past.IN_ FORCE_ GTD_ TIMESTAMP_ IN_ PAST TIME_The TimeInForce is GTD but no GTD timestamp was given.IN_ FORCE_ GTD_ TIMESTAMP_ MISSING TIME_The TimeInForce specified is not valid.IN_ FORCE_ INVALID TIME_The TimeInForce field was not specified.IN_ FORCE_ MISSING TRADE_The trade specified does not exist.DOESNT_ EXIST TRADE_Neither the trade ID nor the client trade ID was specified.ID_ UNSPECIFIED TRADE_The trade ID and the client trade ID given do not identify the same trade.IDENTIFIER_ INCONSISTENCY TRADE_The order cannot create a new trade, so it does not support trade on fill client extensions.ON_ FILL_ CLIENT_ EXTENSIONS_ NOT_ SUPPORTED TRAILING_The client order comment on the trailing stop loss on fill is not valid.STOP_ LOSS_ ON_ FILL_ CLIENT_ ORDER_ COMMENT_ INVALID TRAILING_Filling the order would have created a trailing stop loss order with a client order ID that is already in use.STOP_ LOSS_ ON_ FILL_ CLIENT_ ORDER_ ID_ ALREADY_ EXISTS TRAILING_The client order ID on the trailing stop loss on fill is not valid.STOP_ LOSS_ ON_ FILL_ CLIENT_ ORDER_ ID_ INVALID TRAILING_The client order tag on the trailing stop loss on fill is not valid.STOP_ LOSS_ ON_ FILL_ CLIENT_ ORDER_ TAG_ INVALID TRAILING_The trailing stop loss on fill GTD timestamp is in the past.STOP_ LOSS_ ON_ FILL_ GTD_ TIMESTAMP_ IN_ PAST TRAILING_The trailing stop loss on fill has a GTD TimeInForce but no GTD timestamp.STOP_ LOSS_ ON_ FILL_ GTD_ TIMESTAMP_ MISSING TRAILING_The trailing stop loss on fill distance is not valid.STOP_ LOSS_ ON_ FILL_ PRICE_ DISTANCE_ INVALID TRAILING_The trailing stop loss on fill price distance is more than the maximum allowed.STOP_ LOSS_ ON_ FILL_ PRICE_ DISTANCE_ MAXIMUM_ EXCEEDED TRAILING_The trailing stop loss on fill price distance is less than the minimum allowed.STOP_ LOSS_ ON_ FILL_ PRICE_ DISTANCE_ MINIMUM_ NOT_ MET TRAILING_The trailing stop loss on fill does not give a distance.STOP_ LOSS_ ON_ FILL_ PRICE_ DISTANCE_ MISSING TRAILING_The trailing stop loss on fill distance carries more precision than the instrument allows.STOP_ LOSS_ ON_ FILL_ PRICE_ DISTANCE_ PRECISION_ EXCEEDED TRAILING_The trailing stop loss on fill gives a TimeInForce that is not valid.STOP_ LOSS_ ON_ FILL_ TIME_ IN_ FORCE_ INVALID TRAILING_The trailing stop loss on fill does not give a TimeInForce.STOP_ LOSS_ ON_ FILL_ TIME_ IN_ FORCE_ MISSING TRAILING_The trailing stop loss on fill gives a TriggerCondition that is not valid.STOP_ LOSS_ ON_ FILL_ TRIGGER_ CONDITION_ INVALID TRAILING_The trailing stop loss on fill does not give a TriggerCondition.STOP_ LOSS_ ON_ FILL_ TRIGGER_ CONDITION_ MISSING TRAILING_A trailing stop loss order already exists for the trade specified.STOP_ LOSS_ ORDER_ ALREADY_ EXISTS TRAILING_The trailing stop loss order would break the account's rule that a trade with a guaranteed stop loss order can carry no other risk management order.STOP_ LOSS_ ORDER_ RMO_ MUTUAL_ EXCLUSIVITY_ GSLO_ EXCLUDES_ OTHERS_ VIOLATION TRAILING_The trailing stop loss order would break the account's rule that only one risk management order can be attached to a trade.STOP_ LOSS_ ORDER_ RMO_ MUTUAL_ EXCLUSIVITY_ MUTUALLY_ EXCLUSIVE_ VIOLATION TRAILING_The trailing stop loss order would put its trade in breach of the FIFO violation safeguard constraints.STOP_ LOSS_ ORDER_ WOULD_ VIOLATE_ FIFO_ VIOLATION_ SAFEGUARD TRAILING_A trailing stop loss order, or an order with a trailing stop loss on fill, was sent where OANDA's page says it may not yet be supported.STOP_ LOSS_ ORDERS_ NOT_ SUPPORTED TRIGGER_The TriggerCondition specified is not valid.CONDITION_ INVALID TRIGGER_The TriggerCondition field was not specified.CONDITION_ MISSING UNITS_The order units specified are not valid.INVALID UNITS_The units in the request are more than the maximum number of units allowed.LIMIT_ EXCEEDED UNITS_The units are fewer than the minimum number of units required.MINIMUM_ NOT_ MET UNITS_The order's units were not specified.MISSING UNITS_The units carry more precision than the order's instrument allows.PRECISION_ EXCEEDED
Platform APIs an account here can reach
| Platform API | Offered | Note | Source |
|---|---|---|---|
| MetaTrader 4 (MQL4) | Yes | MT4 offered. Expert Advisors allowed: 'The MetaTrader 4 platform supports Expert Advisors (EAs)'. | OANDA UK MetaTrader 4checked |
| MetaTrader 5 (Python package and MQL5) | Yes | MT5 on web, desktop and mobile, live and demo. Expert Advisors allowed: 'Create expert advisors in MQL5 to automate your trading strategies'. | OANDA UK MetaTrader 5checked |
| cTrader Open API | No | cTrader not listed on the broker's UK platforms page; absence from an overview page is not proof, so unverified. | UnverifiedOANDA UK trading platformschecked |
| TradeLocker API | No | TradeLocker not listed on the broker's UK platforms page; absence from an overview page is not proof, so unverified. | UnverifiedOANDA UK trading platformschecked |
| Match-Trader Platform API | No | Match-Trader not listed on the broker's UK platforms page; absence from an overview page is not proof, so unverified. | UnverifiedOANDA UK trading platformschecked |
| DXtrade APIs | No | DXtrade not listed on the broker's UK platforms page; absence from an overview page is not proof, so unverified. | UnverifiedOANDA UK trading platformschecked |
OANDA API SDKs and wrappers
| Library | Language | Official | Note | Source |
|---|---|---|---|---|
| v20 | Python | Official | Not recorded | Unverifiedgithub.com |
| oandapyV20 | Python | Community | Community wrapper, last release 0.7.2 in Aug 2021. | github.comchecked |
OANDA API: questions and answers
Each answer is read from the record on this page, not written separately. Where the record is unverified, the answer says so.
Does OANDA have an API?
Yes. This register records OANDA as having its own API (REST (v20) and HTTP streaming), with availability marked as active. v20 REST API with HTTP streaming for prices and transactions.
OANDA: v20 REST introductionchecked
OANDA API key: how do I get one?
Account Management Portal > My Services > Manage API Access, accept licence, generate personal access token.
OANDA v20 Introductionchecked
Who can use the OANDA API?
Needs a v20 account; available in all divisions except OANDA Global Markets and OANDA TMS Brokers S.A.
OANDA v20 Introductionchecked
OANDA API demo: is there a demo or sandbox?
Yes: fxTrade Practice environment with its own token.
OANDA Development Guidechecked
What are the OANDA API rate limits?
Headline limit: 120/s per IP address, HTTP 429 above it. Scope: ip. As the record words it: OANDA publishes two figures, on two pages, in two units. The enforced one is on the development guide. The development guide states 120 requests a second per IP address, with HTTP 429 above that, and at most 20 active streams.
developer.oanda.comchecked OANDA v20 best practiceschecked
How does OANDA API authentication work?
Bearer personal access token, generated in the Account Management Portal after accepting the API licence.
Does the OANDA API support streaming?
HTTP chunked transfer encoding carrying JSON objects, not WebSocket. The development guide states at most 20 active streams, with requests above that rejected, and no more than 2 new connections a second.
OANDA Development Guidechecked
How much history does the OANDA API return?
Historical pricing back to 2005, on the introduction page. Candles: at most 5,000 per request, 500 by default, on the pricing endpoints page. Transactions: at most 365 days per request, in pages of up to 1,000.
OANDA v20: Introductionchecked OANDA v20: Pricing endpointschecked OANDA v20: Transaction endpointschecked
Is there a Python library for the OANDA API?
This register lists these Python libraries for the OANDA API. v20 (official, Python). oandapyV20 (community, Python): Community wrapper, last release 0.7.2 in Aug 2021.
oandapyV20checked
Which platform APIs work with an account at OANDA?
Recorded as offered, with a source: MetaTrader 4 and MetaTrader 5. Not verified either way: cTrader, TradeLocker, Match-Trader and DXtrade.
OANDA UK MetaTrader 4checked OANDA UK MetaTrader 5checked
OANDA API questions, each answered in a sentence or two.
The capability tables read one feature at a time across every broker and platform record, OANDA included.
Everything this site records for OANDA, as one JSON file. Each section of the file states its own licence. About the files. This page as Markdown.
OANDA API guides and reference
- OANDA API quickstart: key to first call
- OANDA API endpoints, grouped by what they do
- OANDA API error codes
- Get your OANDA trade history into a spreadsheetOANDA's HUB exports transaction history straight to CSV. Set your timezone first, because it defaults to GMT -12. A mobile export is not mentioned on OANDA's help page.
OANDA API compared
The same fields from two records, side by side. No winner is picked.
What changed recently for the OANDA API
Documentation
OANDA's instrument endpoints page answered 404 on 12 Oct 2026 and is no longer in the v20 documentation menu. The candles call this site read there, GET /v3/instruments/{instrument}/candles, is now marked not verified: OANDA's own OpenAPI file on GitHub still defines it, but no page on developer.oanda.com that we opened does. The site documents the account scoped call, GET /v3/accounts/{accountID}/instruments/{instrument}/candles, on its pricing endpoints page. A missing page is not evidence that the call has gone.
Documentation
OANDA's history depth claim was sourced to the instrument endpoints page, which answered 404 on 12 Oct 2026. Each part was re-read on a page that opens: pricing back to 2005 on the introduction, at most 5,000 candles a request with 500 by default on the pricing endpoints page, and at most 365 days of transactions a request in pages of up to 1,000 on the transaction endpoints page. The figures are unchanged.
Ecosystem
The v20 introduction states the API is not available to OANDA Global Markets or OANDA TMS Brokers S.A. clients. Separately, two OANDA pages state limits in different units: the development guide states 120 requests a second per IP with at most 20 active streams, and the best practices page states 2 new connections a second and 100 requests a second on a persistent connection. Read 23 September 2026.
OANDA v20 REST API: introductiondate last opened not recorded
The newest entries are shown. Every dated change, all brokers and platforms. Follow OANDA changes by RSS
Sample apps that use the OANDA API
- OANDA streaming price loggerOpens one HTTP price stream on the fxTrade Practice host and appends each price to a CSV file.
Partner programme
Published figure, as the page words it: up to US$600* for every client you successfully introduce to us. The OANDA partner programme record. The programme register holds every record. This site carries no affiliate links.
How to cite this
OANDA trading API (v20). Broker API Hub, https://openbrokerapi.com/brokers/oanda, newest check .
Where you rely on a single figure, cite the source and the checked date printed beside it as well.