Deriv API

Proposal

Trading

Get contract pricing and proposal. Major changes to parameter structure and response format.

Quick comparison

AspectLegacyNewAction required
Endpoint
✅ Same
proposalproposalNone
Auth Required
✅ Same
NoNoNone
symbol parameter
✏️ Renamed
symbolunderlying_symbolRename in requests
loginid parameter
❌ Removed
OptionalRemovedRemove from requests
barrier_range parameter
❌ Removed
AvailableRemovedRemove from requests
product_type parameter
❌ Removed
Available (default: basic)RemovedRemove from requests
date_start parameter
❌ Removed
AvailableRemovedRemove from requests
trade_risk_profile parameter
❌ Removed
Available (Snowball)RemovedRemove from requests
trading_period_start parameter
❌ Removed
Available (multi-barrier)RemovedRemove from requests
subscribe parameter
⚠️ Changed
Only 10 or 1None (expanded)
contract_type validation
⚠️ Changed
Strict enum (33 values)Any stringNone (relaxed)
Response proposal object
⚠️ Changed
OptionalRequiredUpdate response handling
Response echo_req
⚠️ Changed
RequiredOptionalAdd null checks if needed
Proposal required fields
⚠️ Changed
8 fields requiredOnly id requiredAdd null checks for other fields
ask_price/payout types
⚠️ Changed
numbernumber | stringHandle both types

Breaking changes

1. Symbol parameter renamed

What Changed: The symbol parameter has been renamed to underlying_symbol.

Migration Action: Update all requests to use underlying_symbol instead of symbol.

2. LoginID parameter removed

What Changed: The loginid parameter used for multi-token authorization scenarios has been removed.

Migration Action: Remove loginid from requests. Account context must be managed through the authorization flow.

3. Multiple request parameters removed

What Changed: The following parameters have been removed from the request:

  • barrier_range - for callputspread contracts (tight/middle/wide)
  • product_type - defaulted to "basic"
  • date_start - epoch value for contract start time
  • trade_risk_profile - for Snowball contracts (low/medium/high)
  • trading_period_start - for multi-barrier trading

Migration Action: Remove these parameters from requests. Snowball and callputspread contract functionality may be affected.

4. Contract type validation relaxed

What Changed: The contract_type parameter no longer has a strict enum validation (was 33 specific values). Similarly, basis no longer requires enum values.

Migration Action: None required. This is a relaxation that accepts more values.

5. Subscribe parameter extended

What Changed: The subscribe parameter now accepts both 0 and 1 (was only 1).

Migration Action: None required. This is an expansion of accepted values.

6. Response proposal object now required

What Changed: The proposal object in the response is now required. Previously it was optional.

Migration Action: You can now rely on proposal being present without null checks.

7. Response echo_req no longer required

What Changed: The echo_req field is no longer required in the response (was required in Legacy).

Migration Action: Add null checks if your code relies on echo_req being present.

8. Proposal required fields reduced

What Changed: The proposal object now only requires the id field. Previously, 8 fields were required:ask_price, date_start,display_value, id,longcode, payout,spot, spot_time.

Migration Action: Add null/undefined checks for fields other than id as they may not always be present.

9. Response field types changed

What Changed: Several response fields now accept both numbers and strings:

  • ask_price: was number, now number | string
  • payout: was number, now number | string
  • commission: was null | number, now null | number | string

Migration Action: Update parsing logic to handle both number and string values for these fields.

10. Snowball contract fields removed

What Changed: Snowball-specific fields have been removed from the contract_details response:

  • caution_price
  • coupon_rate
  • num_of_coupons
  • profit_price
  • trade_risk_profile

Migration Action: Remove any code that relies on these Snowball-specific response fields.

Request structure

Legacy Request Example

1// Required: proposal, contract_type, currency, symbol
2{
3  "proposal": 1,
4  "amount": 10,
5  "basis": "stake",  // enum: payout, stake
6  "contract_type": "CALL",  // enum: 33 specific values
7  "currency": "USD",
8  "duration": 5,
9  "duration_unit": "m",
10  "symbol": "frxEURUSD",  // ❌ Renamed in New
11  "subscribe": 1,  // Only 1 allowed
12  "loginid": "CR123456",  // ❌ Removed in New
13  "barrier_range": "middle",  // ❌ Removed in New
14  "product_type": "basic",  // ❌ Removed in New
15  "date_start": 1699564800  // ❌ Removed in New
16}

