Skip to content

FX Rail

The FX Rail provides APIs for Treasury foreign exchange operations, including quote management, trade booking, position tracking, and limit monitoring.

The FX Rail supports the full foreign exchange lifecycle:

CapabilityDescription
Quote ManagementRequest and manage FX rate quotes
Trade BookingBook, submit, approve, and settle FX trades
Position TrackingReal-time FX position monitoring by currency
Limit ManagementConfigure and monitor FX trading limits
GET /api/v1/fx/quotes

Lists all FX quotes for the authenticated tenant.

Query Parameters:

ParameterTypeDescription
statusstringFilter by status (pending, filled, expired, cancelled)
currencyPairstringFilter by currency pair (e.g., USD/SAR)
pagenumberPage number (default: 1)
perPagenumberItems per page (default: 20, max: 100)
POST /api/v1/fx/quotes

Requests a new FX rate quote.

Request Body:

{
"currencyPair": "USD/SAR",
"direction": "buy",
"notionalAmount": {
"amount": 500000,
"currency": "USD"
},
"valueDate": "2024-01-17",
"tenorCode": "SPOT"
}

Response:

{
"data": {
"id": "fxq_abc123",
"status": "pending",
"currencyPair": "USD/SAR",
"direction": "buy",
"rate": 3.7505,
"notionalAmount": {
"amount": 500000,
"currency": "USD"
},
"counterAmount": {
"amount": 1875250,
"currency": "SAR"
},
"valueDate": "2024-01-17",
"expiresAt": "2024-01-15T10:32:00Z",
"createdAt": "2024-01-15T10:30:00Z"
}
}
GET /api/v1/fx/trades

Lists all FX trades for the authenticated tenant.

Query Parameters:

ParameterTypeDescription
statusstringFilter by status (booked, submitted, approved, confirmed, settled, cancelled)
currencyPairstringFilter by currency pair
fromDatestringFilter trades from date (ISO 8601)
toDatestringFilter trades to date (ISO 8601)
pagenumberPage number (default: 1)
perPagenumberItems per page (default: 20, max: 100)
POST /api/v1/fx/trades

Books a new FX trade from an accepted quote.

Request Body:

{
"quoteId": "fxq_abc123",
"traderReference": "TRD-2024-001",
"notes": "Customer hedging requirement"
}

Response:

{
"data": {
"id": "fxt_xyz789",
"status": "booked",
"quoteId": "fxq_abc123",
"currencyPair": "USD/SAR",
"direction": "buy",
"rate": 3.7505,
"notionalAmount": {
"amount": 500000,
"currency": "USD"
},
"counterAmount": {
"amount": 1875250,
"currency": "SAR"
},
"valueDate": "2024-01-17",
"traderReference": "TRD-2024-001",
"createdAt": "2024-01-15T10:31:00Z",
"updatedAt": "2024-01-15T10:31:00Z"
}
}
POST /api/v1/fx/trades/{id}/submit

Submits a booked trade for approval.

POST /api/v1/fx/trades/{id}/approve

Approves a submitted FX trade.

Request Body:

{
"approverNotes": "Approved within daily limit"
}
POST /api/v1/fx/trades/{id}/confirm

Confirms an approved FX trade with the counterparty.

POST /api/v1/fx/trades/{id}/settle

Marks an FX trade as settled after payment exchange.

Request Body:

{
"settlementReference": "SWIFT-20240117-001",
"settledAt": "2024-01-17T09:00:00Z"
}
POST /api/v1/fx/trades/{id}/cancel

Cancels an FX trade. Only allowed for trades in booked or submitted status.

Request Body:

{
"reason": "Market conditions changed",
"cancelledBy": "usr_trader_001"
}
GET /api/v1/fx/positions

Retrieves real-time FX positions aggregated by currency.

Response:

{
"data": [
{
"currency": "USD",
"longAmount": 2500000,
"shortAmount": 1000000,
"netPosition": 1500000,
"unrealizedPnl": {
"amount": 12500,
"currency": "SAR"
},
"asOf": "2024-01-15T10:30:00Z"
}
]
}
GET /api/v1/fx/limits

