reportify-sdk 0.2.7__py3-none-any.whl → 0.2.9__py3-none-any.whl

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.
reportify_sdk/stock.py CHANGED
@@ -32,34 +32,70 @@ class StockModule:
32
32
  # Company Information
33
33
  # -------------------------------------------------------------------------
34
34
 
35
- def overview(self, symbol: str) -> dict[str, Any]:
35
+ def overview(
36
+ self, symbols: str | None = None, names: str | None = None
37
+ ) -> dict[str, Any] | list[dict[str, Any]]:
36
38
  """
37
39
  Get company overview including business description, sector, and key metrics
38
40
 
39
41
  Args:
40
- symbol: Stock symbol (e.g., "US:AAPL", "HK:0700", "CN:600519")
42
+ symbols: Stock symbols. You can enter multiple items, separated by commas(,)
43
+ Example: "US:AAPL,US:MSFT"
44
+ names: Stock names. You can enter multiple items, separated by commas(,)
45
+ Example: "Apple Inc.,Microsoft"
41
46
 
42
47
  Returns:
43
- Company information dictionary
48
+ Dictionary or list of dictionaries with company overview data
44
49
 
45
50
  Example:
46
- >>> info = client.stock.overview("US:AAPL")
51
+ >>> # Single stock by symbol
52
+ >>> info = client.stock.overview(symbols="US:AAPL")
47
53
  >>> print(info["name"], info["sector"])
54
+
55
+ >>> # Multiple stocks by symbols
56
+ >>> infos = client.stock.overview(symbols="US:AAPL,US:MSFT")
57
+ >>> for info in infos:
58
+ ... print(info["name"])
59
+
60
+ >>> # Search by name
61
+ >>> info = client.stock.overview(names="Apple Inc.")
48
62
  """
49
- response = self._post("/v1/stock/company-overview", json={"symbol": symbol})
63
+ if not symbols and not names:
64
+ raise ValueError("Either symbols or names must be provided")
65
+
66
+ data = {}
67
+ if symbols:
68
+ data["symbols"] = symbols
69
+ if names:
70
+ data["names"] = names
71
+
72
+ response = self._post("/v1/stock/company-overview", json=data)
50
73
  return response
51
74
 
52
- def shareholders(self, symbol: str) -> list[dict[str, Any]]:
75
+ def shareholders(
76
+ self,
77
+ symbol: str,
78
+ *,
79
+ type: Literal["shareholders", "outstanding_shareholders"] = "shareholders",
80
+ limit: int = 10,
81
+ ) -> list[dict[str, Any]]:
53
82
  """
54
83
  Get list of major shareholders
55
84
 
56
85
  Args:
57
86
  symbol: Stock symbol
87
+ type: Type of shareholders to return
88
+ - "shareholders": All shareholders
89
+ - "outstanding_shareholders": Outstanding shareholders only
90
+ limit: Number of shareholders to return (default: 10)
58
91
 
59
92
  Returns:
60
93
  List of shareholders with ownership details
61
94
  """
62
- response = self._post("/v1/stock/company-shareholders", json={"symbol": symbol})
95
+ response = self._post(
96
+ "/v1/stock/company-shareholders",
97
+ json={"symbol": symbol, "type": type, "limit": limit},
98
+ )
63
99
  return response if isinstance(response, list) else response.get("shareholders", [])
64
100
 
65
101
  # -------------------------------------------------------------------------
@@ -70,16 +106,26 @@ class StockModule:
70
106
  self,
71
107
  symbol: str,
72
108
  *,
73
- period: Literal["annual", "quarterly"] = "annual",
74
- limit: int = 10,
109
+ period: Literal["annual", "quarterly", "cumulative quarterly"] = "annual",
110
+ limit: int = 8,
111
+ start_date: str | None = None,
112
+ end_date: str | None = None,
113
+ calendar: Literal["calendar", "fiscal"] = "fiscal",
114
+ fiscal_year: str | None = None,
115
+ fiscal_quarter: str | None = None,
75
116
  ) -> pd.DataFrame:
