1+ import os
2+ import sys
3+ import httpx
4+ from dotenv import load_dotenv
5+
6+ def authenticate_rdp (machine_id , password , app_key , url ) -> dict :
7+ """Authenticate to RDP and return the token response as JSON."""
8+
9+ # Build the OAuth 2.0 Password Grant request payload.
10+ # Sent as application/x-www-form-urlencoded (httpx encodes a dict automatically).
11+ payload = {
12+ "username" : machine_id , # RDP Machine-ID
13+ "password" : password , # RDP Password
14+ "grant_type" : "password" , # OAuth 2.0 grant type
15+ "scope" : "trapi" , # Target API scope
16+ "takeExclusiveSignOnControl" : "true" , # Revoke other active sessions
17+ "client_id" : app_key # RDP AppKey (acts as client_id)
18+ }
19+
20+ # Send authentication request to the OAuth token endpoint.
21+ # `data=payload` sends a form body required by this endpoint.
22+ # `verify=False` skips SSL verification (for local/dev only).
23+ response = httpx .post (url , data = payload , verify = False )
24+ response .raise_for_status () # Raise an exception for 4xx/5xx HTTP errors
25+ return response .json ()
26+
27+ def get_chain (ric , token , url ):
28+ """Fetch chain data for a single RIC symbol using an access token."""
29+ # Bearer token is required for authorized API requests.
30+ headers = {
31+ "Authorization" : f"Bearer { token } " ,
32+ "Content-Type" : "application/json"
33+ }
34+ # Query string parameters sent with the GET request.
35+ parameters = {
36+ "universe" : ric
37+ }
38+ # Request chain data from the pricing chains endpoint.
39+ response = httpx .get (url , params = parameters , headers = headers , verify = False )
40+ response .raise_for_status ()
41+ return response .json ()
42+
43+ def post_historical_event (rics , token , url ):
44+ """Request historical event data for multiple RICs."""
45+ # Send the token in Authorization header for API access.
46+ headers = {
47+ "Authorization" : f"Bearer { token } " ,
48+ "Content-Type" : "application/json"
49+ }
50+ # JSON body for the historical pricing events request.
51+ payload = {
52+ "universe" : rics ,
53+ "eventTypes" : ["trade" ]
54+ }
55+
56+ # `json=payload` serializes and sends JSON in the request body.
57+ response = httpx .post (url , json = payload , headers = headers , verify = False )
58+ response .raise_for_status ()
59+ return response .json ()
60+
61+ def main () -> None :
62+ """Run the end-to-end demo: auth, chain data, and historical events."""
63+ # Load key/value pairs from src/.env into process environment.
64+ load_dotenv ()
65+
66+ # Read credentials and base URL from environment variables.
67+ machine_id = os .getenv ("MACHINEID_RDP" )
68+ password = os .getenv ("PASSWORD_RDP" )
69+ app_key = os .getenv ("APPKEY_RDP" )
70+ base_url = os .getenv ("BASE_URL_RDP" ) # Default to Refinitiv API base URL if not set
71+
72+ # OAuth token endpoint used to obtain access token.
73+ url = f"{ base_url } /auth/oauth2/v1/token"
74+
75+ try :
76+ token_data = authenticate_rdp (machine_id , password , app_key , url )
77+ print ("Authentication successful! Status code: 200" )
78+ # For demos only: print token to verify auth worked.
79+ print (token_data ["access_token" ])
80+ except httpx .HTTPStatusError as e :
81+ # HTTP error response received (e.g. 400 Bad Request, 401 Unauthorized)
82+ print (f"HTTP error: { e .response .status_code } - { e .response .text } " )
83+ except httpx .RequestError as e :
84+ # Network-level error (e.g. connection refused, DNS failure, timeout)
85+ print (f"Request error: { e } " )
86+
87+ # Continue only when an access token is available.
88+ if token_data ["access_token" ]:
89+
90+ print ("Access token received successfully." )
91+ # Example single RIC lookup for chain endpoint using HTTP GET.
92+ RIC = "KIBOR="
93+ chain_url = f"{ base_url } /data/pricing/chains/v1/"
94+ try :
95+ print (f"Fetching chain data... for RIC: { RIC } " )
96+ chain_data = get_chain (RIC , token_data ["access_token" ], chain_url )
97+ print ("Chain data retrieved successfully!" )
98+ print (chain_data )
99+ except httpx .HTTPStatusError as e :
100+ print (f"HTTP error while fetching chain data: { e .response .status_code } - { e .response .text } " )
101+ except httpx .RequestError as e :
102+ print (f"Request error while fetching chain data: { e } " )
103+
104+ # Example multi-RIC request for historical events endpoint using HTTP POST.
105+ RICs = ["LSEG.L" ,"VOD.L" ,"BP.L" ]
106+ historical_event_url = f"{ base_url } /data/historical-pricing/v1/views/events"
107+ try :
108+ print (f"Posting historical event data... for RICs: { RICs } " )
109+ historical_event_data = post_historical_event (RICs , token_data ["access_token" ], historical_event_url )
110+ print ("Historical event data posted successfully!" )
111+ print (historical_event_data )
112+ except httpx .HTTPStatusError as e :
113+ print (f"HTTP error while posting historical event data: { e .response .status_code } - { e .response .text } " )
114+ except httpx .RequestError as e :
115+ print (f"Request error while posting historical event data: { e } " )
116+ else :
117+ print ("Failed to receive access token. Exiting..." )
118+ sys .exit (1 )
119+
120+
121+ if __name__ == "__main__" :
122+ main ()
0 commit comments