API Documentation
Overview
The Financial News API allows you to programmatically submit news articles from various sources. Articles are stored in our database and made searchable through our web interface.
Authentication
All POST requests require an API key. Include your API key in the request header:
X-API-Key: your_api_key_hereContact the administrator to obtain an API key.
API Endpoints
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET | /api/news | No | List all articles |
POST | /api/news | Yes | Create new article |
GET | /api/news/[id] | No | Get single article |
GET | /api/news/search | No | Search articles |
GET | /api/news/stats | No | Get daily statistics |
Submission Rules
Important Guidelines
- Unique URLs: Each article must have a unique
source_url. Duplicate URLs will be rejected. - Required Fields: All fields except
published_atare required. - Content Quality: Submit only legitimate financial news from reputable sources.
- Timestamps: Use ISO 8601 format for dates (e.g.,
2025-12-10T14:30:00Z). - Rate Limiting: Limit requests to 100 per minute per API key.
- Content Length: Title max 500 characters, content has no hard limit but keep it reasonable.
Request Format
POST /api/news
Create a new news article.
Request Body (JSON)
{
"title": "Article headline (required, max 500 chars)",
"content": "Full article content (required)",
"source": "Source name, e.g., Reuters (required)",
"source_url": "Original article URL (required, must be unique)",
"published_at": "ISO 8601 timestamp (optional, defaults to now)"
}Response (201 Created)
{
"data": {
"id": "uuid-of-created-article",
"title": "Article headline",
"content": "Full article content",
"source": "Reuters",
"sourceUrl": "https://example.com/article",
"publishedAt": "2025-12-10T14:30:00.000Z",
"createdAt": "2025-12-10T14:35:00.000Z",
"updatedAt": "2025-12-10T14:35:00.000Z"
}
}Error Responses
// 401 Unauthorized - Missing or invalid API key
{ "error": "Invalid or expired API key" }
// 400 Bad Request - Missing required fields
{ "error": "Missing required fields: title, content, source, source_url" }
// 200 OK - Duplicate article (not an error, but no new record created)
{ "message": "Article already exists", "duplicate": true }Query Parameters
GET /api/news
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 20 | Articles per page (max 100) |
source | string | - | Filter by source name |
from | date | - | Start date (ISO 8601) |
to | date | - | End date (ISO 8601) |
GET /api/news/search
| Parameter | Type | Description |
|---|---|---|
q | string | Search query (min 2 characters, required) |
page | integer | Page number (default: 1) |
limit | integer | Results per page (default: 20, max: 100) |
Code Examples
Python
import requests
import json
from datetime import datetime
API_URL = "https://2daysnews.net/api/news"
API_KEY = "news_5acf3a3c53fe3f34c0b44b3b4ffcdb14"
def post_news_article(title, content, source, source_url, published_at=None):
"""Post a news article to the API."""
headers = {
"Content-Type": "application/json",
"X-API-Key": API_KEY
}
payload = {
"title": title,
"content": content,
"source": source,
"source_url": source_url,
}
if published_at:
payload["published_at"] = published_at.isoformat() + "Z"
response = requests.post(API_URL, headers=headers, json=payload)
if response.status_code == 201:
print("Article created successfully!")
return response.json()["data"]
elif response.status_code == 200:
print("Article already exists (duplicate URL)")
return None
else:
print(f"Error: {response.status_code} - {response.text}")
return None
# Example usage
article = post_news_article(
title="Fed Announces Rate Decision",
content="The Federal Reserve announced today that...",
source="Reuters",
source_url="https://reuters.com/article/fed-rates-2025",
published_at=datetime.utcnow()
)
if article:
print(f"Created article ID: {article['id']}")JavaScript (Node.js)
const API_URL = 'https://2daysnews.net/api/news';
const API_KEY = 'news_5acf3a3c53fe3f34c0b44b3b4ffcdb14';
async function postNewsArticle({ title, content, source, sourceUrl, publishedAt }) {
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY,
},
body: JSON.stringify({
title,
content,
source,
source_url: sourceUrl,
published_at: publishedAt || new Date().toISOString(),
}),
});
const data = await response.json();
if (response.status === 201) {
console.log('Article created successfully!');
return data.data;
} else if (response.status === 200 && data.duplicate) {
console.log('Article already exists (duplicate URL)');
return null;
} else {
throw new Error(data.error || 'Failed to create article');
}
}
// Example usage
postNewsArticle({
title: 'Bitcoin Surges Past $100,000',
content: 'Bitcoin has broken through the $100,000 barrier...',
source: 'Bloomberg',
sourceUrl: 'https://bloomberg.com/news/bitcoin-100k',
publishedAt: new Date().toISOString(),
})
.then((article) => {
if (article) console.log('Created article ID:', article.id);
})
.catch(console.error);JavaScript (Browser/Fetch)
// Browser-compatible version
async function postNews(apiKey, article) {
const response = await fetch('/api/news', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
},
body: JSON.stringify({
title: article.title,
content: article.content,
source: article.source,
source_url: article.sourceUrl,
published_at: article.publishedAt,
}),
});
return response.json();
}
// Example
const result = await postNews('news_5acf3a3c53fe3f34c0b44b3b4ffcdb14', {
title: 'Market Update',
content: 'Stocks rose today...',
source: 'CNBC',
sourceUrl: 'https://cnbc.com/market-update',
});C#
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public class NewsApiClient
{
private readonly HttpClient _client;
private readonly string _apiUrl;
private readonly string _apiKey;
public NewsApiClient(string apiUrl, string apiKey)
{
_apiUrl = apiUrl;
_apiKey = apiKey;
_client = new HttpClient();
_client.DefaultRequestHeaders.Add("X-API-Key", _apiKey);
}
public async Task<NewsArticle?> PostArticleAsync(
string title,
string content,
string source,
string sourceUrl,
DateTime? publishedAt = null)
{
var payload = new
{
title,
content,
source,
source_url = sourceUrl,
published_at = publishedAt?.ToString("o") ?? DateTime.UtcNow.ToString("o")
};
var json = JsonSerializer.Serialize(payload);
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _client.PostAsync(_apiUrl, httpContent);
var responseBody = await response.Content.ReadAsStringAsync();
if (response.StatusCode == System.Net.HttpStatusCode.Created)
{
var result = JsonSerializer.Deserialize<ApiResponse>(responseBody);
Console.WriteLine("Article created successfully!");
return result?.Data;
}
else if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
Console.WriteLine("Article already exists (duplicate URL)");
return null;
}
else
{
throw new Exception($"API Error: {response.StatusCode} - {responseBody}");
}
}
}
public class NewsArticle
{
public string Id { get; set; } = "";
public string Title { get; set; } = "";
public string Content { get; set; } = "";
public string Source { get; set; } = "";
public string SourceUrl { get; set; } = "";
public DateTime PublishedAt { get; set; }
}
public class ApiResponse
{
public NewsArticle? Data { get; set; }
}
// Example usage:
// var client = new NewsApiClient("https://2daysnews.net/api/news", "news_5acf3a3c53fe3f34c0b44b3b4ffcdb14");
// var article = await client.PostArticleAsync(
// "Tech Stocks Rally",
// "Major technology stocks posted gains...",
// "CNBC",
// "https://cnbc.com/tech-rally"
// );C++ (using libcurl)
#include <iostream>
#include <string>
#include <curl/curl.h>
// Callback function for curl
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {
size_t totalSize = size * nmemb;
output->append((char*)contents, totalSize);
return totalSize;
}
class NewsApiClient {
private:
std::string apiUrl;
std::string apiKey;
public:
NewsApiClient(const std::string& url, const std::string& key)
: apiUrl(url), apiKey(key) {}
bool postArticle(const std::string& title,
const std::string& content,
const std::string& source,
const std::string& sourceUrl,
const std::string& publishedAt = "") {
CURL* curl = curl_easy_init();
if (!curl) {
std::cerr << "Failed to initialize CURL" << std::endl;
return false;
}
// Build JSON payload
std::string json = "{"
"\"title\": \"" + escapeJson(title) + "\","
"\"content\": \"" + escapeJson(content) + "\","
"\"source\": \"" + escapeJson(source) + "\","
"\"source_url\": \"" + escapeJson(sourceUrl) + "\"";
if (!publishedAt.empty()) {
json += ",\"published_at\": \"" + publishedAt + "\"";
}
json += "}";
std::string response;
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, ("X-API-Key: " + apiKey).c_str());
curl_easy_setopt(curl, CURLOPT_URL, apiUrl.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
CURLcode res = curl_easy_perform(curl);
long httpCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
if (res != CURLE_OK) {
std::cerr << "CURL error: " << curl_easy_strerror(res) << std::endl;
return false;
}
if (httpCode == 201) {
std::cout << "Article created successfully!" << std::endl;
std::cout << "Response: " << response << std::endl;
return true;
} else if (httpCode == 200) {
std::cout << "Article already exists (duplicate URL)" << std::endl;
return true;
} else {
std::cerr << "Error " << httpCode << ": " << response << std::endl;
return false;
}
}
private:
std::string escapeJson(const std::string& str) {
std::string result;
for (char c : str) {
switch (c) {
case '"': result += "\\\""; break;
case '\\': result += "\\\\"; break;
case '\n': result += "\\n"; break;
case '\r': result += "\\r"; break;
case '\t': result += "\\t"; break;
default: result += c;
}
}
return result;
}
};
// Example usage:
// int main() {
// NewsApiClient client("https://2daysnews.net/api/news", "news_5acf3a3c53fe3f34c0b44b3b4ffcdb14");
// client.postArticle(
// "Market Update",
// "Stocks rose today amid positive earnings...",
// "Reuters",
// "https://reuters.com/market-update-2025"
// );
// return 0;
// }
//
// Compile with: g++ -o news_client news_client.cpp -lcurlcURL (Command Line)
# Post a new article
curl -X POST https://2daysnews.net/api/news \
-H "Content-Type: application/json" \
-H "X-API-Key: news_5acf3a3c53fe3f34c0b44b3b4ffcdb14" \
-d '{
"title": "Fed Announces Rate Decision",
"content": "The Federal Reserve announced today...",
"source": "Reuters",
"source_url": "https://reuters.com/fed-rates-2025",
"published_at": "2025-12-10T14:30:00Z"
}'
# Get all articles
curl https://2daysnews.net/api/news
# Get articles with pagination and filters
curl "https://2daysnews.net/api/news?page=1&limit=10&source=Reuters"
# Search articles
curl "https://2daysnews.net/api/news/search?q=bitcoin"
# Get a specific article
curl https://2daysnews.net/api/news/article-uuid-here
# Get daily statistics
curl "https://2daysnews.net/api/news/stats?days=7"Best Practices
- Error Handling: Always check response status codes and handle errors gracefully.
- Deduplication: Check for duplicate URLs before submitting to reduce unnecessary API calls.
- Timestamps: Always include accurate
published_attimestamps for proper chronological ordering. - Batching: If submitting many articles, add delays between requests to avoid rate limiting.
- API Key Security: Never expose your API key in client-side code or public repositories.
- Content Formatting: Strip unnecessary HTML and submit clean text content.
Support
For API access requests, bug reports, or questions, please contact the administrator.