trade-republic-uapi 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 4strium
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,429 @@
1
+ Metadata-Version: 2.4
2
+ Name: trade-republic-uapi
3
+ Version: 1.0.0
4
+ Summary: Lightweight & Fast unofficial REST API for Trade Republic
5
+ Author: 4strium
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/4strium/trade-republic-uapi
8
+ Project-URL: Repository, https://github.com/4strium/trade-republic-uapi
9
+ Keywords: trade-republic,api,unofficial,fastapi,fintech
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Office/Business :: Financial
20
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: fastapi==0.140.0
25
+ Requires-Dist: httpx==0.28.1
26
+ Requires-Dist: playwright==1.61.0
27
+ Requires-Dist: prompt_toolkit==3.0.52
28
+ Requires-Dist: pydantic==2.13.4
29
+ Requires-Dist: qrcode==8.2
30
+ Requires-Dist: questionary==2.1.1
31
+ Requires-Dist: rich==15.0.0
32
+ Requires-Dist: uvicorn==0.51.0
33
+ Requires-Dist: websockets==16.1.1
34
+ Dynamic: license-file
35
+
36
+ # Trade Republic Unofficial API
37
+
38
+ > ⚠️ **Disclaimer**: this project is **not affiliated with Trade Republic Bank GmbH**. Use it at your own risk, especially for endpoints that place real orders.
39
+
40
+ <p align="center">
41
+ <img src="https://github.com/4strium/trade-republic-uapi/blob/main/ressources/TradeRepublicUAPI_demo.gif?raw=true" width="80%" alt="CLI demonstration">
42
+ </p>
43
+
44
+ Lightweight & Fast unofficial REST API for Trade Republic
45
+
46
+ ## How it works
47
+
48
+ 1. The main program launches a headless Chromium browser and guides you through the official Trade Republic login flow.
49
+ 2. Once authenticated, it starts a local FastAPI server in the background, reusing that authenticated session to call Trade Republic's private REST and WebSocket APIs.
50
+ 3. You then interact with your own account through simple, well-documented HTTP endpoints exposed by that local server.
51
+
52
+ ## Install and start the API server
53
+
54
+ ### Option 1: via pip (recommended)
55
+ ```bash
56
+ pip install trade-republic-uapi
57
+ traderep-uapi
58
+ ```
59
+
60
+ ### Option 2: from source (development)
61
+ ```bash
62
+ python3 -m venv .venv
63
+ source .venv/bin/activate
64
+ pip install -r requirements.txt
65
+ python3 -m trade_republic_uapi.cli
66
+ ```
67
+
68
+ Follow the on-screen instructions to scan the QR code with the Trade Republic app. Once authenticated, the API server starts automatically.
69
+
70
+ ## Interactive API documentation
71
+
72
+ Once the server is running, interactive documentation where you can browse every endpoint, see the request/response schemas, try requests live, and view example payloads is available at:
73
+
74
+ - Swagger UI: `http://127.0.0.1:8000/docs`
75
+ - ReDoc: `http://127.0.0.1:8000/redoc`
76
+ - Raw OpenAPI schema: `http://127.0.0.1:8000/openapi.json`
77
+
78
+ ## Endpoints reference
79
+
80
+ All endpoints are served from the base URL of your running instance (e.g. `http://127.0.0.1:8000`). `GET` endpoints take no body; `POST` endpoints take a JSON body as described.
81
+
82
+ | Method | Path | Tag | Description | Body schema |
83
+ |--------|--------------------------|--------------|----------------------------------------------------------------------------|---------------------------|
84
+ | GET | `/api/personal-details` | Account | Personal details + banking info (IBAN/BIC) of the customer | — |
85
+ | GET | `/api/tickets` | Account | Open and closed support tickets | — |
86
+ | GET | `/api/card` | Card | Debit card details (status, cardholder, security settings...) | — |
87
+ | GET | `/api/interests` | Account | Interest rate applied to cash in the default account | — |
88
+ | GET | `/api/orders` | Orders | Last 500 orders per securities account | — |
89
+ | GET | `/api/transactions` | Account | Last 500 timeline transactions (trades, dividends, payments...) | — |
90
+ | GET | `/api/portfolio` | Portfolio | Current positions per account, enriched with stock details | — |
91
+ | GET | `/api/accounts` | Account | Accounts with cash balances (`cashAmount`, `availableCashAmount`) | — |
92
+ | GET | `/api/price-alarms` | Price Alarms | List all configured price alarms | — |
93
+ | GET | `/api/accounts-activity` | Account | Timeline activity log (logins, actions...) | — |
94
+ | POST | `/api/schedule-exchange` | Instruments | Trading schedule of an exchange | [`ExchangeSymbol`](#exchangesymbol) |
95
+ | POST | `/api/accounts-history` | Portfolio | Historical portfolio value per account, over a time range | [`AccountHistoryRequest`](#accounthistoryrequest) |
96
+ | POST | `/api/instrument-history`| Instruments | Historical price series of an instrument, over a time range | [`InstrumentHistory`](#instrumenthistory) |
97
+ | POST | `/api/instrument` | Instruments | General details about an instrument (name, type, exchanges...) | [`Instrument`](#instrument) |
98
+ | POST | `/api/tr-instrument` | Instruments | Trade Republic's home exchange for an instrument | [`Instrument`](#instrument) |
99
+ | POST | `/api/order-price` | Orders | Live buy/sell price quote for an instrument | [`OrderPrice`](#orderprice) |
100
+ | POST | `/api/order-fees` | Orders | Simulates an order and returns its fees (no order is placed) | [`Order`](#order) (`validity` optional) |
101
+ | POST | `/api/place-order` | Orders | **Places a real order** ⚠️ | [`Order`](#order) (`validity` required) |
102
+ | POST | `/api/cancel-order` | Orders | Cancels an open order | [`OrderId`](#orderid) |
103
+ | POST | `/api/set-price-alarm` | Price Alarms | Creates a new price alarm | [`PriceAlarm`](#pricealarm) |
104
+ | POST | `/api/delete-price-alarm`| Price Alarms | Deletes an existing price alarm | [`PriceAlarmId`](#pricealarmid) |
105
+
106
+ ### Schemas
107
+
108
+ #### ExchangeSymbol
109
+ ```jsonc
110
+ { "symbol": "XETR" } // one of: LSX, TDG, TIB, XETR, XMIL, XPAR, XWBO
111
+ ```
112
+
113
+ #### InstrumentHistory
114
+ ```jsonc
115
+ { "id": "US0378331005", "range": "1m" } // range: 1d, 5d, 1m, 1y, max
116
+ ```
117
+
118
+ #### Instrument
119
+ ```jsonc
120
+ { "id": "US0378331005" } // ISIN
121
+ ```
122
+
123
+ #### AccountHistoryRequest
124
+ ```jsonc
125
+ { "range": "1y" } // range: 1d, 5d, 1m, 1y, max
126
+ ```
127
+
128
+ #### OrderPrice
129
+ ```jsonc
130
+ { "exchange": "XETR", "instrument": "US0378331005" }
131
+ ```
132
+
133
+ #### Order
134
+ ```jsonc
135
+ {
136
+ "account_nb": "DE1234567890123456",
137
+ "exchange": "XETR",
138
+ "instrument": "US0378331005",
139
+ "mode": "limit", // stopMarket, market, limit
140
+ "quantity": 10,
141
+ "stop": null, // required if mode = stopMarket
142
+ "limit": 145.5, // required if mode = limit
143
+ "type": "buy", // buy, sell
144
+ "validity": "GTC" // GFD, GTD, GTC — required for /api/place-order
145
+ }
146
+ ```
147
+
148
+ #### OrderId
149
+ ```jsonc
150
+ { "orderId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }
151
+ ```
152
+
153
+ #### PriceAlarm
154
+ ```jsonc
155
+ { "instrument": "US0378331005", "targetPrice": 180.0 }
156
+ ```
157
+
158
+ #### PriceAlarmId
159
+ ```jsonc
160
+ { "alarmId": "9f8e7d6c-5b4a-3210-fedc-ba0987654321" }
161
+ ```
162
+
163
+ ## Usage examples
164
+
165
+ The examples below use fictitious values (fake ISIN, account number, order IDs). Replace them with your own data. All examples assume the server runs on `http://127.0.0.1:8000`.
166
+
167
+ ### curl
168
+
169
+ ```bash
170
+ # Personal details
171
+ curl -s -X GET "http://127.0.0.1:8000/api/personal-details"
172
+
173
+ # Support tickets
174
+ curl -s -X GET "http://127.0.0.1:8000/api/tickets"
175
+
176
+ # Debit card details
177
+ curl -s -X GET "http://127.0.0.1:8000/api/card"
178
+
179
+ # Interest rate on cash
180
+ curl -s -X GET "http://127.0.0.1:8000/api/interests"
181
+
182
+ # Orders per account
183
+ curl -s -X GET "http://127.0.0.1:8000/api/orders"
184
+
185
+ # Transactions timeline
186
+ curl -s -X GET "http://127.0.0.1:8000/api/transactions"
187
+
188
+ # Portfolio positions
189
+ curl -s -X GET "http://127.0.0.1:8000/api/portfolio"
190
+
191
+ # Accounts + cash balances
192
+ curl -s -X GET "http://127.0.0.1:8000/api/accounts"
193
+
194
+ # Price alarms
195
+ curl -s -X GET "http://127.0.0.1:8000/api/price-alarms"
196
+
197
+ # Account activity log
198
+ curl -s -X GET "http://127.0.0.1:8000/api/accounts-activity"
199
+
200
+ # Exchange trading schedule
201
+ curl -s -X POST "http://127.0.0.1:8000/api/schedule-exchange" \
202
+ -H "Content-Type: application/json" \
203
+ -d '{"symbol": "XETR"}'
204
+
205
+ # Portfolio value history
206
+ curl -s -X POST "http://127.0.0.1:8000/api/accounts-history" \
207
+ -H "Content-Type: application/json" \
208
+ -d '{"range": "1y"}'
209
+
210
+ # Instrument price history
211
+ curl -s -X POST "http://127.0.0.1:8000/api/instrument-history" \
212
+ -H "Content-Type: application/json" \
213
+ -d '{"id": "US0378331005", "range": "1m"}'
214
+
215
+ # Global instrument details
216
+ curl -s -X POST "http://127.0.0.1:8000/api/instrument" \
217
+ -H "Content-Type: application/json" \
218
+ -d '{"id": "US0378331005"}'
219
+
220
+ # Trade Republic home exchange for an instrument
221
+ curl -s -X POST "http://127.0.0.1:8000/api/tr-instrument" \
222
+ -H "Content-Type: application/json" \
223
+ -d '{"id": "US0378331005"}'
224
+
225
+ # Live order price (buy/sell quote)
226
+ curl -s -X POST "http://127.0.0.1:8000/api/order-price" \
227
+ -H "Content-Type: application/json" \
228
+ -d '{"exchange": "XETR", "instrument": "US0378331005", "unit": "EUR"}'
229
+
230
+ # Get order fees
231
+ curl -s -X POST "http://127.0.0.1:8000/api/order-fees" \
232
+ -H "Content-Type: application/json" \
233
+ -d '{
234
+ "account_nb": "DE1234567890123456",
235
+ "exchange": "XETR",
236
+ "instrument": "US0378331005",
237
+ "mode": "limit",
238
+ "quantity": 10,
239
+ "limit": 145.5,
240
+ "type": "buy"
241
+ }'
242
+
243
+ # Place a real order ⚠️
244
+ curl -s -X POST "http://127.0.0.1:8000/api/place-order" \
245
+ -H "Content-Type: application/json" \
246
+ -d '{
247
+ "account_nb": "DE1234567890123456",
248
+ "exchange": "XETR",
249
+ "instrument": "US0378331005",
250
+ "mode": "limit",
251
+ "quantity": 10,
252
+ "limit": 145.5,
253
+ "type": "buy",
254
+ "validity": "GTC"
255
+ }'
256
+
257
+ # Cancel an order
258
+ curl -s -X POST "http://127.0.0.1:8000/api/cancel-order" \
259
+ -H "Content-Type: application/json" \
260
+ -d '{"orderId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}'
261
+
262
+ # Create a price alarm
263
+ curl -s -X POST "http://127.0.0.1:8000/api/set-price-alarm" \
264
+ -H "Content-Type: application/json" \
265
+ -d '{"instrument": "US0378331005", "targetPrice": 180.0}'
266
+
267
+ # Delete a price alarm
268
+ curl -s -X POST "http://127.0.0.1:8000/api/delete-price-alarm" \
269
+ -H "Content-Type: application/json" \
270
+ -d '{"alarmId": "9f8e7d6c-5b4a-3210-fedc-ba0987654321"}'
271
+ ```
272
+
273
+ ### Python
274
+
275
+ Using the [`requests`](https://pypi.org/project/requests/) library (`pip install requests`):
276
+
277
+ ```python
278
+ import requests
279
+
280
+ BASE_URL = "http://127.0.0.1:8000"
281
+
282
+ # --- Simple GET endpoints -------------------------------------------------
283
+ portfolio = requests.get(f"{BASE_URL}/api/portfolio").json()
284
+ accounts = requests.get(f"{BASE_URL}/api/accounts").json()
285
+ print(portfolio, accounts)
286
+
287
+ # --- Get the live price of an instrument ----------------------------------
288
+ price = requests.post(
289
+ f"{BASE_URL}/api/order-price",
290
+ json={
291
+ "exchange": "XETR",
292
+ "instrument": "US0378331005", # fictitious ISIN
293
+ "unit": "EUR",
294
+ },
295
+ ).json()
296
+ print("Sell price:", price["sell"])
297
+ print("Buy price:", price["buy"])
298
+
299
+ # --- Simulate an order and check its fees before placing it ---------------
300
+ order_payload = {
301
+ "account_nb": "DE1234567890123456", # fictitious securities account number
302
+ "exchange": "XETR",
303
+ "instrument": "US0378331005",
304
+ "mode": "limit",
305
+ "quantity": 10,
306
+ "limit": 145.5,
307
+ "type": "buy",
308
+ }
309
+ fees_response = requests.post(f"{BASE_URL}/api/order-fees", json=order_payload)
310
+ fees_response.raise_for_status()
311
+ print("Estimated fees:", fees_response.json())
312
+
313
+ # --- Place a real order (validity is required) ⚠️ --------------------------
314
+ order_payload["validity"] = "GTC"
315
+ place_response = requests.post(f"{BASE_URL}/api/place-order", json=order_payload)
316
+ if place_response.status_code == 200:
317
+ print("Order placed:", place_response.json())
318
+ else:
319
+ print("Error placing order:", place_response.status_code, place_response.json())
320
+
321
+ # --- Create and then delete a price alarm ----------------------------------
322
+ alarm = requests.post(
323
+ f"{BASE_URL}/api/set-price-alarm",
324
+ json={"instrument": "US0378331005", "targetPrice": 180.0},
325
+ ).json()
326
+ print("Alarm created:", alarm)
327
+
328
+ requests.post(
329
+ f"{BASE_URL}/api/delete-price-alarm",
330
+ json={"alarmId": "9f8e7d6c-5b4a-3210-fedc-ba0987654321"},
331
+ )
332
+ ```
333
+
334
+ ### Rust
335
+
336
+ Using [`reqwest`](https://crates.io/crates/reqwest) and [`serde_json`](https://crates.io/crates/serde_json). Add to `Cargo.toml`:
337
+
338
+ ```toml
339
+ [dependencies]
340
+ reqwest = { version = "0.12", features = ["json", "blocking"] }
341
+ serde_json = "1"
342
+ ```
343
+
344
+ ```rust
345
+ use reqwest::blocking::Client;
346
+ use serde_json::json;
347
+
348
+ const BASE_URL: &str = "http://127.0.0.1:8000";
349
+
350
+ fn main() -> Result<(), Box<dyn std::error::Error>> {
351
+ let client = Client::new();
352
+
353
+ // --- Simple GET endpoints ---------------------------------------------
354
+ let portfolio: serde_json::Value = client
355
+ .get(format!("{BASE_URL}/api/portfolio"))
356
+ .send()?
357
+ .json()?;
358
+ println!("Portfolio: {portfolio}");
359
+
360
+ let accounts: serde_json::Value = client
361
+ .get(format!("{BASE_URL}/api/accounts"))
362
+ .send()?
363
+ .json()?;
364
+ println!("Accounts: {accounts}");
365
+
366
+ // --- Get the live price of an instrument -------------------------------
367
+ let price: serde_json::Value = client
368
+ .post(format!("{BASE_URL}/api/order-price"))
369
+ .json(&json!({
370
+ "exchange": "XETR",
371
+ "instrument": "US0378331005", // fictitious ISIN
372
+ "unit": "EUR"
373
+ }))
374
+ .send()?
375
+ .json()?;
376
+ println!("Sell price: {}", price["sell"]);
377
+ println!("Buy price: {}", price["buy"]);
378
+
379
+ // --- Simulate an order and check its fees before placing it -----------
380
+ let mut order_payload = json!({
381
+ "account_nb": "DE1234567890123456", // fictitious securities account number
382
+ "exchange": "XETR",
383
+ "instrument": "US0378331005",
384
+ "mode": "limit",
385
+ "quantity": 10,
386
+ "limit": 145.5,
387
+ "type": "buy"
388
+ });
389
+
390
+ let fees: serde_json::Value = client
391
+ .post(format!("{BASE_URL}/api/order-fees"))
392
+ .json(&order_payload)
393
+ .send()?
394
+ .json()?;
395
+ println!("Estimated fees: {fees}");
396
+
397
+ // --- Place a real order (validity is required) ⚠️ -----------------------
398
+ order_payload["validity"] = json!("GTC");
399
+ let response = client
400
+ .post(format!("{BASE_URL}/api/place-order"))
401
+ .json(&order_payload)
402
+ .send()?;
403
+
404
+ if response.status().is_success() {
405
+ println!("Order placed: {:?}", response.json::<serde_json::Value>()?);
406
+ } else {
407
+ println!(
408
+ "Error placing order ({}): {:?}",
409
+ response.status(),
410
+ response.json::<serde_json::Value>()?
411
+ );
412
+ }
413
+
414
+ // --- Create and then delete a price alarm ------------------------------
415
+ let alarm: serde_json::Value = client
416
+ .post(format!("{BASE_URL}/api/set-price-alarm"))
417
+ .json(&json!({ "instrument": "US0378331005", "targetPrice": 180.0 }))
418
+ .send()?
419
+ .json()?;
420
+ println!("Alarm created: {alarm}");
421
+
422
+ client
423
+ .post(format!("{BASE_URL}/api/delete-price-alarm"))
424
+ .json(&json!({ "alarmId": "9f8e7d6c-5b4a-3210-fedc-ba0987654321" }))
425
+ .send()?;
426
+
427
+ Ok(())
428
+ }
429
+ ```