Deriv API
Migration guide/Proposal open contract

Proposal open contract

Trading
Auth Required

Get open contract details. The loginid parameter removed, response field types changed, and several display fields removed.

Quick comparison

AspectLegacyNewAction required
Endpoint
✅ Same
proposal_open_contractproposal_open_contractNone
Auth Required
✅ Same
YesYesNone
loginid Parameter
⚠️ Changed
OptionalRemovedRemove from requests
subscribe Values
⚠️ Changed
1 only0 or 1None (expanded)
Response Required Fields
⚠️ Changed
echo_req onlycontract_id, contract_type, currencyUpdate type expectations

Breaking changes

1. loginid parameter removed

What Changed: The loginid parameter has been removed from the request schema. This parameter was previously used when multiple tokens were provided during authorize.

Migration: Remove the loginid parameter from your requests. Account selection is now handled differently.

2. subscribe parameter enum expanded

What Changed: The subscribe parameter now accepts both 0 and 1, whereas legacy only accepted 1.

Migration: No action required. This is a non-breaking expansion that allows explicitly disabling subscription.

3. Response field types changed

What Changed: Several numeric fields now return string | number instead of just number:

  • bid_price: numberstring | number
  • buy_price: numberstring | number
  • current_spot: numberstring | number
  • profit: numberstring | number
  • payout: numberstring (always string now)
  • sell_price: numbernull | string
  • selected_spot: numbernull | string

Migration: Update your type definitions and parsing logic to handle both string and number values.

4. Required fields in response

What Changed: The proposal_open_contract response object now has required fields: contract_id, contract_type, and currency.

Migration: You can now rely on these fields always being present, simplifying null checks.

5. Display fields removed

What Changed: Several display-specific fields have been removed:

  • display_value - the bid_price with correct precision
  • exit_tick_display_value
  • sell_spot_display_value (was already deprecated)

Migration: Format numeric values on the client side using the currency precision.

6. Deprecated and display fields

What Changed: The display-only field sell_spot_display_value has been removed. The sell_spot and sell_spot_time fields remain in v4 but are marked as deprecated and will be removed in a future API version.

  • sell_spot_display_value - removed in v4
  • sell_spot and sell_spot_time - still present in v4 but deprecated; migrate to exit_spot and exit_spot_time

7. is_forward_starting field removed

What Changed: The is_forward_starting boolean flag has been removed.

Migration: Determine forward-starting status by comparing purchase_time and date_start.

8. Snowball contract fields removed

What Changed: Snowball contract-specific fields have been removed:

  • caution_price
  • profit_price
  • coupon_rate
  • coupon_collection_epochs
  • num_of_coupons
  • trade_risk_profile

New fields in v4

The following new fields are available in the v4 response:

  • exit_spot - Exit spot price (replaces deprecated sell_spot)
  • exit_spot_time - Epoch time of the exit spot (replaces deprecated sell_spot_time)
  • entry_spot_time - Epoch time of the entry spot
  • underlying_symbol - The underlying symbol code (alternative to underlying)

Request structure

Legacy Request Example

1{
2  "proposal_open_contract": 1,
3  "contract_id": 123456789,
4  "subscribe": 1,
5  "loginid": "CR90000001"
6}

New Request Example

1{
2  "proposal_open_contract": 1,
3  "contract_id": 123456789,
4  "subscribe": 1
5}

Note: The loginid parameter is no longer accepted in v4.

Response structure

Legacy Response Example

1{
2  "proposal_open_contract": {
3    "contract_id": 123456789,
4    "contract_type": "CALL",
5    "currency": "USD",
6    "buy_price": 10.50,
7    "bid_price": 15.50,
8    "current_spot": 1.0850,
9    "display_value": "15.50",
10    "display_name": "EUR/USD",
11    "is_forward_starting": 0,
12    "is_expired": 0,
13    "is_sold": 0,
14    "payout": 20.00,
15    "profit": 5.00,
16    "sell_spot": 1.0852,
17    "sell_spot_display_value": "1.0852",
18    "status": "open"
19  },
20  "msg_type": "proposal_open_contract"
21}

New Response Example

1{
2  "proposal_open_contract": {
3    "contract_id": 123456789,
4    "contract_type": "CALL",
5    "currency": "USD",
6    "buy_price": "10.50",
7    "bid_price": "15.50",
8    "current_spot": "1.0850",
9    "display_name": "EUR/USD",
10    "is_expired": 0,
11    "is_sold": 0,
12    "payout": "20.00",
13    "profit": "5.00",
14    "exit_spot": "1.0852",
15    "exit_spot_time": 1446629000,
16    "status": "open"
17  },
18  "msg_type": "proposal_open_contract"
19}

Note: Fields like display_value, is_forward_starting, and sell_spot_display_value are removed. sell_spot and sell_spot_time remain in v4 but are deprecated. Numeric fields may now return strings. display_name is still available.

Code examples

Legacy Implementation

1async function getOpenContract(contractId, loginId) {
2  const request = {
3    proposal_open_contract: 1,
4    contract_id: contractId,
5    subscribe: 1,
6    loginid: loginId // Optional for multi-token
7  };
8
9  ws.send(JSON.stringify(request));
10
11  ws.onmessage = (event) => {
12    const response = JSON.parse(event.data);
13    if (response.msg_type === 'proposal_open_contract') {
14      const contract = response.proposal_open_contract;
15      
16      // Numeric fields are always numbers
17      const profit = contract.profit;
18      const payout = contract.payout;
19      
20      // Display value available
21      const displayValue = contract.display_value;
22      
23      // Sell spot for sold contracts
24      const sellSpot = contract.sell_spot;
25    }
26  };
27}

New Implementation

1async function getOpenContract(contractId) {
2  const request = {
3    proposal_open_contract: 1,
4    contract_id: contractId,
5    subscribe: 1
6    // loginid no longer supported
7  };
8
9  ws.send(JSON.stringify(request));
10
11  ws.onmessage = (event) => {
12    const response = JSON.parse(event.data);
13    if (response.msg_type === 'proposal_open_contract') {
14      const contract = response.proposal_open_contract;
15      
16      // Handle string or number types
17      const profit = Number(contract.profit);
18      const payout = Number(contract.payout);
19      
20      // display_value removed - format manually
21      const displayValue = payout.toFixed(2);
22      
23      // Use exit_spot instead of sell_spot
24      const exitSpot = contract.exit_spot;
25    }
26  };
27}

TypeScript type handling

Legacy Types

1interface ProposalOpenContract {
2  contract_id: number;
3  contract_type: string;
4  currency: string;
5  buy_price: number;
6  bid_price: number;
7  current_spot: number;
8  payout: number;
9  profit: number;
10  sell_spot?: number;
11  display_value?: string;
12  is_forward_starting?: 0 | 1;
13  // ... other fields
14}

New Types

1interface ProposalOpenContract {
2  // Now required fields
3  contract_id: number;
4  contract_type: string;
5  currency: string;
6  
7  // Fields can be string or number
8  buy_price: string | number;
9  bid_price: string | number;
10  current_spot: string | number;
11  payout: string; // Always string now
12  profit: string | number;
13  
14  // New fields replace deprecated ones
15  exit_spot?: string | null;
16  exit_spot_time?: number | null;
17  entry_spot_time?: number | null;
18  underlying_symbol?: string;
19  // ... other fields
20}
21
22// Helper to safely parse numeric fields
23function toNumber(value: string | number): number {
24  return typeof value === 'string' 
25    ? parseFloat(value) 
26    : value;
27}