76
117
  """
77
118
  Get income statement data
78
119
 
79
120
  Args:
80
121
  symbol: Stock symbol (e.g., "US:AAPL")
81
- period: "annual" or "quarterly"
82
- limit: Number of periods to return
122
+ period: Report cycle ("annual", "quarterly", "cumulative quarterly")
123
+ limit: Return latest N records (default: 8)
124
+ start_date: Start date (YYYY-MM-DD)
125
+ end_date: End date (YYYY-MM-DD)
126
+ calendar: "calendar" or "fiscal" (default: "fiscal")
127
+ fiscal_year: Specific fiscal year (e.g., "2023")
128
+ fiscal_quarter: Specific fiscal quarter (Q1, Q2, Q3, Q4, FY, H1, "Q3 (9 months)")
83
129
 
84
130
  Returns:
85
131
  DataFrame with income statement data, indexed by date
@@ -88,10 +134,22 @@ class StockModule:
88
134
  >>> income = client.stock.income_statement("US:AAPL", period="quarterly")
89
135
  >>> print(income[["revenue", "net_income"]].head())
90
136
  """
91
- response = self._post(
92
- "/v1/stock/company-income-statement",
93
- json={"symbol": symbol, "period": period, "limit": limit},
94
- )
137
+ data: dict[str, Any] = {
138
+ "symbol": symbol,
139
+ "period": period,
140
+ "limit": limit,
141
+ "calendar": calendar,
142
+ }
143
+ if start_date:
144
+ data["start_date"] = start_date
145
+ if end_date:
146
+ data["end_date"] = end_date
147
+ if fiscal_year:
148
+ data["fiscal_year"] = fiscal_year
149
+ if fiscal_quarter:
150
+ data["fiscal_quarter"] = fiscal_quarter
151
+
152
+ response = self._post("/v1/stock/company-income-statement", json=data)
95
153
  return self._to_dataframe(response)
96
154
 
97
155
  def balance_sheet(
@@ -99,15 +157,25 @@ class StockModule:
99
157
  symbol: str,
100
158
  *,
101
159
  period: Literal["annual", "quarterly"] = "annual",
102
- limit: int = 10,
160
+ limit: int = 8,
161
+ start_date: str | None = None,
162
+ end_date: str | None = None,
163
+ calendar: Literal["calendar", "fiscal"] = "fiscal",
164
+ fiscal_year: str | None = None,
165
+ fiscal_quarter: str | None = None,
103
166
  ) -> pd.DataFrame:
104
167
  """
105
168
  Get balance sheet data
106
169
 
107
170
  Args:
108
171
  symbol: Stock symbol
109
- period: "annual" or "quarterly"
110
- limit: Number of periods to return
172
+ period: Report cycle ("annual", "quarterly")
173
+ limit: Return latest N records (default: 8)
174
+ start_date: Start date (YYYY-MM-DD)
175
+ end_date: End date (YYYY-MM-DD)
176
+ calendar: "calendar" or "fiscal" (default: "fiscal")
177
+ fiscal_year: Specific fiscal year (e.g., "2023")
178
+ fiscal_quarter: Specific fiscal quarter (Q1, Q2, Q3, Q4, FY)
111
179
 
112
180
  Returns:
113
181
  DataFrame with balance sheet data, indexed by date
@@ -116,26 +184,48 @@ class StockModule:
116
184
  >>> balance = client.stock.balance_sheet("US:AAPL")
117
185
  >>> print(balance[["total_assets", "total_liabilities"]].head())
118
186
  """
119
- response = self._post(
120
- "/v1/stock/company-balance-sheet",
121
- json={"symbol": symbol, "period": period, "limit": limit},
122
- )
187
+ data: dict[str, Any] = {
188
+ "symbol": symbol,
189
+ "period": period,
190
+ "limit": limit,
191
+ "calendar": calendar,
192
+ }
193
+ if start_date:
194
+ data["start_date"] = start_date
195
+ if end_date:
196
+ data["end_date"] = end_date
197
+ if fiscal_year:
198
+ data["fiscal_year"] = fiscal_year
199
+ if fiscal_quarter:
200
+ data["fiscal_quarter"] = fiscal_quarter
201
+
202
+ response = self._post("/v1/stock/company-balance-sheet", json=data)
123
203
  return self._to_dataframe(response)
