Proposal
Get contract pricing and proposal. Major changes to parameter structure and response format.
10 breaking changes - code updates required
Critical Changes:
- The
symbolparameter renamed tounderlying_symbol. - Multiple request parameters removed (loginid, barrier_range, product_type, date_start, trade_risk_profile, trading_period_start).
- Response
proposalobject now required; required fields reduced from 8 to justid. - Some response field types changed to accept both numbers and strings.
Quick comparison
| Aspect | Legacy | New | Action required |
|---|---|---|---|
Endpoint ✅ Same | proposal | proposal | None |
Auth Required ✅ Same | No | No | None |
symbol parameter ✏️ Renamed | symbol | underlying_symbol | Rename in requests |
loginid parameter ❌ Removed | Optional | Removed | Remove from requests |
barrier_range parameter ❌ Removed | Available | Removed | Remove from requests |
product_type parameter ❌ Removed | Available (default: basic) | Removed | Remove from requests |
date_start parameter ❌ Removed | Available | Removed | Remove from requests |
trade_risk_profile parameter ❌ Removed | Available (Snowball) | Removed | Remove from requests |
trading_period_start parameter ❌ Removed | Available (multi-barrier) | Removed | Remove from requests |
subscribe parameter ⚠️ Changed | Only 1 | 0 or 1 | None (expanded) |
contract_type validation ⚠️ Changed | Strict enum (33 values) | Any string | None (relaxed) |
Response proposal object ⚠️ Changed | Optional | Required | Update response handling |
Response echo_req ⚠️ Changed | Required | Optional | Add null checks if needed |
Proposal required fields ⚠️ Changed | 8 fields required | Only id required | Add null checks for other fields |
ask_price/payout types ⚠️ Changed | number | number | string | Handle 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 timetrade_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: wasnumber, nownumber | stringpayout: wasnumber, nownumber | stringcommission: wasnull | number, nownull | 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_pricecoupon_ratenum_of_couponsprofit_pricetrade_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}