Gateway to Global Information Streams
The LunarCrypto API provides access to translated cryptocurrency news articles from trusted global sources. Each client receives an API key with configurable limits on request frequency, items per request, and total daily usage.
High-quality translation for crypto news in multiple languages
ScrollBoost v1.1 with bidirectional pagination support
Enterprise-ready with SLA support and custom solutions
All API requests require authentication using an API key passed in the X-API-Key
header. Each client is assigned a unique API key with specific rate limits and access permissions.
If you don't have an API key, please contact your LunarFeed representative or reach out to [email protected] for client agreement and key provisioning.
X-API-Key: your_client_api_key
Accept: application/json
Fetch a list of translated cryptocurrency articles in the specified language. The latest ScrollBoost v1.1 update introduces smart scrolling with direction
support, enabling efficient pagination of both newer and older content.
direction
parameterParameter | Type | Required | Description |
---|---|---|---|
lang | string | Optional | Target language code (fa, it, en, arb). Default: fa |
limit | integer | Optional | Number of items to return (1-100). Default: 10 |
direction | string | Optional | Scroll direction: "newer" (latest) or "older" (previous) |
curl -X GET "https://api.lunarfeed.online/api/v1/crypto/articles/translated/?lang=en&limit=5&direction=newer" \
-H "X-API-Key: your_api_key_here" \
-H "Accept: application/json"
const response = await fetch(
'https://api.lunarfeed.online/api/v1/crypto/articles/translated/?lang=en&limit=10&direction=newer',
{
headers: {
'X-API-Key': 'your_api_key_here',
'Accept': 'application/json'
}
}
);
const articles = await response.json();
ScrollBoost v1.1 introduces intelligent pagination with bidirectional scrolling capabilities. The system uses checkpoint-based navigation for efficient content loading.
direction=newer
for latest contentdirection=older
for historical content (limited to the past 2 days)
import requests
API_KEY = "your_api_key_here"
BASE_URL = "https://api.lunarfeed.online/api/v1/crypto/articles/translated/"
def fetch_newer(limit=10):
response = requests.get(BASE_URL, headers={
"X-API-Key": API_KEY,
"Accept": "application/json"
}, params={
"limit": limit,
"direction": "newer"
})
response.raise_for_status()
articles = response.json()
if not articles:
print("No new articles available.")
else:
print(f"Fetched {len(articles)} newer articles.")
return articles
def fetch_older(limit=10):
response = requests.get(BASE_URL, headers={
"X-API-Key": API_KEY,
"Accept": "application/json"
}, params={
"limit": limit,
"direction": "older"
})
response.raise_for_status()
articles = response.json()
if not articles:
print("No more historical articles.")
else:
print(f"Fetched {len(articles)} older articles.")
return articles
Access real-time snapshots of translated crypto articles - clean, structured, and ready for instant use. Unlike the scroll-based feed, this endpoint is optimized for real-time system polling and ingestion. *Snapshot endpoint is stateless and always returns the latest available articles at the time of request.
GET https://api.lunarfeed.online/api/v1/crypto/articles/translated/latest-snapshot/
This endpoint returns the latest available batch of translated crypto news, ideal for systems that need to sync once every few minutes without managing scroll state.
Parameter | Type | Required | Description |
---|---|---|---|
lang | string | Optional | Target translation language (en, fa, it, arb) |
limit | integer | Optional | Max number of items to return. Default: 20 |
If no language is provided, the default translation is used.
curl -X GET "https://api.lunarfeed.online/api/v1/crypto/articles/translated/latest-snapshot/?lang=en&limit=10" \
-H "X-API-Key: your_api_key_here" \
-H "Accept: application/json"
// Real-time polling example
const pollSnapshots = async () => {
try {
const response = await fetch(
'https://api.lunarfeed.online/api/v1/crypto/articles/translated/latest-snapshot/?lang=en&limit=20',
{
headers: {
'X-API-Key': 'your_api_key_here',
'Accept': 'application/json'
}
}
);
const articles = await response.json();
console.log(`Received ${articles.length} articles`);
// Process articles for your system
processArticles(articles);
} catch (error) {
console.error('Snapshot polling failed:', error);
}
};
// Poll every 5 minutes
setInterval(pollSnapshots, 5 * 60 * 1000);
import requests
import time
def fetch_snapshot(lang='en', limit=20):
headers = {
"X-API-Key": "your_api_key_here",
"Accept": "application/json"
}
params = {
"lang": lang,
"limit": limit
}
response = requests.get(
"https://api.lunarfeed.online/api/v1/crypto/articles/translated/latest-snapshot/",
headers=headers,
params=params
)
return response.json()
# Real-time ingestion loop
while True:
try:
articles = fetch_snapshot()
print(f"Ingested {len(articles)} articles")
# Process articles for your system
process_articles(articles)
# Wait 5 minutes before next poll
time.sleep(300)
except Exception as e:
print(f"Error: {e}")
time.sleep(60) # Wait 1 minute on error
[
{
"id": "654abc123def456",
"title_translated": "Bitcoin Hits New High Amid Institutional Interest",
"summary_translated": "Bitcoin crosses $70,000 as major institutions announce new crypto investment strategies...",
"language": "en",
"original_source": "https://cryptonews.example.com/bitcoin-institutional-interest",
"created_at": "2025-07-08T10:34:00Z"
},
{
"id": "789ghi456jkl123",
"title_translated": "Ethereum Network Upgrade Shows Promising Results",
"summary_translated": "The latest Ethereum upgrade demonstrates improved transaction speeds and reduced gas fees...",
"language": "en",
"original_source": "https://blockchain.example.com/ethereum-upgrade-results",
"created_at": "2025-07-08T10:28:15Z"
}
]
The API returns a JSON array of article objects. Each article contains standardized fields for easy integration and rendering in your application.
[
{
"original_id": 1800,
"language": "en",
"translated_title": "Bitcoin Reaches New All-Time High Amid Institutional Adoption",
"translated_content": "### Market Analysis\n\nBitcoin has surged to unprecedented levels...",
"created_at": "2025-06-27T07:06:37.558344",
"meta": {
"token_mentioned": "BTC",
"has_watermark": false,
"thumbnail_url": "https://cdn.lunarfeed.com/thumbnails/1800.jpg"
}
}
]
Complete reference for all fields returned in article objects. Understanding these fields will help you integrate and display content effectively in your application.
Field | Type | Description | Example |
---|---|---|---|
original_id | integer | Unique identifier for the original article | 1800 |
language | string | Target translation language code | en |
translated_title | string | Article title in requested language | Bitcoin Reaches New High |
translated_content | string | Full article content with markdown formatting | ### Analysis\\n\\nBitcoin has... |
created_at | string | ISO 8601 timestamp of article creation | 2025-06-27T07:06:37.558344 |
meta | object | Additional metadata about the article | { token_mentioned: 'BTC' } |
meta.token_mentioned | string | Primary cryptocurrency token discussed | BTC, ETH, ADA |
meta.has_watermark | boolean | Whether article contains watermark | false |
meta.thumbnail_url | string | URL to article thumbnail image | https://cdn.lunarfeed.com/... |
original_id
for deduplication and cachingtoken_mentioned
helps with content categorizationcreated_at
is in UTC timezonethumbnail_url
may be null for some articlesThe API uses standard HTTP status codes and returns structured error responses. Proper error handling ensures robust integration with your application.
400
- Bad Request (invalid parameters)401
- Unauthorized (invalid API key)429
- Rate limit exceeded500
- Internal server error{
"detail": "Invalid API key"
}
import requests
def fetch_articles(api_key: str, lang: str = 'en', limit: int = 10):
"""
Fetch translated cryptocurrency articles from LunarFeed API.
Args:
api_key (str): Your LunarFeed API key.
lang (str): Target language for translation (default: 'en').
limit (int): Number of articles to fetch (default: 10).
Returns:
list: List of translated article objects.
Raises:
Exception: If the request fails or the API returns an error.
"""
url = "https://api.lunarfeed.online/api/v1/crypto/articles/translated/"
headers = {
"X-API-Key": api_key,
"Accept": "application/json"
}
params = {
"lang": lang,
"limit": limit
}
try:
response = requests.get(url, headers=headers, params=params)
# Check for HTTP errors
if response.status_code != 200:
try:
error_data = response.json()
detail = error_data.get("detail", "Unknown error")
raise Exception(f"Error {response.status_code}: {detail}")
except ValueError:
raise Exception(f"Error {response.status_code}: Unable to parse error response")
# Return parsed JSON data
return response.json()
except requests.exceptions.RequestException as e:
raise Exception(f"Request failed: {str(e)}")
Ready-to-use code examples and libraries for popular programming languages. These examples include error handling, rate limiting, and best practices.
Full-featured Python library
NPM package with TypeScript
Ready-to-import API collection
import requests
import time
from typing import Optional, List, Dict
class LunarFeedClient:
def __init__(self, api_key: str, base_url: str = "https://api.lunarfeed.online"):
self.api_key = api_key
self.base_url = base_url
self.session = requests.Session()
self.session.headers.update({
"X-API-Key": api_key,
"Accept": "application/json"
})
def get_articles(self, lang: str = "en", limit: int = 10,
direction: str = "newer") -> List[Dict]:
"""Fetch translated crypto articles"""
params = {
"lang": lang,
"limit": limit,
"direction": direction
}
response = self.session.get(
f"{self.base_url}/api/v1/crypto/articles/translated/",
params=params
)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
raise Exception(f"Rate limited. Retry after {retry_after} seconds")
response.raise_for_status()
return response.json()
def get_snapshot(self, lang: str = "en", limit: int = 20) -> List[Dict]:
"""Get latest snapshot of articles"""
params = {"lang": lang, "limit": limit}
response = self.session.get(
f"{self.base_url}/api/v1/crypto/articles/translated/latest-snapshot/",
params=params
)
response.raise_for_status()
return response.json()
# Usage example
client = LunarFeedClient("your_api_key_here")
try:
articles = client.get_articles(lang="en", limit=5)
print(f"Fetched {len(articles)} articles")
for article in articles:
print(f"- {article['translated_title']}")
except Exception as e:
print(f"Error: {e}")
<?php
class LunarFeedClient {
private $apiKey;
private $baseUrl;
public function __construct($apiKey, $baseUrl = 'https://api.lunarfeed.online') {
$this->apiKey = $apiKey;
$this->baseUrl = $baseUrl;
}
public function getArticles($lang = 'en', $limit = 10, $direction = 'newer') {
$params = http_build_query([
'lang' => $lang,
'limit' => $limit,
'direction' => $direction
]);
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => [
"X-API-Key: {$this->apiKey}",
"Accept: application/json"
]
]
]);
$url = "{$this->baseUrl}/api/v1/crypto/articles/translated/?{$params}";
$response = file_get_contents($url, false, $context);
if ($response === false) {
throw new Exception('Failed to fetch articles');
}
return json_decode($response, true);
}
public function getSnapshot($lang = 'en', $limit = 20) {
$params = http_build_query(['lang' => $lang, 'limit' => $limit]);
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => [
"X-API-Key: {$this->apiKey}",
"Accept: application/json"
]
]
]);
$url = "{$this->baseUrl}/api/v1/crypto/articles/translated/latest-snapshot/?{$params}";
$response = file_get_contents($url, false, $context);
return json_decode($response, true);
}
}
// Usage
$client = new LunarFeedClient('your_api_key_here');
try {
$articles = $client->getArticles('en', 5);
echo "Fetched " . count($articles) . " articles\n";
foreach ($articles as $article) {
echo "- " . $article['translated_title'] . "\n";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"
)
type LunarFeedClient struct {
APIKey string
BaseURL string
Client *http.Client
}
type Article struct {
OriginalID int `json:"original_id"`
Language string `json:"language"`
TranslatedTitle string `json:"translated_title"`
TranslatedContent string `json:"translated_content"`
CreatedAt string `json:"created_at"`
Meta struct {
TokenMentioned string `json:"token_mentioned"`
HasWatermark bool `json:"has_watermark"`
ThumbnailURL string `json:"thumbnail_url"`
} `json:"meta"`
}
func NewLunarFeedClient(apiKey string) *LunarFeedClient {
return &LunarFeedClient{
APIKey: apiKey,
BaseURL: "https://api.lunarfeed.online",
Client: &http.Client{Timeout: 30 * time.Second},
}
}
func (c *LunarFeedClient) GetArticles(lang string, limit int, direction string) ([]Article, error) {
params := url.Values{}
params.Add("lang", lang)
params.Add("limit", fmt.Sprintf("%d", limit))
params.Add("direction", direction)
reqURL := fmt.Sprintf("%s/api/v1/crypto/articles/translated/?%s", c.BaseURL, params.Encode())
req, err := http.NewRequest("GET", reqURL, nil)
if err != nil {
return nil, err
}
req.Header.Set("X-API-Key", c.APIKey)
req.Header.Set("Accept", "application/json")
resp, err := c.Client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("API request failed with status %d", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var articles []Article
err = json.Unmarshal(body, &articles)
return articles, err
}
func main() {
client := NewLunarFeedClient("your_api_key_here")
articles, err := client.GetArticles("en", 5, "newer")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Fetched %d articles\n", len(articles))
for _, article := range articles {
fmt.Printf("- %s\n", article.TranslatedTitle)
}
}
Optimize your integration with these performance tips and best practices. Proper implementation ensures efficient resource usage and better user experience.
original_id
limit
values (10-50 recommended)class LunarFeedCache {
constructor(ttl = 300000) { // 5 minutes default TTL
this.cache = new Map();
this.ttl = ttl;
}
set(key, value) {
this.cache.set(key, {
value,
timestamp: Date.now()
});
}
get(key) {
const item = this.cache.get(key);
if (!item) return null;
if (Date.now() - item.timestamp > this.ttl) {
this.cache.delete(key);
return null;
}
return item.value;
}
clear() {
this.cache.clear();
}
}
class OptimizedLunarFeedClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.cache = new LunarFeedCache();
this.requestQueue = [];
this.processing = false;
}
async getArticles(params = {}) {
const cacheKey = JSON.stringify(params);
const cached = this.cache.get(cacheKey);
if (cached) {
console.log('Returning cached result');
return cached;
}
const articles = await this.fetchArticles(params);
this.cache.set(cacheKey, articles);
return articles;
}
async fetchArticles(params) {
const queryString = new URLSearchParams(params).toString();
const response = await fetch(
`https://api.lunarfeed.online/api/v1/crypto/articles/translated/?${queryString}`,
{
headers: {
'X-API-Key': this.apiKey,
'Accept': 'application/json',
'Accept-Encoding': 'gzip'
}
}
);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.json();
}
}
import requests
import time
import json
from typing import Optional
class LunarFeedCache:
def __init__(self, ttl: int = 300): # Default TTL: 5 minutes (in seconds)
self.cache = {}
self.ttl = ttl
def set(self, key: str, value: dict):
self.cache[key] = {
'value': value,
'timestamp': time.time()
}
def get(self, key: str) -> Optional[dict]:
item = self.cache.get(key)
if not item:
return None
if time.time() - item['timestamp'] > self.ttl:
del self.cache[key]
return None
return item['value']
def clear(self):
self.cache.clear()
class OptimizedLunarFeedClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.cache = LunarFeedCache()
self.base_url = "https://api.lunarfeed.online"
def get_articles(self, lang: str = "en", limit: int = 10, direction: str = "newer"):
params = {
"lang": lang,
"limit": limit,
"direction": direction
}
cache_key = json.dumps(params, sort_keys=True)
cached = self.cache.get(cache_key)
if cached:
print("🔁 Returning cached result")
return cached
url = f"{self.base_url}/api/v1/crypto/articles/translated/"
headers = {
"X-API-Key": self.api_key,
"Accept": "application/json",
"Accept-Encoding": "gzip"
}
response = requests.get(url, headers=headers, params=params)
if response.status_code != 200:
raise Exception(f"HTTP {response.status_code}: {response.text}")
data = response.json()
self.cache.set(cache_key, data)
return data
# Usage Example
client = OptimizedLunarFeedClient("your_api_key_here")
try:
articles = client.get_articles(lang="en", limit=5)
print(f"✅ Fetched {len(articles)} articles")
except Exception as e:
print(f"❌ Error: {e}")
class RateLimitedClient {
constructor(apiKey, requestsPerMinute = 60) {
this.apiKey = apiKey;
this.requestsPerMinute = requestsPerMinute;
this.requestTimes = [];
}
async makeRequest(url, options = {}) {
await this.waitForRateLimit();
const response = await fetch(url, {
...options,
headers: {
'X-API-Key': this.apiKey,
'Accept': 'application/json',
...options.headers
}
});
this.requestTimes.push(Date.now());
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
console.log(`Rate limited. Waiting ${retryAfter} seconds...`);
await this.sleep(retryAfter * 1000);
return this.makeRequest(url, options); // Retry
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}
async waitForRateLimit() {
const now = Date.now();
const oneMinuteAgo = now - 60000;
// Remove old requests
this.requestTimes = this.requestTimes.filter(time => time > oneMinuteAgo);
if (this.requestTimes.length >= this.requestsPerMinute) {
const oldestRequest = this.requestTimes[0];
const waitTime = 60000 - (now - oldestRequest);
if (waitTime > 0) {
console.log(`Rate limit reached. Waiting ${waitTime}ms...`);
await this.sleep(waitTime);
}
}
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
import time
import requests
from collections import deque
from typing import Optional
class RateLimitedClient:
def __init__(self, api_key: str, requests_per_minute: int = 60):
self.api_key = api_key
self.requests_per_minute = requests_per_minute
self.request_times = deque()
def _wait_for_rate_limit(self):
now = time.time()
one_minute_ago = now - 60
# Remove outdated timestamps
while self.request_times and self.request_times[0] < one_minute_ago:
self.request_times.popleft()
if len(self.request_times) >= self.requests_per_minute:
oldest = self.request_times[0]
wait_time = 60 - (now - oldest)
if wait_time > 0:
print(f"⏳ Rate limit reached. Waiting {int(wait_time)} seconds...")
time.sleep(wait_time)
def make_request(self, url: str, params: Optional[dict] = None) -> dict:
self._wait_for_rate_limit()
headers = {
"X-API-Key": self.api_key,
"Accept": "application/json"
}
try:
response = requests.get(url, headers=headers, params=params)
self.request_times.append(time.time())
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
print(f"🚫 Rate limited. Retrying in {retry_after} seconds...")
time.sleep(retry_after)
return self.make_request(url, params) # Retry
response.raise_for_status()
return response.json()
except requests.RequestException as e:
print(f"❌ Request failed: {e}")
raise
# Usage Example
if __name__ == "__main__":
client = RateLimitedClient("your_api_key_here", requests_per_minute=60)
try:
result = client.make_request(
"https://api.lunarfeed.online/api/v1/crypto/articles/translated/",
params={"lang": "en", "limit": 5}
)
print(f"✅ Fetched {len(result)} articles")
except Exception as e:
print(f"❌ Error: {e}")
© 2025 LunarFeed. All rights reserved. | Empowering localized news intelligence across global markets.