Quickstart
Get your first article in about 5 minutes — request a key, send one GET, read the JSON array.
Code Examples
curl -X GET "https://api.upgate.online/api/v1/crypto/articles/translated/latest-snapshot/?lang=en&limit=3" \
-H "X-API-Key: your_client_api_key" \
-H "Accept: application/json"Response
[
{
"original_id": 2147,
"language": "en",
"title": "OKX will launch IRYS/USD and IRYS/EUR for spot trading",
"content": "To support the growth of the unified USD and EUR ecosystem...",
"created_at": "2026-05-27T05:00:00",
"meta": {
"token_mentions": ["IRYS"],
"thumbnail_url": "https://img.upgate.online/crypto/2147",
"source_name": "OKX",
"category": "exchanges",
"sentiment": "positive"
}
}
]Which Endpoint?
Not sure whether to use ScrollBoost or Snapshot? Use the chooser below.
Which endpoint should I use?
Pick your use case — we suggest the right call.
What are you building?
Integration Guide: News Feed
Poll ScrollBoost with direction=newer while your app is open. The server tracks read position — you do not send cursors. Append new articles to your UI; treat [] as up to date.
Code Examples
const API_BASE = "https://api.upgate.online"
const PATH = "/api/v1/crypto/articles/translated/"
async function pollFeed({ apiKey, lang = "en", limit = 10 }) {
const url = new URL(API_BASE + PATH)
url.searchParams.set("lang", lang)
url.searchParams.set("limit", String(limit))
url.searchParams.set("direction", "newer")
const res = await fetch(url, {
headers: { "X-API-Key": apiKey, Accept: "application/json" },
})
if (!res.ok) {
const err = await res.json().catch(() => ({}))
throw new Error(err.detail || `HTTP ${res.status}`)
}
return res.json() // [] = no new articles (not an error)
}
const apiKey = process.env.UPGATE_API_KEY
setInterval(async () => {
const batch = await pollFeed({ apiKey, lang: "en", limit: 10 })
for (const article of batch) {
renderCard(article) // title, meta.thumbnail_url, meta.sentiment
}
}, 60_000) // interval ≥ frequency_minutes on your planIntegration Guide: Cron & Alerts
Poll Snapshot from a server or cron job. Stateless — deduplicate by original_id on your side. Ideal for dashboards, Telegram bots, and token filters (?token=BTC).
Code Examples
const API_BASE = "https://api.upgate.online"
const PATH = "/api/v1/crypto/articles/translated/latest-snapshot/"
const seen = new Set()
async function pollSnapshot({ apiKey, lang = "en", limit = 10, token }) {
const params = { lang, limit: String(limit) }
if (token) params.token = token
const url = new URL(API_BASE + PATH)
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v))
const res = await fetch(url, {
headers: { "X-API-Key": apiKey, Accept: "application/json" },
})
if (!res.ok) throw new Error((await res.json().catch(() => ({}))).detail || res.status)
return res.json()
}
function ingestNew(articles) {
return articles.filter((a) => {
if (seen.has(a.original_id)) return false
seen.add(a.original_id)
return true
})
}
async function tick() {
const apiKey = process.env.UPGATE_API_KEY
const fresh = ingestNew(await pollSnapshot({ apiKey, lang: "en", limit: 10, token: "BTC" }))
for (const article of fresh) await notify(article)
}
setInterval(tick, 5 * 60_000)Overview
Translated crypto news for your product — headlines, body text, thumbnails, token tags, categories, and sentiment. Output in English (en) or Persian (fa, RTL). Two GET endpoints: one for scrollable feeds, one for server-side polling.
What each article includes
| Deliverable | Details |
|---|---|
| Translated title & body | en or localized — Markdown-ready |
| Topic category | market_trends, exchanges, regulation_policy, and more |
| Sentiment | positive, negative, or neutral |
| Token tags | meta.token_mentions — e.g. BTC, ETH, SOL |
| Source label | meta.source_name — publisher name |
| Thumbnail | CDN URL via meta.thumbnail_url — no extra auth |
Endpoints
| Endpoint | Stateful | Max limit | Use when |
|---|---|---|---|
| GET /articles/translated/ | Yes | 100 (default 10) | Building a scrollable news feed in your app |
| GET /articles/translated/latest-snapshot/ | No | 50 (default 10) | Polling from a server, dashboard, or cron job |
Authentication
Pass your API key in the X-API-Key header on every request. Keys are issued per account with rate limits configured at onboarding.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| X-API-Key | string | Yes | API key issued by UpGate Example: your_client_api_key |
| Accept | string | No | application/json Example: application/json |
| X-Request-ID | string | No | Optional; echoed in the response for support Example: my-trace-id-123 |
Code Examples
curl -X GET "https://api.upgate.online/api/v1/crypto/articles/translated/latest-snapshot/?limit=1" \
-H "X-API-Key: your_client_api_key"ScrollBoost Feed
Intelligent scroll pagination with server-side checkpoints. No cursor tokens. Articles limited to a rolling 2-day window.
ScrollBoost state flow
First request GET ?direction=newer → latest articles Poll for new items GET ?direction=newer → unseen articles only [] → nothing new (up to date) Scroll into older items (2-day window) GET ?direction=older → older articles [] → no more history available Position is tracked server-side per API key and language. You do not send cursor or offset parameters. For feed polling, always pass direction=newer on every request.
Endpoint
GEThttps://api.upgate.online/api/v1/crypto/articles/translated/Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| lang | string | No | en or fa. Default: fa Example: en |
| limit | integer | No | 1–100, capped by plan max_items_per_request Example: 10 |
| direction | string | No | newer (unseen) or older (history). If omitted: newer when no checkpoint yet, otherwise older. Always pass newer for feed polling. Example: newer |
| token | string | No | Filter by token symbol (case-insensitive) Example: BTC |
Code Examples
curl -X GET "https://api.upgate.online/api/v1/crypto/articles/translated/?lang=en&limit=10&direction=newer" \
-H "X-API-Key: your_api_key_here"Snapshot API
Returns the latest articles without tracking read history. Use for dashboards, cron jobs, and alerts. Deduplicate by original_id on your side.
Endpoint
GEThttps://api.upgate.online/api/v1/crypto/articles/translated/latest-snapshot/Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| lang | string | No | en or fa. Default: fa Example: en |
| limit | integer | No | 1–50. Default: 10 Example: 10 |
| token | string | No | Filter by token symbol Example: BTC |
Code Examples
curl -X GET "https://api.upgate.online/api/v1/crypto/articles/translated/latest-snapshot/?lang=en&limit=10&token=BTC" \
-H "X-API-Key: your_api_key_here"Response Format
Both endpoints return a JSON array of articles. There is no wrapper object.
Response
[{ "original_id": 2147, "title": "...", "meta": { "token_mentions": ["IRYS"], "sentiment": "positive" } }]Article fields
| Field | Type | Description |
|---|---|---|
| original_id | integer | Unique article ID — use for deduplication |
| language | string | en or fa |
| title | string | Translated headline |
| content | string | Translated body (Markdown supported; RTL when localized) |
| created_at | string (ISO 8601) | Translation creation time (UTC), not original publish time |
| meta.token_mentions | string[] | Detected token symbols e.g. ["BTC", "ETH"] |
| meta.source_name | string | Original source e.g. OKX, CoinDesk |
| meta.category | string | Topic category (see table below) |
| meta.sentiment | string | positive | negative | neutral |
| meta.thumbnail_url | string | Image Gateway URL: https://img.upgate.online/crypto/{id} |
| meta.has_watermark | boolean | Whether source image had a watermark |
Categories
| Label | Description |
|---|---|
| market_trends | Price action, market analysis, ETF flows |
| regulation_policy | Regulation, policy, legal news |
| project_updates | Upgrades, roadmaps, team announcements |
| defi | DeFi protocols and yields |
| nft | NFT markets and collections |
| memecoin | Meme coins and community tokens |
| exchanges | Listings, delistings, exchange updates |
| security_hacks | Hacks, exploits, vulnerabilities |
| adoption_partnerships | Adoption, partnerships, integrations |
| technology_innovation | L2, consensus, technical upgrades |
| mining_infrastructure | Mining, staking, infrastructure |
| macro_economy | Macro factors affecting crypto |
| unclassified | Low-confidence classification |
Languages
| Code | Language | Default |
|---|---|---|
| en | English | No |
| fa | Localized (RTL) | Yes |
Errors Cheat Sheet
What you see in production, what it means, and what to do next.
Response
HTTP 429
{
"detail": "Rate limit exceeded. Please wait 1 minutes between requests."
}
HTTP 200 (normal)
[]Symptoms & fixes
| What you see | Meaning | What to do |
|---|---|---|
| [] (empty array) | No new or matching articles | Normal — keep polling. Not an error. |
| HTTP 401 + detail | Invalid, inactive, or expired API key | Verify X-API-Key. Contact team@upgate.online if newly issued. |
| HTTP 429 + wait N minutes | frequency_minutes — too soon after last request | Wait N minutes, then retry. Add backoff in cron jobs. |
| HTTP 429 + daily limit | daily_limit exceeded for your API key | Stop polling until next UTC day or upgrade plan. |
| HTTP 400 + max items | limit param exceeds max_items_per_request | Lower the limit query param. |
| HTTP 400 + invalid lang | Unsupported lang code | Use en or fa only. |
| HTTP 500 | Server error | Retry with exponential backoff. Email team@upgate.online with X-Request-ID. |
| Docs demo limit message | Shared docs tester quota (not your key) | Use your own API key, or try again tomorrow. |
FAQ
Answers to the most common integration questions.
Frequently asked questions
Do you support webhooks?
No. Integrate via polling — ScrollBoost for feeds, Snapshot for cron jobs.
Which languages are supported?
en and fa language codes. Default is fa when lang is omitted.
Is there a sandbox?
No public sandbox. Contact team@upgate.online for an API key.
How do I filter by token?
Add ?token=BTC (case-insensitive) to either endpoint.
Rate Limits & Quotas
Per-client limits set at provisioning. Enforced on every request.
Limit types
| Limit | Description | HTTP code |
|---|---|---|
| frequency_minutes | Minimum wait between consecutive requests | 429 |
| daily_limit | Maximum requests per day | 429 |
| max_items_per_request | Maximum value of the limit parameter | 400 |
| access_expires_at | Key expiry date | 401 |
Support
Need help? Contact team@upgate.online with your X-Request-ID, endpoint path, and approximate request time.