New Request Example

1// Required: proposal, contract_type, currency, underlying_symbol
2{
3  "proposal": 1,
4  "amount": 10,
5  "basis": "stake",  // No enum restriction
6  "contract_type": "CALL",  // No enum restriction
7  "currency": "USD",
8  "duration": 5,
9  "duration_unit": "m",
10  "underlying_symbol": "frxEURUSD",  // ✅ Renamed from symbol
11  "subscribe": 1  // 0 or 1 allowed
12  // loginid, barrier_range, product_type, date_start removed
13}

Note: Parameters trade_risk_profile and trading_period_start (for Snowball and multi-barrier contracts) have also been removed.

Response structure

Legacy Response Example

1// Root required: echo_req, msg_type
2// proposal object: OPTIONAL
3// proposal required fields: 8 (ask_price, date_start,
4//   display_value, id, longcode, payout, spot, spot_time)
5{
6  "proposal": {
7    "ask_price": 10.50,  // type: number
8    "date_start": 1699564800,  // REQUIRED
9    "display_value": "10.50",  // REQUIRED
10    "id": "proposal-id-123",  // REQUIRED
11    "longcode": "Win payout if...",  // REQUIRED
12    "payout": 20.00,  // type: number, REQUIRED
13    "spot": 1.0850,  // REQUIRED
14    "spot_time": 1234567890  // REQUIRED
15  },
16  "echo_req": { ... },  // REQUIRED
17  "msg_type": "proposal",
18  "subscription": { "id": "sub-123" }
19}

New Response Example

1// Root required: proposal, msg_type
2// proposal object: ✅ REQUIRED
3// proposal required fields: only "id"
4{
5  "proposal": {
6    "ask_price": "10.50",  // type: number | string
7    "date_start": 1699564800,  // now optional
8    "display_value": "10.50",  // now optional
9    "id": "proposal-id-123",  // ✅ Only required field
10    "longcode": "Win payout if...",  // now optional
11    "payout": "20.00",  // type: number | string, optional
12    "spot": 1.0850,  // now optional
13    "spot_time": 1234567890  // now optional
14  },
15  "echo_req": { ... },  // now optional
16  "msg_type": "proposal",
17  "subscription": { "id": "sub-123" }
18}

Important: Fields like ask_price and payout may now be strings. Parse them appropriately. Also, only id is guaranteed - add null checks for other fields.

Code examples

Legacy Implementation

1async function getProposal() {
2  const request = {
3    proposal: 1,
4    amount: 10,
5    basis: "stake",
6    contract_type: "CALL",
7    currency: "USD",
8    duration: 5,
9    duration_unit: "m",
10    symbol: "frxEURUSD",  // Use symbol
11    subscribe: 1,
12    loginid: "CR123456"  // For multi-token scenarios
13  };
14
15  ws.send(JSON.stringify(request));
16
17  ws.onmessage = (event) => {
18    const response = JSON.parse(event.data);
19    if (response.msg_type === 'proposal') {
20      // Fields are guaranteed to exist
21      console.log('Price:', response.proposal.ask_price);
22      console.log('Payout:', response.proposal.payout);
23      console.log('Spot:', response.proposal.spot);
24      console.log('ID:', response.proposal.id);
25    }
26  };
27}

New Implementation

1async function getProposal() {
2  const request = {
3    proposal: 1,
4    amount: 10,
5    basis: "stake",
6    contract_type: "CALL",
7    currency: "USD",
8    duration: 5,
9    duration_unit: "m",
10    underlying_symbol: "frxEURUSD",  // Renamed from symbol
11    subscribe: 1
12    // loginid removed - manage via authorization
13  };
14
15  ws.send(JSON.stringify(request));
16
17  ws.onmessage = (event) => {
18    const response = JSON.parse(event.data);
19    if (response.msg_type === 'proposal') {
20      // Only id is guaranteed - add null checks for others
21      // ask_price/payout may be string or number
22      const askPrice = Number(response.proposal.ask_price);
23      const payout = response.proposal.payout 
24        ? Number(response.proposal.payout) 
25        : null;
26      const spot = response.proposal.spot ?? null;
27      console.log('Price:', askPrice);
28      console.log('Payout:', payout);
29      console.log('Spot:', spot);
30      console.log('ID:', response.proposal.id);
31    }
32  };
33}