124
204
 
125
205
  def cashflow_statement(
126
206
  self,
127
207
  symbol: str,
128
208
  *,
129
- period: Literal["annual", "quarterly"] = "annual",
130
- limit: int = 10,
209
+ period: Literal["annual", "quarterly", "cumulative quarterly"] = "annual",
210
+ limit: int = 8,
211
+ start_date: str | None = None,
212
+ end_date: str | None = None,
213
+ calendar: Literal["calendar", "fiscal"] = "fiscal",
214
+ fiscal_year: str | None = None,
215
+ fiscal_quarter: str | None = None,
131
216
  ) -> pd.DataFrame:
132
217
  """
133
218
  Get cash flow statement data
134
219
 
135
220
  Args:
136
221
  symbol: Stock symbol
137
- period: "annual" or "quarterly"
138
- limit: Number of periods to return
222
+ period: Report cycle ("annual", "quarterly", "cumulative quarterly")
223
+ limit: Return latest N records (default: 8)
224
+ start_date: Start date (YYYY-MM-DD)
225
+ end_date: End date (YYYY-MM-DD)
226
+ calendar: "calendar" or "fiscal" (default: "fiscal")
227
+ fiscal_year: Specific fiscal year (e.g., "2023")
228
+ fiscal_quarter: Specific fiscal quarter (Q1, Q2, Q3, Q4, FY, H1, "Q3 (9 months)")
139
229
 
140
230
  Returns:
141
231
  DataFrame with cash flow data, indexed by date
@@ -144,134 +234,111 @@ class StockModule:
144
234
  >>> cashflow = client.stock.cashflow_statement("US:AAPL")
145
235
  >>> print(cashflow[["operating_cashflow", "free_cashflow"]].head())
146
236
  """
147
- response = self._post(
148
- "/v1/stock/company-cashflow-statement",
149
- json={"symbol": symbol, "period": period, "limit": limit},
150
- )
151
- return self._to_dataframe(response)
152
-
153
- def revenue_breakdown(
154
- self,
155
- symbol: str,
156
- *,
157
- breakdown_type: Literal["segment", "product", "region"] = "segment",
158
- ) -> pd.DataFrame:
159
- """
160
- Get revenue breakdown by segment, product, or region
161
-
162
- Args:
163
- symbol: Stock symbol
164
- breakdown_type: Type of breakdown ("segment", "product", or "region")
237
+ data: dict[str, Any] = {
238
+ "symbol": symbol,
239
+ "period": period,
240
+ "limit": limit,
241
+ "calendar": calendar,
242
+ }
243
+ if start_date:
244
+ data["start_date"] = start_date
245
+ if end_date:
246
+ data["end_date"] = end_date
247
+ if fiscal_year:
248
+ data["fiscal_year"] = fiscal_year
249
+ if fiscal_quarter:
250
+ data["fiscal_quarter"] = fiscal_quarter
165
251
 
166
- Returns:
167
- DataFrame with revenue breakdown data
168
- """
169
- response = self._post(
170
- "/v1/stock/company-revenue-breakdown",
171
- json={"symbol": symbol, "breakdown_type": breakdown_type},
172
- )
252
+ response = self._post("/v1/stock/company-cashflow-statement", json=data)
173
253
  return self._to_dataframe(response)
174
254
 
