You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Data Platform APIs HTTP REST Application using Httpx
2
+
3
+
- Version: 1.0
4
+
- Last update: Mar 2026
5
+
- Environment: Python + JupyterLab + Data Platform Account
6
+
- Prerequisite: Data Platform access/entitlements
7
+
8
+
## Overview
9
+
10
+
The [Requests](https://requests.readthedocs.io/en/latest/) library is widely regarded as *the de facto* standard HTTP client for Python applications. Many Python developers first learn REST API calls through Requests — including through our [Data Platform APIs Tutorials](https://developers.lseg.com/en/api-catalog/refinitiv-data-platform/refinitiv-data-platform-apis/tutorials) (or you can try RDP HTTP operations with the [built-in http.client](https://docs.python.org/3/library/http.client.html) if you enjoy a challenge.).
11
+
12
+
That said, there are other Python HTTP libraries worth considering — [HTTPX](https://www.python-httpx.org/), [Aiohttp](https://docs.aiohttp.org/en/stable/), [Urllib3](https://urllib3.readthedocs.io/en/stable/), [Grequests](https://pypi.org/project/grequests/), [PycURL](http://pycurl.io/docs/latest/index.html), and more — each offering different trade-offs in performance and features that may better suit your requirements.
13
+
14
+
I was drawn to HTTPX because it provides a **requests-compatible API** while also supporting **asynchronous operations** out of the box. That combination made migrating from Requests to HTTPX straightforward, with the added benefit of async support when needed.
15
+
16
+
This project demonstrates how to use [`httpx`](https://www.python-httpx.org/) to authenticate and retrieve data from [LSEG Data Platform APIs](https://developers.lseg.com/en/api-catalog/refinitiv-data-platform/refinitiv-data-platform-apis) via HTTP endpoints — covering both synchronous and asynchronous patterns for comparison.
17
+
18
+
**Note**: A basic knowledge of Python [built-in asyncio](https://docs.python.org/3/library/asyncio.html) library is required to understand example codes.
Interactive notebook version of the synchronous workflow. Each logical step is a separate cell with a markdown explanation above it, making it easy to run and inspect results incrementally.
25
+
26
+
Demonstrates:
27
+
-`POST /auth/oauth2/v1/token` — OAuth 2.0 Password Grant authentication
28
+
-`GET /data/historical-pricing/v1/views/interday-summaries/{ric}` — daily OHLCV data with corporate-action adjustments for 10 RICs
29
+
-`POST /auth/oauth2/v1/revoke` — session token revocation using HTTP Basic Auth
30
+
- Shared `httpx.Client` inside a `with` block for clean connection-pool teardown
Interactive notebook version of the async concurrent workflow using `httpx.AsyncClient` and `asyncio.gather()`. Jupyter's native top-level `await` support means no `asyncio.run()` wrapper is needed.
44
+
45
+
Demonstrates:
46
+
-`POST /auth/oauth2/v1/token` — async OAuth 2.0 Password Grant authentication
47
+
-`GET /data/historical-pricing/v1/views/interday-summaries/{ric}` — daily OHLCV data fetched concurrently for 10 RICs
48
+
-`asyncio.Semaphore` — caps concurrent in-flight requests (default: 3) to respect server rate limits
49
+
-`asyncio.gather(return_exceptions=True)` — all RIC coroutines run simultaneously; one failure does not cancel the rest
### `src/example_async_gather.py` — Async with `asyncio.gather()` and `Semaphore`
65
+
66
+
Async script that fires all RIC requests concurrently via `asyncio.gather()`, with an `asyncio.Semaphore` to cap the number of in-flight requests and avoid hitting server rate limits.
- Environment validation with a `_require_env()` helper that fails fast on missing credentials
86
+
87
+
## Security Notes
88
+
89
+
- All examples use `verify=False` to disable TLS certificate verification. This is intended for local/dev environments only (e.g. where a TLS-inspecting proxy such as ZScaler is in use). Remove `verify=False` or supply a proper CA bundle for production use.
90
+
- Do not log or print access tokens in production applications.
Copy file name to clipboardExpand all lines: README.md
+14-95Lines changed: 14 additions & 95 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -115,6 +115,8 @@ if __name__ == "__main__":
115
115
116
116
If the HTTP request takes 60 seconds, the program idles for those 60 seconds before executing the next line. For a single request this is fine, but it becomes a bottleneck when you need to fetch data for many symbols or endpoints.
117
117
118
+

119
+
118
120
On the other hand, **Asynchronous** code allows multiple tasks to run concurrently in a non-blocking manner. While one task is waiting for I/O (such as a network response), the event loop can hand control to another task (execute next line of codes) instead of sitting idle. The example below uses `asyncio.create_task()` to launch a fetch in the background and immediately continues to the next line — without waiting for the response:
The real payoff of async comes when you have **many requests to make**. With `asyncio.gather()`, you can fire all of them concurrently so the total wall-clock time is roughly that of the single slowest response — instead of the sum of all response times. That is exactly the pattern used in `example_async_gather.py` and `async_call_nb.ipynb` examples for fetching multiple RICs.
144
148
145
149
## Prerequisites
146
150
147
-
- Python 3.11+ (required for `asyncio.TaskGroup` and `except*`)
151
+
- Python 3.11+
148
152
- LSEG Data Platform credentials with Historical Pricing permission:
149
153
- Machine ID
150
154
- Password
151
155
- AppKey
152
156
153
-
If you do not have access yet, contact your LSEG representative or account manager.
157
+
Please your LSEG representative or account manager for the Data Platform Access
Interactive notebook version of the synchronous workflow. Each logical step is a separate cell with a markdown explanation above it, making it easy to run and inspect results incrementally.
173
-
174
-
Demonstrates:
175
-
-`POST /auth/oauth2/v1/token` — OAuth 2.0 Password Grant authentication
176
-
-`GET /data/historical-pricing/v1/views/interday-summaries/{ric}` — daily OHLCV data with corporate-action adjustments for 10 RICs
177
-
-`POST /auth/oauth2/v1/revoke` — session token revocation using HTTP Basic Auth
178
-
- Shared `httpx.Client` inside a `with` block for clean connection-pool teardown
Interactive notebook version of the async concurrent workflow using `httpx.AsyncClient` and `asyncio.gather()`. Jupyter's native top-level `await` support means no `asyncio.run()` wrapper is needed.
192
-
193
-
Demonstrates:
194
-
-`POST /auth/oauth2/v1/token` — async OAuth 2.0 Password Grant authentication
195
-
-`GET /data/historical-pricing/v1/views/interday-summaries/{ric}` — daily OHLCV data fetched concurrently for 10 RICs
196
-
-`asyncio.Semaphore` — caps concurrent in-flight requests (default: 3) to respect server rate limits
197
-
-`asyncio.gather(return_exceptions=True)` — all RIC coroutines run simultaneously; one failure does not cancel the rest
### `src/example_async_gather.py` — Async with `asyncio.gather()` and `Semaphore`
213
-
214
-
Async script that fires all RIC requests concurrently via `asyncio.gather()`, with an `asyncio.Semaphore` to cap the number of in-flight requests and avoid hitting server rate limits.
- Environment validation with a `_require_env()` helper that fails fast on missing credentials
234
-
235
-
### `src/example_sync_httpx.py` — Synchronous, direct `httpx` calls
236
-
237
-
Simplest synchronous example. Each function calls `httpx.get()` / `httpx.post()` directly — no shared client or connection pool. Good as a minimal reference or quick script.
238
-
239
-
Demonstrates:
240
-
-`POST /auth/oauth2/v1/token` — OAuth 2.0 Password Grant authentication
241
-
-`GET /data/pricing/chains/v1/` — chain constituent lookup for a single RIC
242
-
-`POST /data/historical-pricing/v1/views/events` — historical trade events for multiple RICs
243
-
- Refresh token flow (`grant_type=refresh_token`)
244
-
-`POST /auth/oauth2/v1/revoke` — session revocation using HTTP Basic Auth
245
-
- Per-call `verify=False` passed directly to each `httpx` function
246
-
247
-
248
-
249
-
## Setup
174
+
## Project Setup
250
175
251
176
1. Create and activate a virtual environment.
252
177
@@ -261,7 +186,7 @@ python -m venv .venv
261
186
pip install -r requirements.txt
262
187
```
263
188
264
-
3. Create your environment file by creating `src/.env` with the following content:
189
+
3. Create your environment file by creating `src/.env` with the following content (see `src/.env.example` file):
0 commit comments