NewTimeSpace API
NewTimeSpace API

NewTimeSpace API Get articles

Quick start

Full request (Base URL: https://www.newtimespace.com). No registration and no API key are required; both GET and POST are supported (POST may carry a JSON body):

GET https://www.newtimespace.com/api/v1/article/getArticles?language=en&q=AI&page=1&limit=10&format=json

The list endpoint returns only a short summary for each article; call the details endpoint to read the full text. Response example (JSON):

{
  "status": "success",
  "articles": [
    {
      "article_id": "1024",
      "title": "Xiaomi unveils next-generation smart cockpit",
      "summary": "Xiaomi today unveiled its next-generation smart cockpit solution...",
      "publish_time": "2026-09-22T10:00:00+08:00",
      "url": "https://www.newtimespace.com/en/news/1024.html",
      "category": "Tech"
    }
  ],
  "pagination": { "page": 1, "limit": 10, "total": 137, "total_pages": 14 },
  "request_id": "a1b2c3d4e5f60718",
  "server_time": "2026-09-23T09:30:00+08:00",
  "applied_filters": {
    "q": "AI", "category": "", "category_ids": [], "language": "en",
    "start_date": "", "end_date": "", "sort": "publish_time", "order": "desc",
    "format": "json", "fields": []
  },
  "warnings": []
}

Parsing the response

Responses are standard UTF-8 JSON with no BOM and Content-Type: application/json, so you can hand the bytes straight to json.loads. Every response carries request_id (equal to the X-Request-Id response header); include it when reporting an issue.

import json, urllib.request

raw = urllib.request.urlopen(
    "https://www.newtimespace.com/api/v1/article/getArticles?format=json"
).read()
data = json.loads(raw.decode("utf-8"))  # standard UTF-8 JSON, no BOM
for a in data["articles"]:
    print(a["article_id"], a["publish_time"], a["title"])
print(data["pagination"])  # use total_pages as the paging stop condition

Request parameters

ParameterTypeRequiredDescriptionDefault
qstringNoSearch keyword, fuzzy-matched against title and summary. Pass a single core term (e.g. "Xiaomi"); avoid spaces and AND/OR/NOT operators''
categorystringNoCategory name (exact match, case-sensitive); must pair with language (see below)''
languagestringNoOutput language: zh-cn (Simplified, default), zh-hk (Traditional), en (English). Unknown values fall back to zh-cnzh-cn
start_datestringNoStart date (YYYY-MM-DD, inclusive of 00:00:00 that day)''
end_datestringNoEnd date (YYYY-MM-DD, inclusive of 23:59:59 that day)''
pageintegerNoPage number (starting from 1). A page beyond the total returns an empty array without an error1
limitintegerNoPage size (1-100); out-of-range returns HTTP 400 (PARAMETER_OUT_OF_RANGE). 10-20 recommended to save tokens10
sortstringNoSort field: publish_time (publish time) or id (article ID)publish_time
orderstringNoSort direction: desc (descending) or asc (ascending)desc
fieldsstringNoSparse fieldset (comma-separated) to trim list output and save tokens. Allowed: article_id,title,summary,publish_time,url,category. article_id is always returned. Empty = all fields''
formatstringNoResponse format: json or xml; other values are treated as json. The Accept header does not affect the format — always pass it explicitlyjson

Backward compatibility: the legacy title parameter is merged into q; the legacy date parameter is treated as a single-day range (start_date = end_date = date); the legacy sortBy (date | id) maps to sort (date → publish_time).

Category values (must be paired with language)

languageValid categories
zh-cnETF、财经、新股、科技、出海、新时空研究院
zh-hkETF、新股、科技、出海. 财经 and 新时空研究院 return an empty result under zh-hk (both simplified and traditional forms)
enETF, Finance, IPO, Research, Tech, Overseas

Mismatched combinations (e.g. zh-cn with IPO) or nonexistent category values return HTTP 200 with an empty array and a message; the warnings field then lists the valid categories for that language so you can self-correct. Note: articles with category 财经 / 新时空研究院 do appear in zh-hk list results, yet filtering zh-hk by these two values returns an empty array — to get these categories in Traditional Chinese, fetch language=zh-hk without category and filter on the category field yourself.

Response fields and envelope

Each item in articles contains six fields:

FieldDescription
article_idArticle ID (always returned); use it to call the details endpoint
titleTitle
summarySummary (not the full text); call the details endpoint to read the full text
publish_timePublish time, ISO-8601 Beijing time (GMT+8), e.g. 2026-09-22T10:00:00+08:00
urlCanonical article link; use it for citations, do not build your own
categoryCategory name

Top-level envelope fields:

FieldDescription
status"success" on success
articlesArray of articles (an empty array when there are no matches)
pagination{ page, limit, total, total_pages }
request_idRequest tracking ID (equals the X-Request-Id header); include it when reporting issues
server_timeServer time, ISO-8601
applied_filtersThe filters the server actually applied (q, category, category_ids, language, start_date, end_date, sort, order, format, fields); verify them against your intent
warningsNon-fatal hints (e.g. category not matched, en summary fell back to Chinese)
messageOptional; present on empty results

XML output (format=xml, list endpoint only; no envelope or pagination). Each field is wrapped in CDATA and Content-Type is text/xml:

<?xml version="1.0" encoding="UTF-8"?>
<articles>
  <article>
    <article_id><![CDATA[1024]]></article_id>
    <title><![CDATA[Xiaomi unveils next-generation smart cockpit]]></title>
    <summary><![CDATA[Xiaomi today unveiled its next-generation smart cockpit solution...]]></summary>
    <publish_time><![CDATA[2026-09-22T10:00:00+08:00]]></publish_time>
    <url><![CDATA[https://www.newtimespace.com/en/news/1024.html]]></url>
    <category><![CDATA[Tech]]></category>
  </article>
</articles>

Pagination

pagination contains page (current page), limit (page size), total (total matches) and total_pages (total pages). Example: {"page": 1, "limit": 10, "total": 137, "total_pages": 14}.

Stop on total_pages, not on an empty array. A page beyond the total returns HTTP 200 with an empty array and no error; using "got an empty array" as the stop condition wastes requests. Stop paging when page >= total_pages.

Empty results and errors

No matches / mismatched combination / page beyond the total return HTTP 200 with an empty array — a normal result; do not retry. The warnings field explains why (e.g. it lists the valid categories):

{ "status": "success", "articles": [], "pagination": { "page": 1, "limit": 10, "total": 0, "total_pages": 0 }, "request_id": "a1b2c3d4e5f60718", "server_time": "2026-09-23T09:30:00+08:00", "applied_filters": { "q": "", "category": "IPO", "category_ids": [], "language": "zh-cn", "start_date": "", "end_date": "", "sort": "publish_time", "order": "desc", "format": "json", "fields": [] }, "warnings": ["category 'IPO' has no match under language 'zh-cn'"], "message": "no articles matched the given filters" }

Errors use RFC 7807 (Content-Type: application/problem+json) with a standard HTTP status code. Example (limit out of range):

{
  "type": "about:blank",
  "title": "Bad Request",
  "status": 400,
  "detail": "limit out of range: page size must be between 1 and 100.",
  "error_code": "PARAMETER_OUT_OF_RANGE",
  "request_id": "a1b2c3d4e5f60718",
  "instance": "/api/v1/article/getArticles?limit=200",
  "code": 400,
  "message": "limit out of range: page size must be between 1 and 100."
}
TriggerHTTPerror_code
limit outside 1-100400PARAMETER_OUT_OF_RANGE
more than 60 requests per IP per 60 seconds429RATE_LIMIT_EXCEEDED (carries Retry-After; wait accordingly)
unexpected server failure500INTERNAL_SERVER_ERROR

Notes for agents

  • The list returns summaries only: summary is a short abstract, not the full text. To read the full text, call the details endpoint, which returns clean minimal Markdown (see Get article details).
  • No BOM: responses are standard UTF-8 JSON; call json.loads / raw.decode("utf-8") directly — no need for utf-8-sig.
  • Time is Beijing time (GMT+8): publish_time is ISO-8601 (e.g. 2026-09-22T10:00:00+08:00) and already carries the offset; do not add 8 hours.
  • Date range: use start_date / end_date (YYYY-MM-DD); start_date includes 00:00:00 and end_date includes 23:59:59.
  • Take article_id from results: use real article_id values from the response; never construct or guess one.
  • Self-check with the envelope: verify applied_filters against your intent and read warnings (e.g. category not matched, en fell back to Chinese); include request_id when reporting issues.
  • Empty results are normal: no matches / mismatched combination / page beyond the total all return HTTP 200 with an empty array; do not retry. Page until page >= total_pages.
  • Rate limit: 60 requests per IP per 60 seconds; on 429 wait per Retry-After, then retry. No remaining-quota headers are returned, so count request frequency yourself.
  • GET and POST: POST may carry a JSON body. CORS is enabled (Access-Control-Allow-Origin: *; methods GET/POST/OPTIONS; OPTIONS preflight returns 204).
  • Format: always pass format explicitly; the Accept header does not affect it. XML is supported by the list endpoint only (format=xml); the details endpoint is JSON only.

Complete example (search + pagination + reading the full text)

import json, urllib.request, urllib.parse

BASE = "https://www.newtimespace.com/api/v1/article/getArticles"
DETAIL = "https://www.newtimespace.com/api/v1/article/detail"

def search(keyword, max_pages=3):
    results = []
    for page in range(1, max_pages + 1):
        url = BASE + "?" + urllib.parse.urlencode(
            {"q": keyword, "language": "en", "format": "json", "page": page})
        raw = urllib.request.urlopen(url).read()
        data = json.loads(raw.decode("utf-8"))          # standard UTF-8 JSON, no BOM
        results += data["articles"]
        if page >= data["pagination"]["total_pages"]:   # stop condition: total_pages
            break
    return results

hits = search("profit warning")
for a in hits:
    print(a["publish_time"], a["title"])    # publish_time is Beijing time (GMT+8)
    print("  summary:", a["summary"][:80])  # the list returns a summary only
    print("  url:", a["url"])               # use this url for citations

# To read the full text, call the details endpoint (up to 10 IDs per call)
ids = ",".join(a["article_id"] for a in hits[:10])
raw = urllib.request.urlopen(DETAIL + "?article_ids=" + ids).read()
detail = json.loads(raw.decode("utf-8"))
for d in detail["data"]:                    # data is always an array
    print(d["article_id"], d["word_count"])
    print("  content (Markdown):", d["content"][:120])