Public API recipes
Use the generated reference for exact request and response schemas. These recipes target published @newsteam/api@1.0.0-alpha.10 and the public V1 API. First obtain a Site app ID and matching API origin.
JSON POST and SDK calls
Section titled “JSON POST and SDK calls”Raw calls include the versioned operation path and the app-id header:
curl --fail-with-body https://api.newsteam.io/v1/site.route \ -H 'content-type: application/json' \ -H 'app-id: YOUR_APP_ID' \ --data '{"path":""}'The raw success body is the response model itself, such as RouteResponse, with type and entity. It is not wrapped in { data, error }. Check the HTTP status before reading a success model and handle the documented error response on failure.
Install the published client in your project:
npm install --save-exact @newsteam/api@1.0.0-alpha.10import { NewsTeamApi } from "@newsteam/api";
const api = new NewsTeamApi({ appId: "YOUR_APP_ID", url: "https://api.newsteam.io",});const result = await api.site.route({ path: "" });if (result.error) { throw new Error(result.error.message);}console.log(result.data.type, result.data.entity);The SDK origin has no /v1 suffix: it adds /v1/site.route. SDK methods return a result with data or error; branch on error before rendering data. Also handle thrown/network failures at the application’s request boundary. A missing route should produce a real 404; a temporary upstream failure needs an error/retry state.
Wire operation names use kebab-case; SDK method names use camelCase. Request fields remain as documented in the schema:
| Raw POST operation | SDK method |
|---|---|
article.popular-terms | api.article.popularTerms(...) |
site.get-ads-txt | api.site.getAdsTxt() |
auth.issue-access-token | api.auth.issueAccessToken(...) |
subscription.list-products | api.subscription.listProducts() |
subscription.subscribe-callback | api.subscription.subscribeCallback(...) |
subscription.get-portal-url | api.subscription.getPortalUrl(...) |
Route through the Site
Section titled “Route through the Site”Use one site.route({ path }) resolver for page rendering, article rendering and metadata. The homepage path is "". Honour redirectPath and render the returned page/article entity; do not construct a public article URL by appending its slug to a section.
ArticleListItem.path is optional. Link a card only when it has an approved destination. A relative path is a Site route; an absolute HTTP(S) path is external. Validate external destinations and open them according to your product’s external-link policy. Keep a pathless card unlinked or omit it from a surface that requires navigation. A slug or canonicalUrl alone is not proof that the Site serves that route.
For section RSS/Atom feeds, query article.list({ path, limit }) using the section’s menu path. Do not infer feed membership by parsing page widgets. Use the same route rules for sitemap entries, including section URLs and only indexable canonical articles. Exclude pathless items, previews, search, member and transaction routes. See Site client rules.
Millisecond dates and token expiry
Section titled “Millisecond dates and token expiry”NewsTeam timestamps such as publishedAt, createdAt, dateMin, dateMax and auth.issueAccessToken().expiresAt use Unix epoch milliseconds. Use new Date(value) and compare to Date.now() directly. Do not multiply by 1,000. Cookie Max-Age and third-party JWT exp are separate contracts measured in seconds.
For a secure web session, set cookie expiry from new Date(token.expiresAt). If your cookie helper uses maxAge, compute remaining seconds with Math.max(0, Math.floor((token.expiresAt - Date.now()) / 1000)). Keep the reader token in a secure, HTTP-only cookie and private reads uncached; see reader identity.
Filtered cursor pages
Section titled “Filtered cursor pages”Freeze the query inputs for one pagination run. Send nextPageToken back as pageToken, retaining the same filters. Reset the cursor, accumulated IDs and query bounds when filters change.
const filters = { path: "news", dateMin: Date.now() - 7 * 24 * 60 * 60 * 1000, limit: 20,};let pageToken: string | undefined;const seenTokens = new Set<string>();const seenIds = new Set<string>();
// Bound automatic traversal. A UI would usually request one page per action.for (let page = 0; page < 10; page++) { const result = await api.article.list({ ...filters, pageToken }); if (result.error) throw new Error(result.error.message); for (const article of result.data.items) { if (seenIds.has(article.id)) continue; seenIds.add(article.id); if (article.path) console.log(article.path); } const next = result.data.nextPageToken; if (!next || next === pageToken || seenTokens.has(next)) break; seenTokens.add(next); pageToken = next;}Use your Site’s real section path instead of news. Stop when the cursor is absent or repeats, not merely when a filtered visible page is short or empty. Deduplicate articles by ID. If a UI hides pathless or otherwise ineligible cards, preserve the raw response’s continuation token; bounded continuation prevents an endless load loop. Continue only through a user action when the automatic bound is reached.