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_here

Contact the administrator to obtain an API key.

API Endpoints

MethodEndpointAuthDescription
GET/api/newsNoList all articles
POST/api/newsYesCreate new article
GET/api/news/[id]NoGet single article
GET/api/news/searchNoSearch articles
GET/api/news/statsNoGet 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_at are 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

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger20Articles per page (max 100)
sourcestring-Filter by source name
fromdate-Start date (ISO 8601)
todate-End date (ISO 8601)

GET /api/news/search

ParameterTypeDescription
qstringSearch query (min 2 characters, required)
pageintegerPage number (default: 1)
limitintegerResults 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 -lcurl

cURL (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_at timestamps 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.