175
- # -------------------------------------------------------------------------
176
- # Price Data (returns DataFrame)
177
- # -------------------------------------------------------------------------
178
-
179
- def prices(
255
+ def revenue_breakdown(
180
256
  self,
181
257
  symbol: str,
182
258
  *,
259
+ period: str | None = None,
260
+ limit: int = 6,
183
261
  start_date: str | None = None,
184
262
  end_date: str | None = None,
185
- limit: int = 100,
263
+ fiscal_year: str | None = None,
186
264
  ) -> pd.DataFrame:
187
265
  """
188
- Get historical stock prices with market data
266
+ Get revenue breakdown
189
267
 
190
268
  Args:
191
269
  symbol: Stock symbol
270
+ period: Report cycle (e.g., "FY", "Q2")
271
+ limit: Return latest N records (default: 6)
192
272
  start_date: Start date (YYYY-MM-DD)
193
273
  end_date: End date (YYYY-MM-DD)
194
- limit: Maximum number of records
274
+ fiscal_year: Specific fiscal year (e.g., "2023")
195
275
 
196
276
  Returns:
197
- DataFrame with price data (date, close, volume, market_cap, pe, ps)
198
-
199
- Example:
200
- >>> prices = client.stock.prices("US:AAPL", limit=30)
201
- >>> print(prices[["close", "volume"]].tail())
277
+ DataFrame with revenue breakdown data
202
278
  """
203
279
  data: dict[str, Any] = {"symbol": symbol, "limit": limit}
280
+ if period:
281
+ data["period"] = period
204
282
  if start_date:
205
283
  data["start_date"] = start_date
206
284
  if end_date:
207
285
  data["end_date"] = end_date
286
+ if fiscal_year:
287
+ data["fiscal_year"] = fiscal_year
208
288
 
209
- response = self._post("/v1/stock/company-prices", json=data)
289
+ response = self._post("/v1/stock/company-revenue-breakdown", json=data)
210
290
  return self._to_dataframe(response)
211
291
 
212
- def kline(
292
+ # -------------------------------------------------------------------------
293
+ # Price Data (returns DataFrame)
294
+ # -------------------------------------------------------------------------
295
+
296
+ def prices(
213
297
  self,
214
298
  symbol: str,
215
299
  *,
216
- interval: Literal["1d", "1w", "1m"] = "1d",
217
- adjust: Literal["forward", "backward", "none"] = "forward",
218
300
  start_date: str | None = None,
219
301
  end_date: str | None = None,
220
- limit: int = 100,
221
302
  ) -> pd.DataFrame:
222
303
  """
223
- Get K-line (candlestick) data
304
+ Get historical stock prices with market data
224
305
 
225
306
  Args:
226
307
  symbol: Stock symbol
227
- interval: Time interval ("1d" daily, "1w" weekly, "1m" monthly)
228
- adjust: Price adjustment type
229
- - "forward": Forward adjusted (前复权)
230
- - "backward": Backward adjusted (后复权)
231
- - "none": Unadjusted (不复权)
232
308
  start_date: Start date (YYYY-MM-DD)
233
309
  end_date: End date (YYYY-MM-DD)
234
- limit: Maximum number of records
235
310
 
236
311
  Returns:
237
- DataFrame with OHLCV data (date, open, high, low, close, volume)
312
+ DataFrame with price data (date, close, volume, market_cap, pe, ps)
238
313
 
239
314
  Example:
240
- >>> kline = client.stock.kline("US:TSLA", interval="1d", limit=100)
241
- >>> print(kline.tail())
315
+ >>> prices = client.stock.prices("US:AAPL")
316
+ >>> print(prices[["close", "volume"]].tail())
242
317
  """
243
- data: dict[str, Any] = {
244
- "symbol": symbol,
245
- "interval": interval,
246
- "adjust": adjust,
247
- "limit": limit,
248
- }
318
+ data: dict[str, Any] = {"symbol": symbol}
249
319
  if start_date:
250
320
  data["start_date"] = start_date
251
321
  if end_date:
252
322
  data["end_date"] = end_date
253
323
 
254
- response = self._post("/v1/stock/kline", json=data)
324
+ response = self._post("/v1/stock/company-prices", json=data)
255
325
  return self._to_dataframe(response)
256
326
 
257
- def quote(self, symbols: str | list[str]) -> pd.DataFrame:
327
+ def quote(self, symbol: str) -> pd.DataFrame:
258
328
  """
259
- Get real-time stock quotes
329
+ Get real-time stock quote
260
330
 
261
331
  Args:
262
- symbols: Single symbol or list of symbols
332
+ symbol: Stock symbol (e.g., "US:AAPL", "688001", "00700")
263
333
 
264
334
  Returns:
265
335
  DataFrame with real-time quote data
266
336
 
267
337
  Example:
268
- >>> quotes = client.stock.quote(["US:AAPL", "US:MSFT"])
269
- >>> print(quotes[["symbol", "price", "change_percent"]])
338
+ >>> quote = client.stock.quote("US:AAPL")
339
+ >>> print(quote[["symbol", "price", "change_percent"]])
270
340
  """
271
- if isinstance(symbols, str):
272
- symbols = [symbols]
273
-
274
- response = self._post("/v1/stock/quote-realtime", json={"symbols": symbols})
341
+ response = self._post("/v1/stock/quote-realtime", json={"symbol": symbol})
275
342
  return self._to_dataframe(response)
276
343
 
277
344
  def index_prices(
@@ -280,21 +347,19 @@ class StockModule:
280
347
  *,
281
348
  start_date: str | None = None,
282
349
  end_date: str | None = None,
283
- limit: int = 100,
284
350
  ) -> pd.DataFrame:
285
351
  """
286
- Get stock index prices (e.g., S&P 500, NASDAQ)
352
+ Get stock index prices (e.g., HSI, SPX, DJI)
287
353
 
288
354
  Args:
289
- symbol: Index symbol
355
+ symbol: Index symbol (e.g., "HSI", "SPX", "DJI")
290
356
  start_date: Start date (YYYY-MM-DD)
291
357
  end_date: End date (YYYY-MM-DD)
292
- limit: Maximum number of records
293
358
 
294
359
  Returns:
295
360
  DataFrame with index price data
296
361
  """
297
- data: dict[str, Any] = {"symbol": symbol, "limit": limit}
362
+ data: dict[str, Any] = {"symbol": symbol}
298
363
  if start_date:
299
364
  data["start_date"] = start_date
300
365
  if end_date:
@@ -310,42 +375,82 @@ class StockModule:
310
375
  def screener(
311
376
  self,
312
377
  *,
313
- market: str | None = None,
314
- sector: str | None = None,
315
- min_market_cap: float | None = None,
316
- max_market_cap: float | None = None,
317
- min_pe: float | None = None,
318
- max_pe: float | None = None,
319
- limit: int = 50,
378
+ market_cap_more_than: float | None = None,
379
+ market_cap_lower_than: float | None = None,
380
+ price_more_than: float | None = None,
381
+ price_lower_than: float | None = None,
382
+ change_percentage_more_than: float | None = None,
383
+ change_percentage_lower_than: float | None = None,
384
+ volume_more_than: int | None = None,
385
+ volume_lower_than: int | None = None,
386
+ country: str | None = None,
387
+ exchange: str | None = None,
388
+ dividend_yield_more_than: float | None = None,
389
+ dividend_yield_lower_than: float | None = None,
390
+ pe_ttm_more_than: float | None = None,
391
+ pe_ttm_lower_than: float | None = None,
392
+ limit: int = 100,
320
393
  ) -> pd.DataFrame:
321
394
  """
322
395
  Screen stocks based on various criteria
323
396
 
324
397
  Args:
325
- market: Filter by market (US, HK, CN)
326
- sector: Filter by sector
327
- min_market_cap: Minimum market cap
328
- max_market_cap: Maximum market cap
329
- min_pe: Minimum P/E ratio
330
- max_pe: Maximum P/E ratio
331
- limit: Maximum number of results
398
+ market_cap_more_than: Market cap greater than
399
+ market_cap_lower_than: Market cap less than
400
+ price_more_than: Stock price greater than
401
+ price_lower_than: Stock price less than
402
+ change_percentage_more_than: Change percentage greater than (e.g., 0.02 for 2%)
403
+ change_percentage_lower_than: Change percentage less than (e.g., 0.04 for 4%)
404
+ volume_more_than: Trading volume greater than
405
+ volume_lower_than: Trading volume less than
406
+ country: Country code (e.g., "US", "CN", "HK")
407
+ exchange: Exchange code (e.g., "NASDAQ", "NYSE", "HKEX")
408
+ dividend_yield_more_than: Dividend yield greater than
409
+ dividend_yield_lower_than: Dividend yield less than
410
+ pe_ttm_more_than: PE TTM greater than
411
+ pe_ttm_lower_than: PE TTM less than
412
+ limit: Maximum number of results (default: 100)
332
413
 
333
414
  Returns:
334
415
  DataFrame with screened stocks
416
+
417
+ Example:
418
+ >>> # Find US stocks with PE < 15 and market cap > 1B
419
+ >>> stocks = client.stock.screener(
420
+ ... country="US",
421
+ ... pe_ttm_lower_than=15,
422
+ ... market_cap_more_than=1000000000
423
+ ... )
335
424
  """
336
425
  data: dict[str, Any] = {"limit": limit}
337
- if market:
338
- data["market"] = market
339
- if sector:
340
- data["sector"] = sector
341
- if min_market_cap is not None:
342
- data["min_market_cap"] = min_market_cap
343
- if max_market_cap is not None:
344
- data["max_market_cap"] = max_market_cap
345
- if min_pe is not None:
346
- data["min_pe"] = min_pe
347
- if max_pe is not None:
348
- data["max_pe"] = max_pe
426
+ if market_cap_more_than is not None:
427
+ data["market_cap_more_than"] = market_cap_more_than
428
+ if market_cap_lower_than is not None:
429
+ data["market_cap_lower_than"] = market_cap_lower_than
430
+ if price_more_than is not None:
431
+ data["price_more_than"] = price_more_than
432
+ if price_lower_than is not None:
433
+ data["price_lower_than"] = price_lower_than
434
+ if change_percentage_more_than is not None:
435
+ data["change_percentage_more_than"] = change_percentage_more_than
436
+ if change_percentage_lower_than is not None:
437
+ data["change_percentage_lower_than"] = change_percentage_lower_than
438
+ if volume_more_than is not None:
439
+ data["volume_more_than"] = volume_more_than
440
+ if volume_lower_than is not None:
441
+ data["volume_lower_than"] = volume_lower_than
442
+ if country:
443
+ data["country"] = country
444
+ if exchange:
445
+ data["exchange"] = exchange
446
+ if dividend_yield_more_than is not None:
447
+ data["dividend_yield_more_than"] = dividend_yield_more_than
448
+ if dividend_yield_lower_than is not None:
449
+ data["dividend_yield_lower_than"] = dividend_yield_lower_than
450
+ if pe_ttm_more_than is not None:
451
+ data["pe_ttm_more_than"] = pe_ttm_more_than
452
+ if pe_ttm_lower_than is not None:
453
+ data["pe_ttm_lower_than"] = pe_ttm_lower_than
349
454
 
350
455
  response = self._post("/v1/stock/screener", json=data)
351
456
  return self._to_dataframe(response)
reportify_sdk/timeline.py CHANGED
@@ -3,14 +3,28 @@ Timeline Module
3
3
 
4
4
  Provides access to timeline feeds based on user's followed entities
5
5
  (companies, topics, institutes, media).
6
+
7
+ NOTE: This module uses internal APIs that are not documented in the public OpenAPI spec.
8
+ These endpoints may change without notice.
6
9
  """
7
10
 
11
+ import warnings
8
12
  from typing import TYPE_CHECKING, Any
9
13
 
10
14
  if TYPE_CHECKING:
11
15
  from reportify_sdk.client import Reportify
12
16
 
13
17
 
18
+ def _timeline_deprecation_warning(method_name: str) -> None:
19
+ """Emit deprecation warning for timeline methods."""
20
+ warnings.warn(
21
+ f"timeline.{method_name}() uses an internal API not documented in the public OpenAPI spec. "
22
+ "This endpoint may change without notice.",
23
+ DeprecationWarning,
24
+ stacklevel=3,
25
+ )
26
+
27
+
14
28
  class TimelineModule:
15
29
  """
16
30
  Timeline module for following-based content feeds
@@ -30,6 +44,9 @@ class TimelineModule:
30
44
  """
31
45
  Get timeline for followed companies
32
46
 
47
+ .. deprecated::
48
+ This method uses an internal API not documented in the public OpenAPI spec.
49
+
33
50
  Returns recent content related to companies the user is following,
34
51
  including financial reports, news, research reports, and announcements.
35
52
 
@@ -44,6 +61,7 @@ class TimelineModule:
44
61
  >>> for item in timeline:
45
62
  ... print(item["title"], item["published_at"])
46
63
  """
64
+ _timeline_deprecation_warning("companies")
47
65
  response = self._post("/v1/tools/timeline/companies", json={"num": num})
48
66
  return response.get("docs", [])
49
67
 
@@ -51,6 +69,9 @@ class TimelineModule:
51
69
  """
52
70
  Get timeline for followed topics
53
71
 
72
+ .. deprecated::
73
+ This method uses an internal API not documented in the public OpenAPI spec.
74
+
54
75
  Returns recent content related to custom topics the user is following.
55
76
 
56
77
  Args:
@@ -64,6 +85,7 @@ class TimelineModule:
64
85
  >>> for item in timeline:
65
86
  ... print(item["title"])
66
87
  """
88
+ _timeline_deprecation_warning("topics")
67
89
  response = self._post("/v1/tools/timeline/topics", json={"num": num})
68
90
  return response.get("docs", [])
69
91
 
@@ -71,6 +93,9 @@ class TimelineModule:
71
93
  """
72
94
  Get timeline for followed professional institutes
73
95
 
96
+ .. deprecated::
97
+ This method uses an internal API not documented in the public OpenAPI spec.
98
+
74
99
  Returns recent content from research institutions, banks,
75
100
  and other professional organizations the user is following.
76
101
 
@@ -85,6 +110,7 @@ class TimelineModule:
85
110
  >>> for item in timeline:
86
111
  ... print(item["channel_name"], item["title"])
87
112
  """
113
+ _timeline_deprecation_warning("institutes")
88
114
  response = self._post("/v1/tools/timeline/institutes", json={"num": num})
89
115
  return response.get("docs", [])
90
116
 
@@ -92,6 +118,9 @@ class TimelineModule:
92
118
  """
93
119
  Get timeline for followed public media
94
120
 
121
+ .. deprecated::
122
+ This method uses an internal API not documented in the public OpenAPI spec.
123
+
95
124
  Returns recent content from public media accounts (WeChat, etc.)
96
125
  the user is following.
97
126
 
@@ -104,6 +133,7 @@ class TimelineModule:
104
133
  Example:
105
134
  >>> timeline = client.timeline.public_media(num=20)
106
135
  """
136
+ _timeline_deprecation_warning("public_media")
107
137
  response = self._post("/v1/tools/timeline/public-media", json={"num": num})
108
138
  return response.get("docs", [])
109
139
 
@@ -111,6 +141,9 @@ class TimelineModule:
111
141
  """
112
142
  Get timeline for followed social media
113
143
 
144
+ .. deprecated::
145
+ This method uses an internal API not documented in the public OpenAPI spec.
146
+
114
147
  Returns recent content from social media accounts (Twitter, etc.)
115
148
  the user is following.
116
149
 
@@ -123,5 +156,6 @@ class TimelineModule:
123
156
  Example:
124
157
  >>> timeline = client.timeline.social_media(num=20)
125
158
  """
159
+ _timeline_deprecation_warning("social_media")
126
160
  response = self._post("/v1/tools/timeline/social-media", json={"num": num})
127
161
  return response.get("docs", [])