Lists all configured FX trading limits.

Query Parameters:

ParameterTypeDescription
limitTypestringFilter by type (position, daily_volume, stop_loss)
currencystringFilter by currency
statusstringFilter by status (active, breached, suspended)
POST /api/v1/fx/limits

Creates a new FX trading limit.

Request Body:

{
"limitType": "position",
"currency": "USD",
"maxAmount": {
"amount": 5000000,
"currency": "USD"
},
"alertThresholdPercent": 80,
"effectiveFrom": "2024-01-15",
"effectiveTo": "2024-12-31"
}
stateDiagram-v2
direction LR
[*] --> Booked: Book Trade
Booked --> Submitted: Submit
Submitted --> Approved: Approve
Approved --> Confirmed: Confirm
Confirmed --> Settled: Settle
Booked --> Cancelled: Cancel
Submitted --> Cancelled: Cancel
classDef booked fill:#1565c0,color:#fff,stroke:#1565c0
classDef submitted fill:#e65100,color:#fff,stroke:#e65100
classDef approved fill:#2e7d32,color:#fff,stroke:#2e7d32
classDef confirmed fill:#1a5f4a,color:#fff,stroke:#1a5f4a
classDef settled fill:#455a64,color:#fff,stroke:#455a64
classDef cancelled fill:#c62828,color:#fff,stroke:#c62828
class Booked booked
class Submitted submitted
class Approved approved
class Confirmed confirmed
class Settled settled
class Cancelled cancelled
StatusDescription
bookedTrade booked, pending submission
submittedSubmitted for approval
approvedApproved by authorized trader/manager
confirmedConfirmed with counterparty
settledSettlement completed
cancelledTrade cancelled

The FX Rail emits the following webhook events:

EventDescription
fx.quote.createdFX quote requested and created
fx.trade.bookedFX trade booked from a quote
fx.trade.submittedTrade submitted for approval
fx.trade.approvedTrade approved
fx.trade.confirmedTrade confirmed with counterparty
fx.trade.settledTrade fully settled
fx.trade.cancelledTrade cancelled
fx.position.updatedFX position updated after trade event
fx.limit.breachedFX trading limit breached
import { IOFClient } from "@iof/sdk";
const client = new IOFClient({ apiKey: process.env.IOF_API_KEY });
// Request a quote
const quote = await client.fx.quotes.create({
currencyPair: "USD/SAR",
direction: "buy",
notionalAmount: { amount: 500000, currency: "USD" },
valueDate: "2024-01-17",
tenorCode: "SPOT",
});
// Book a trade from the quote
const trade = await client.fx.trades.create({
quoteId: quote.id,
traderReference: "TRD-2024-001",
});
// Move trade through lifecycle
await client.fx.trades.submit(trade.id);
await client.fx.trades.approve(trade.id, { approverNotes: "Within limits" });
await client.fx.trades.confirm(trade.id);
await client.fx.trades.settle(trade.id, {
settlementReference: "SWIFT-20240117-001",
settledAt: new Date().toISOString(),
});
// Check current positions
const positions = await client.fx.positions.list();
from iof import IOFClient
client = IOFClient(api_key=os.environ["IOF_API_KEY"])
# Request a quote
quote = client.fx.quotes.create(
currency_pair="USD/SAR",
direction="buy",
notional_amount={"amount": 500000, "currency": "USD"},
value_date="2024-01-17",
tenor_code="SPOT",
)
# Book and submit a trade
trade = client.fx.trades.create(quote_id=quote.id, trader_reference="TRD-2024-001")
client.fx.trades.submit(trade.id)
client.fx.trades.approve(trade.id, approver_notes="Within limits")
client.fx.trades.confirm(trade.id)
client.fx.trades.settle(trade.id, settlement_reference="SWIFT-20240117-001")
# Check positions
positions = client.fx.positions.list()