JavaScript bindings for OANDA's v20 REST API enabling programmatic forex and CFD trading operations.
Complete transaction history access with querying by date range or transaction ID, transaction detail retrieval, and transaction streaming for real-time updates on all account activity.
All transaction operations are accessed via ctx.transaction where ctx is a Context instance.
Get a list of Transactions for an Account with pagination.
/**
* Get list of Transactions for Account
* @param accountID - Account identifier
* @param queryParams - Query parameters object
* - from: string (start datetime RFC3339 format, optional)
* - to: string (end datetime RFC3339 format, optional)
* - pageSize: number (transactions per page, max 1000, optional, default 100)
* - type: string (comma-separated list of transaction types to filter, optional)
* @param responseHandler - Callback receiving Response object
* Response body contains: {
* from: string,
* to: string,
* pageSize: number,
* type: string[],
* count: number,
* pages: string[],
* lastTransactionID: string
* }
*/
list(accountID, queryParams, responseHandler);Usage Example:
// List recent transactions
ctx.transaction.list('001-001-1234567-001', {
pageSize: 50
}, response => {
if (response.isSuccess()) {
console.log(`Transaction count: ${response.body.count}`);
console.log(`Pages available: ${response.body.pages.length}`);
console.log('Fetch individual pages using URLs in pages array');
}
});
// List transactions by date range
ctx.transaction.list('001-001-1234567-001', {
from: '2023-01-01T00:00:00Z',
to: '2023-01-31T23:59:59Z',
pageSize: 100
}, response => {
if (response.isSuccess()) {
console.log(`Transactions in January: ${response.body.count}`);
}
});
// Filter by transaction type
ctx.transaction.list('001-001-1234567-001', {
type: 'ORDER_FILL,MARKET_ORDER',
pageSize: 50
}, response => {
if (response.isSuccess()) {
console.log('Order fill transactions:', response.body);
}
});Get the details of a single Transaction.
/**
* Get details of specific Transaction
* @param accountID - Account identifier
* @param transactionID - Transaction identifier
* @param responseHandler - Callback receiving Response object
* Response body contains: { transaction: Transaction, lastTransactionID: string }
*/
get(accountID, transactionID, responseHandler);Usage Example:
ctx.transaction.get('001-001-1234567-001', '1234', response => {
if (response.isSuccess()) {
const txn = response.body.transaction;
console.log(`Transaction ${txn.id}:`);
console.log(` Type: ${txn.type}`);
console.log(` Time: ${txn.time}`);
console.log(` Account ID: ${txn.accountID}`);
// Type-specific properties
if (txn.type === 'ORDER_FILL') {
console.log(` Instrument: ${txn.instrument}`);
console.log(` Units: ${txn.units}`);
console.log(` Price: ${txn.price}`);
console.log(` P/L: ${txn.pl}`);
}
}
});Get a range of Transactions by ID.
/**
* Get range of Transactions
* @param accountID - Account identifier
* @param queryParams - Query parameters object
* - from: string (starting transaction ID, required)
* - to: string (ending transaction ID, required)
* - type: string (comma-separated list of transaction types to filter, optional)
* @param responseHandler - Callback receiving Response object
* Response body contains: { transactions: Transaction[], lastTransactionID: string }
*/
range(accountID, queryParams, responseHandler);Usage Example:
// Get transactions from ID 1000 to 1100
ctx.transaction.range('001-001-1234567-001', {
from: '1000',
to: '1100'
}, response => {
if (response.isSuccess()) {
console.log(`Retrieved ${response.body.transactions.length} transactions`);
response.body.transactions.forEach(txn => {
console.log(`${txn.id}: ${txn.type} at ${txn.time}`);
});
}
});Get all Transactions since a specific Transaction ID.
/**
* Get Transactions since ID
* @param accountID - Account identifier
* @param queryParams - Query parameters object
* - id: string (transaction ID to query from, required)
* - type: string (comma-separated list of transaction types to filter, optional)
* @param responseHandler - Callback receiving Response object
* Response body contains: { transactions: Transaction[], lastTransactionID: string }
*/
since(accountID, queryParams, responseHandler);Usage Example:
// Get all transactions since ID 1500
ctx.transaction.since('001-001-1234567-001', {
id: '1500'
}, response => {
if (response.isSuccess()) {
console.log(`New transactions: ${response.body.transactions.length}`);
response.body.transactions.forEach(txn => {
console.log(`${txn.id}: ${txn.type}`);
});
}
});Stream real-time Transactions for an Account.
/**
* Stream Transactions
* @param accountID - Account identifier
* @param streamChunkHandler - Callback for each streamed chunk (Transaction or TransactionHeartbeat)
* @param responseHandler - Callback receiving Response object when stream ends
* Streamed objects are Transaction instances or TransactionHeartbeat instances
*/
stream(accountID, streamChunkHandler, responseHandler);Usage Example:
ctx.transaction.stream('001-001-1234567-001',
chunk => {
// Handle each streamed chunk
try {
const data = JSON.parse(chunk);
if (data.type === 'HEARTBEAT') {
console.log('Heartbeat:', data.time);
} else {
// Transaction received
console.log(`Transaction ${data.id}: ${data.type}`);
if (data.type === 'ORDER_FILL') {
console.log(` ${data.instrument} ${data.units} @ ${data.price}`);
console.log(` P/L: ${data.pl}`);
}
}
} catch (e) {
console.error('Parse error:', e);
}
},
response => {
// Stream ended
console.log('Transaction stream ended');
}
);All transactions share common base properties:
interface TransactionBase {
id: string;
time: string; // RFC3339 timestamp
userID: string;
accountID: string;
batchID?: string;
requestID?: string;
type: string; // Transaction type (see Transaction Types below)
}The library includes 36 transaction types organized by category:
Account Lifecycle:
CREATE - CreateTransaction - Account creationCLOSE - CloseTransaction - Account closureREOPEN - ReopenTransaction - Account reopeningConfiguration:
CLIENT_CONFIGURE - ClientConfigureTransaction - Account configuration changeCLIENT_CONFIGURE_REJECT - ClientConfigureRejectTransaction - Rejected configurationFunding:
TRANSFER_FUNDS - TransferFundsTransaction - Fund transferTRANSFER_FUNDS_REJECT - TransferFundsRejectTransaction - Rejected transferOrder Creation:
MARKET_ORDER - MarketOrderTransaction - Market order createdMARKET_ORDER_REJECT - MarketOrderRejectTransaction - Market order rejectedFIXED_PRICE_ORDER - FixedPriceOrderTransaction - Fixed price orderLIMIT_ORDER - LimitOrderTransaction - Limit order createdLIMIT_ORDER_REJECT - LimitOrderRejectTransaction - Limit order rejectedSTOP_ORDER - StopOrderTransaction - Stop order createdSTOP_ORDER_REJECT - StopOrderRejectTransaction - Stop order rejectedMARKET_IF_TOUCHED_ORDER - MarketIfTouchedOrderTransaction - MIT order createdMARKET_IF_TOUCHED_ORDER_REJECT - MarketIfTouchedOrderRejectTransaction - MIT order rejectedTAKE_PROFIT_ORDER - TakeProfitOrderTransaction - Take profit order createdTAKE_PROFIT_ORDER_REJECT - TakeProfitOrderRejectTransaction - Take profit rejectedSTOP_LOSS_ORDER - StopLossOrderTransaction - Stop loss order createdSTOP_LOSS_ORDER_REJECT - StopLossOrderRejectTransaction - Stop loss rejectedTRAILING_STOP_LOSS_ORDER - TrailingStopLossOrderTransaction - Trailing stop loss createdTRAILING_STOP_LOSS_ORDER_REJECT - TrailingStopLossOrderRejectTransaction - Trailing stop loss rejectedOrder Execution:
ORDER_FILL - OrderFillTransaction - Order filledORDER_CANCEL - OrderCancelTransaction - Order cancelledORDER_CANCEL_REJECT - OrderCancelRejectTransaction - Order cancellation rejectedModifications:
ORDER_CLIENT_EXTENSIONS_MODIFY - OrderClientExtensionsModifyTransaction - Order extensions modifiedORDER_CLIENT_EXTENSIONS_MODIFY_REJECT - OrderClientExtensionsModifyRejectTransaction - Modification rejectedTRADE_CLIENT_EXTENSIONS_MODIFY - TradeClientExtensionsModifyTransaction - Trade extensions modifiedTRADE_CLIENT_EXTENSIONS_MODIFY_REJECT - TradeClientExtensionsModifyRejectTransaction - Modification rejectedMargin & Risk:
MARGIN_CALL_ENTER - MarginCallEnterTransaction - Margin call enteredMARGIN_CALL_EXTEND - MarginCallExtendTransaction - Margin call extendedMARGIN_CALL_EXIT - MarginCallExitTransaction - Margin call exitedTrade Management:
DELAYED_TRADE_CLOSURE - DelayedTradeClosureTransaction - Delayed trade closureDAILY_FINANCING - DailyFinancingTransaction - Daily financing appliedRESET_RESETTABLE_PL - ResetResettablePLTransaction - Resettable P/L resetMost important transaction type for tracking trade execution:
interface OrderFillTransaction extends TransactionBase {
type: 'ORDER_FILL';
orderID: string;
clientOrderID?: string;
instrument: string;
units: string;
price: string;
pl: string; // Realized P/L
financing: string;
commission: string;
accountBalance: string;
gainQuoteHomeConversionFactor: string;
lossQuoteHomeConversionFactor: string;
halfSpreadCost: string;
// Trade impact
tradeOpened?: TradeOpen;
tradesClosed?: TradeReduce[];
tradeReduced?: TradeReduce;
// Full trade state
fullPrice?: FullPrice;
reason?: string;
}Market order creation:
interface MarketOrderTransaction extends TransactionBase {
type: 'MARKET_ORDER';
instrument: string;
units: string;
timeInForce: string;
priceBound?: string;
positionFill: string;
reason?: string;
clientExtensions?: ClientExtensions;
takeProfitOnFill?: TakeProfitDetails;
stopLossOnFill?: StopLossDetails;
trailingStopLossOnFill?: TrailingStopLossDetails;
tradeClientExtensions?: ClientExtensions;
}Daily rollover financing:
interface DailyFinancingTransaction extends TransactionBase {
type: 'DAILY_FINANCING';
financing: string;
accountBalance: string;
accountFinancingMode: string;
positionFinancings: PositionFinancing[];
}Heartbeat for transaction streams:
interface TransactionHeartbeat {
type: 'HEARTBEAT';
time: string; // RFC3339 timestamp
}interface TradeOpen {
tradeID: string;
units: string;
price: string;
guaranteedExecutionFee?: string;
clientExtensions?: ClientExtensions;
halfSpreadCost: string;
initialMarginRequired: string;
}
interface TradeReduce {
tradeID: string;
units: string;
price: string;
realizedPL: string;
financing: string;
guaranteedExecutionFee?: string;
halfSpreadCost: string;
}
interface PositionFinancing {
instrument: string;
financing: string;
openTradeFinancings: OpenTradeFinancing[];
}
interface OpenTradeFinancing {
tradeID: string;
financing: string;
openTradeFinancing: string;
financingToDate: string;
}When streaming transactions:
type === 'HEARTBEAT' to distinguish from actual transactionsInstall with Tessl CLI
npx tessl i tessl/npm-oanda--v20