Athena News API Documentation
FeaturesPricingContact UsCreate AccountSign In
Athena API v2
Athena API v2
  • About Athena News API
  • v2 Change Summary
  • Account Overview
    • Account Overview
    • Dashboard
    • News Search
    • API Key
    • Account Settings
    • Manage Subscription
  • Getting Started
    • API Quickstart
    • Intro to Building a Query
    • API Reference
      • News Search
      • Headlines (BETA)
    • Data Model Reference
      • Articles
      • Entities
    • Supported Languages
    • Rate Limits
    • Troubleshooting
Powered by GitBook
On this page
  • Using Async Query Endpoint
  • Using Synchronous Endpoint
  1. Getting Started

API Quickstart

PreviousManage SubscriptionNextIntro to Building a Query

Last updated 3 months ago

Making your first request with the Athena API is straightforward with this script.

There are two examples provided below. The first, and recommended method, is using our /api/v2/query-async endpoint. The second method uses our /api/v2/query endpoint, which is geared towards small searches.

Using Async Query Endpoint

The initial request is sent via a POST call to Athena’s query-async API endpoint. The response contains your query_id, which is how you will retrieve results from your search with the /api/v2/get-results endpoint.

import time
import requests

# Constants
ATHENA_API_KEY = "YOUR_API_KEY"
QUERY = "donald trump"
start_date = "2025-03-04T15:13:52.466Z"
end_date = "2025-03-05T15:13:52.466Z"
QUERY_URL = "https://app.runathena.com/api/v2/query-async"
RESULTS_URL = "https://app.runathena.com/api/v2/get-results"
HEADERS = {"Content-Type": "application/json"}
ARTICLES_PER_PAGE = 25
POLL_INTERVAL = 1  # seconds to wait between polls

def send_initial_query(query: str, api_key: str) -> str:
    """
    Sends the initial query to the API and returns the query_id.
    """
    payload = {"query": query, "api_key": api_key,'toggle_state':'Encoded Articles',"start_date":start_date,"end_date":end_date}
    response = requests.post(QUERY_URL, headers=HEADERS, json=payload)
    response.raise_for_status()  # raise an error for bad responses
    data = response.json()
    return data.get('query_id')

def poll_for_results(query_id: str, api_key: str, interval: int = POLL_INTERVAL) -> dict:
    """
    Polls the API until the query status is not 'PENDING'.
    Returns the final result data.
    """
    payload = {"query_id": query_id, "api_key": api_key}
    response = requests.post(RESULTS_URL, headers=HEADERS, json=payload)
    response.raise_for_status()
    data = response.json()
    
    # Poll until the status changes from 'PENDING'
    while data.get('state') == 'PENDING':
        time.sleep(interval)
        response = requests.post(RESULTS_URL, headers=HEADERS, json=payload)
        response.raise_for_status()
        data = response.json()
    
    return data

def fetch_all_articles(query_id: str, total_results: int, api_key: str) -> list:
    """
    Fetches and aggregates all articles by paginating through the results.
    """
    all_articles = []
    page = 1
    payload = {"query_id": query_id, "api_key": api_key,'toggle_state':'Encoded Articles'}
    
    # Continue fetching while there are articles remaining.
    while (page - 1) * ARTICLES_PER_PAGE < total_results:
        payload['page'] = page
        response = requests.post(RESULTS_URL, headers=HEADERS, json=payload)
        response.raise_for_status()
        data = response.json()
        
        articles = data.get('articles', [])
        all_articles.extend(articles)
        page += 1
    
    return all_articles

def main():
    try:
        # Step 1: Send the initial query and retrieve the query_id.
        query_id = send_initial_query(QUERY, ATHENA_API_KEY)
        if not query_id:
            print("Failed to retrieve query ID.")
            return
        
        # Step 2: Poll the API until the query is processed.
        result_data = poll_for_results(query_id, ATHENA_API_KEY)
        
        #print(result_data)
        #print(result_data.keys())
        # Check if the query was successful before pagination.
        if result_data.get('state') != 'SUCCESS':
            print("Query did not complete successfully:", result_data)
            return
        
        total_results = result_data.get('totalArticles', 0)
        if total_results == 0:
            print("No results found.")
            return
        
        # Step 3: Paginate through the results and collect all articles.
        all_articles = fetch_all_articles(query_id, total_results, ATHENA_API_KEY)
        print("Total articles fetched:", len(all_articles))
    
    except requests.RequestException as e:
        print("An error occurred while communicating with the API:", e)

if __name__ == '__main__':
    main()
```
// Constants
const ATHENA_API_KEY = "YOUR_API_KEY";
const QUERY = "donald trump";
const start_date = "2025-03-04T15:13:52.466Z";
const end_date = "2025-03-05T15:13:52.466Z";
const QUERY_URL = "https://app.runathena.com/api/v2/query-async";
const RESULTS_URL = "https://app.runathena.com/api/v2/get-results";
const HEADERS = { "Content-Type": "application/json" };
const ARTICLES_PER_PAGE = 25;
const POLL_INTERVAL = 1000; // milliseconds

// Helper sleep function
function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function sendInitialQuery(query, apiKey) {
  const payload = {
    query: query,
    api_key: apiKey,
    toggle_state: 'Encoded Articles',
    start_date: start_date,
    end_date: end_date
  };

  const response = await fetch(QUERY_URL, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify(payload)
  });

  if (!response.ok) {
    throw new Error(`Network error: ${response.statusText}`);
  }

  const data = await response.json();
  return data.query_id;
}

async function pollForResults(queryId, apiKey, interval = POLL_INTERVAL) {
  const payload = {
    query_id: queryId,
    api_key: apiKey
  };

  let response = await fetch(RESULTS_URL, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify(payload)
  });
  if (!response.ok) {
    throw new Error(`Network error: ${response.statusText}`);
  }
  let data = await response.json();

  // Poll until the state is not 'PENDING'
  while (data.state === 'PENDING') {
    await sleep(interval);
    response = await fetch(RESULTS_URL, {
      method: "POST",
      headers: HEADERS,
      body: JSON.stringify(payload)
    });
    if (!response.ok) {
      throw new Error(`Network error: ${response.statusText}`);
    }
    data = await response.json();
  }

  return data;
}

async function fetchAllArticles(queryId, totalResults, apiKey) {
  let allArticles = [];
  let page = 1;

  // Continue fetching while there are articles remaining.
  while ((page - 1) * ARTICLES_PER_PAGE < totalResults) {
    const payload = {
      query_id: queryId,
      api_key: apiKey,
      toggle_state: 'Encoded Articles',
      page: page
    };

    const response = await fetch(RESULTS_URL, {
      method: "POST",
      headers: HEADERS,
      body: JSON.stringify(payload)
    });

    if (!response.ok) {
      throw new Error(`Network error: ${response.statusText}`);
    }
    const data = await response.json();

    const articles = data.articles || [];
    allArticles.push(...articles);
    page++;
  }

  return allArticles;
}

async function main() {
  try {
    // Step 1: Send the initial query and retrieve the query_id.
    const queryId = await sendInitialQuery(QUERY, ATHENA_API_KEY);
    if (!queryId) {
      console.log("Failed to retrieve query ID.");
      return;
    }

    // Step 2: Poll the API until the query is processed.
    const resultData = await pollForResults(queryId, ATHENA_API_KEY);

    // Check if the query was successful before pagination.
    if (resultData.state !== 'SUCCESS') {
      console.log("Query did not complete successfully:", resultData);
      return;
    }

    const totalResults = resultData.totalArticles || 0;
    if (totalResults === 0) {
      console.log("No results found.");
      return;
    }

    // Step 3: Paginate through the results and collect all articles.
    const allArticles = await fetchAllArticles(queryId, totalResults, ATHENA_API_KEY);
    console.log("Total articles fetched:", allArticles.length);
  } catch (error) {
    console.error("An error occurred while communicating with the API:", error);
  }
}

main();
<?php

// Constants
define('ATHENA_API_KEY', 'YOUR_API_KEY');
define('QUERY', 'donald trump');
define('START_DATE', '2025-03-04T15:13:52.466Z');
define('END_DATE', '2025-03-05T15:13:52.466Z');
define('QUERY_URL', 'https://app.runathena.com/api/v2/query-async');
define('RESULTS_URL', 'https://app.runathena.com/api/v2/get-results');
define('ARTICLES_PER_PAGE', 25);
define('POLL_INTERVAL', 1); // seconds

/**
 * Send the initial query and return the query_id.
 *
 * @param string $query
 * @param string $apiKey
 * @return string|null
 * @throws Exception if the request fails
 */
function sendInitialQuery($query, $apiKey) {
    $payload = [
        "query"         => $query,
        "api_key"       => $apiKey,
        "toggle_state"  => "Encoded Articles",
        "start_date"    => START_DATE,
        "end_date"      => END_DATE
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, QUERY_URL);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));

    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        throw new Exception('Request Error: ' . curl_error($ch));
    }
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode < 200 || $httpCode >= 300) {
        throw new Exception("HTTP error: $httpCode");
    }

    $data = json_decode($response, true);
    return isset($data['query_id']) ? $data['query_id'] : null;
}

/**
 * Polls the API until the query state is no longer 'PENDING'.
 *
 * @param string $queryId
 * @param string $apiKey
 * @param int $interval
 * @return array
 * @throws Exception if the request fails
 */
function pollForResults($queryId, $apiKey, $interval = POLL_INTERVAL) {
    $payload = [
        "query_id" => $queryId,
        "api_key"  => $apiKey
    ];

    do {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, RESULTS_URL);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));

        $response = curl_exec($ch);
        if (curl_errno($ch)) {
            throw new Exception('Request Error: ' . curl_error($ch));
        }
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode < 200 || $httpCode >= 300) {
            throw new Exception("HTTP error: $httpCode");
        }

        $data = json_decode($response, true);

        if (isset($data['state']) && $data['state'] === 'PENDING') {
            sleep($interval);
        } else {
            return $data;
        }
    } while (true);
}

/**
 * Fetches all articles by paginating through the results.
 *
 * @param string $queryId
 * @param int $totalResults
 * @param string $apiKey
 * @return array
 * @throws Exception if the request fails
 */
function fetchAllArticles($queryId, $totalResults, $apiKey) {
    $allArticles = [];
    $page = 1;

    while ((($page - 1) * ARTICLES_PER_PAGE) < $totalResults) {
        $payload = [
            "query_id"      => $queryId,
            "api_key"       => $apiKey,
            "toggle_state"  => "Encoded Articles",
            "page"          => $page
        ];

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, RESULTS_URL);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));

        $response = curl_exec($ch);
        if (curl_errno($ch)) {
            throw new Exception('Request Error: ' . curl_error($ch));
        }
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode < 200 || $httpCode >= 300) {
            throw new Exception("HTTP error: $httpCode");
        }

        $data = json_decode($response, true);
        $articles = isset($data['articles']) ? $data['articles'] : [];
        $allArticles = array_merge($allArticles, $articles);
        $page++;
    }
    return $allArticles;
}

function main() {
    try {
        // Step 1: Send the initial query and retrieve the query_id.
        $queryId = sendInitialQuery(QUERY, ATHENA_API_KEY);
        if (!$queryId) {
            echo "Failed to retrieve query ID.\n";
            return;
        }

        // Step 2: Poll the API until the query is processed.
        $resultData = pollForResults($queryId, ATHENA_API_KEY);

        // Check if the query was successful before pagination.
        if (!isset($resultData['state']) || $resultData['state'] !== 'SUCCESS') {
            echo "Query did not complete successfully:\n";
            print_r($resultData);
            return;
        }

        $totalResults = isset($resultData['totalArticles']) ? $resultData['totalArticles'] : 0;
        if ($totalResults == 0) {
            echo "No results found.\n";
            return;
        }

        // Step 3: Paginate through the results and collect all articles.
        $allArticles = fetchAllArticles($queryId, $totalResults, ATHENA_API_KEY);
        echo "Total articles fetched: " . count($allArticles) . "\n";

    } catch (Exception $e) {
        echo "An error occurred while communicating with the API: " . $e->getMessage() . "\n";
    }
}

main();
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;

public class AthenaQuery {
    // Constants
    private static final String ATHENA_API_KEY = "YOUR_API_KEY";
    private static final String QUERY = "donald trump";
    private static final String START_DATE = "2025-03-04T15:13:52.466Z";
    private static final String END_DATE = "2025-03-05T15:13:52.466Z";
    private static final String QUERY_URL = "https://app.runathena.com/api/v2/query-async";
    private static final String RESULTS_URL = "https://app.runathena.com/api/v2/get-results";
    private static final int ARTICLES_PER_PAGE = 25;
    private static final int POLL_INTERVAL = 1000; // milliseconds

    private static final HttpClient httpClient = HttpClient.newHttpClient();
    private static final ObjectMapper objectMapper = new ObjectMapper();

    // Sends the initial query and returns the query_id
    public static String sendInitialQuery(String query, String apiKey) throws Exception {
        String payload = String.format(
            "{\"query\":\"%s\", \"api_key\":\"%s\", \"toggle_state\":\"Encoded Articles\", \"start_date\":\"%s\", \"end_date\":\"%s\"}",
            query, apiKey, START_DATE, END_DATE
        );

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(QUERY_URL))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(payload))
            .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        if(response.statusCode() < 200 || response.statusCode() >= 300) {
            throw new RuntimeException("HTTP error: " + response.statusCode());
        }

        JsonNode jsonResponse = objectMapper.readTree(response.body());
        return jsonResponse.has("query_id") ? jsonResponse.get("query_id").asText() : null;
    }

    // Polls the API until the query state is no longer "PENDING"
    public static JsonNode pollForResults(String queryId, String apiKey) throws Exception {
        String payload = String.format("{\"query_id\":\"%s\", \"api_key\":\"%s\"}", queryId, apiKey);
        JsonNode data;
        do {
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(RESULTS_URL))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(payload))
                .build();

            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            if(response.statusCode() < 200 || response.statusCode() >= 300) {
                throw new RuntimeException("HTTP error: " + response.statusCode());
            }

            data = objectMapper.readTree(response.body());
            if (data.has("state") && data.get("state").asText().equals("PENDING")) {
                Thread.sleep(POLL_INTERVAL);
            } else {
                break;
            }
        } while (true);

        return data;
    }

    // Fetches and aggregates all articles by paginating through the results
    public static ArrayNode fetchAllArticles(String queryId, int totalResults, String apiKey) throws Exception {
        ArrayNode allArticles = objectMapper.createArrayNode();
        int page = 1;
        while ((page - 1) * ARTICLES_PER_PAGE < totalResults) {
            String payload = String.format(
                "{\"query_id\":\"%s\", \"api_key\":\"%s\", \"toggle_state\":\"Encoded Articles\", \"page\":%d}",
                queryId, apiKey, page
            );

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(RESULTS_URL))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(payload))
                .build();

            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            if(response.statusCode() < 200 || response.statusCode() >= 300) {
                throw new RuntimeException("HTTP error: " + response.statusCode());
            }

            JsonNode data = objectMapper.readTree(response.body());
            JsonNode articles = data.get("articles");
            if (articles != null && articles.isArray()) {
                allArticles.addAll((ArrayNode) articles);
            }
            page++;
        }
        return allArticles;
    }

    public static void main(String[] args) {
        try {
            // Step 1: Send the initial query and retrieve the query_id.
            String queryId = sendInitialQuery(QUERY, ATHENA_API_KEY);
            if (queryId == null || queryId.isEmpty()) {
                System.out.println("Failed to retrieve query ID.");
                return;
            }

            // Step 2: Poll the API until the query is processed.
            JsonNode resultData = pollForResults(queryId, ATHENA_API_KEY);
            if (!resultData.has("state") || !resultData.get("state").asText().equals("SUCCESS")) {
                System.out.println("Query did not complete successfully: " + resultData.toString());
                return;
            }

            int totalResults = resultData.has("totalArticles") ? resultData.get("totalArticles").asInt() : 0;
            if (totalResults == 0) {
                System.out.println("No results found.");
                return;
            }

            // Step 3: Paginate through the results and collect all articles.
            ArrayNode allArticles = fetchAllArticles(queryId, totalResults, ATHENA_API_KEY);
            System.out.println("Total articles fetched: " + allArticles.size());
        } catch (Exception e) {
            System.out.println("An error occurred while communicating with the API: " + e.getMessage());
        }
    }
}
require 'net/http'
require 'uri'
require 'json'

# Constants
ATHENA_API_KEY = "YOUR_API_KEY"
QUERY = "donald trump"
START_DATE = "2025-03-04T15:13:52.466Z"
END_DATE = "2025-03-05T15:13:52.466Z"
QUERY_URL = "https://app.runathena.com/api/v2/query-async"
RESULTS_URL = "https://app.runathena.com/api/v2/get-results"
ARTICLES_PER_PAGE = 25
POLL_INTERVAL = 1  # seconds

def send_initial_query(query, api_key)
  payload = {
    query: query,
    api_key: api_key,
    toggle_state: 'Encoded Articles',
    start_date: START_DATE,
    end_date: END_DATE
  }

  uri = URI.parse(QUERY_URL)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true if uri.scheme == 'https'
  request = Net::HTTP::Post.new(uri.request_uri, { 'Content-Type' => 'application/json' })
  request.body = payload.to_json

  response = http.request(request)
  if response.code.to_i < 200 || response.code.to_i >= 300
    raise "HTTP error: #{response.code}"
  end

  data = JSON.parse(response.body)
  data['query_id']
end

def poll_for_results(query_id, api_key)
  payload = { query_id: query_id, api_key: api_key }
  uri = URI.parse(RESULTS_URL)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true if uri.scheme == 'https'

  loop do
    request = Net::HTTP::Post.new(uri.request_uri, { 'Content-Type' => 'application/json' })
    request.body = payload.to_json

    response = http.request(request)
    if response.code.to_i < 200 || response.code.to_i >= 300
      raise "HTTP error: #{response.code}"
    end

    data = JSON.parse(response.body)
    if data['state'] == 'PENDING'
      sleep(POLL_INTERVAL)
    else
      return data
    end
  end
end

def fetch_all_articles(query_id, total_results, api_key)
  all_articles = []
  page = 1
  uri = URI.parse(RESULTS_URL)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true if uri.scheme == 'https'

  while (page - 1) * ARTICLES_PER_PAGE < total_results
    payload = {
      query_id: query_id,
      api_key: api_key,
      toggle_state: 'Encoded Articles',
      page: page
    }

    request = Net::HTTP::Post.new(uri.request_uri, { 'Content-Type' => 'application/json' })
    request.body = payload.to_json

    response = http.request(request)
    if response.code.to_i < 200 || response.code.to_i >= 300
      raise "HTTP error: #{response.code}"
    end

    data = JSON.parse(response.body)
    articles = data['articles'] || []
    all_articles.concat(articles)
    page += 1
  end

  all_articles
end

def main
  begin
    # Step 1: Send the initial query and retrieve the query_id.
    query_id = send_initial_query(QUERY, ATHENA_API_KEY)
    unless query_id
      puts "Failed to retrieve query ID."
      return
    end

    # Step 2: Poll the API until the query is processed.
    result_data = poll_for_results(query_id, ATHENA_API_KEY)
    unless result_data['state'] == 'SUCCESS'
      puts "Query did not complete successfully: #{result_data}"
      return
    end

    total_results = result_data['totalArticles'] || 0
    if total_results == 0
      puts "No results found."
      return
    end

    # Step 3: Paginate through the results and collect all articles.
    all_articles = fetch_all_articles(query_id, total_results, ATHENA_API_KEY)
    puts "Total articles fetched: #{all_articles.size}"
  rescue StandardError => e
    puts "An error occurred while communicating with the API: #{e.message}"
  end
end

main

Using Synchronous Endpoint

It begins by defining the necessary ATHENA_API_KEY. The payload dictionary specifies the query parameters, including a search term ("donald trump"), your api key, and other configuration details used to filter the results (for the sake of simplicity we are choosing to omit extra parameters).

The initial request is sent via a POST call to Athena’s API endpoint, with the response stored in data. This response includes metadata such as totalResults, allowing for efficient pagination. The loop then iterates over pages, adjusting the payload to request the next set of articles and appending each batch to all_articles. By the end, all_articles contains all retrieved articles matching the query, providing an easy way to gather a complete dataset in only a few lines of code.

import requests
import json

ATHENA_API_KEY = "your_api_key"
url = "https://app.runathena.com/api/v2/query"
headers = {
    "Content-Type": "application/json"
}

# Define the initial payload with the query and other required fields
payload = {
    "query": "donald trump",
    "api_key": ATHENA_API_KEY
}

# Send the initial request
response = requests.post(url, headers=headers, json=payload)
data = response.json()

# Initialize variables for pagination
page = 1
all_articles = []
articles_per_request = 25 

# Fetch and collect all articles while there are more pages
while page * articles_per_request < data.get('totalResults', 0):
    payload['page'] = page
    response = requests.post(url, headers=headers, json=payload)
    data = response.json()
    all_articles.extend(data.get('articles', []))
    page += 1

print(all_articles)
const axios = require('axios');

const ATHENA_API_KEY = "your_api_key";
const url = "https://app.runathena.com/api/v2/query";

const headers = {
    "Content-Type": "application/json"
};

// Define the initial payload with the query and other required fields
const payload = {
    query: "donald trump",
    api_key: ATHENA_API_KEY
};

// Fetch all articles function
const fetchArticles = async () => {
    try {
        // Send the initial request
        let response = await axios.post(url, payload, { headers });
        let data = response.data;

        // Initialize variables for pagination
        let page = 1;
        const allArticles = [];
        const articlesPerRequest = 25;

        // Fetch and collect all articles while there are more pages
        while (page * articlesPerRequest < (data.totalResults || 0)) {
            payload.page = page; // Update the payload with the current page
            response = await axios.post(url, payload, { headers });
            data = response.data;

            if (data.articles) {
                allArticles.push(...data.articles); // Collect articles
            }

            page++;
        }

        console.log(allArticles);
    } catch (error) {
        console.error("Error fetching articles:", error.message);
    }
};

// Call the function to fetch articles
fetchArticles();
require 'net/http'
require 'json'

ATHENA_API_KEY = "your_api_key"
url = URI("https://app.runathena.com/api/v2/query")

# Define the initial payload with the query and other required fields
payload = {
  query: "donald trump",
  api_key: ATHENA_API_KEY
}

headers = {
  "Content-Type" => "application/json"
}

# Fetch all articles function
def fetch_articles(url, headers, payload)
  all_articles = []
  articles_per_request = 25
  page = 1

  begin
    # Send the initial request
    response = Net::HTTP.post(url, payload.to_json, headers)
    data = JSON.parse(response.body)

    total_results = data['totalResults'] || 0

    # Fetch and collect all articles while there are more pages
    while page * articles_per_request < total_results
      payload[:page] = page
      response = Net::HTTP.post(url, payload.to_json, headers)
      data = JSON.parse(response.body)

      if data['articles']
        all_articles.concat(data['articles'])
      end

      page += 1
    end

    puts all_articles
  rescue StandardError => e
    puts "Error fetching articles: #{e.message}"
  end
end

# Call the function to fetch articles
fetch_articles(url, headers, payload)
// Some code<?php

$athenaApiKey = "your_api_key";
$url = "https://app.runathena.com/api/v2/query";

// Define the initial payload with the query and other required fields
$payload = [
    "query" => "donald trump",
    "api_key" => $athenaApiKey
];

// Function to fetch articles
function fetchArticles($url, $payload)
{
    $allArticles = [];
    $articlesPerRequest = 25;
    $page = 1;

    try {
        // Initialize cURL
        $ch = curl_init();

        // Function to execute cURL request
        $executeCurl = function ($url, $payload) use ($ch) {
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Content-Type: application/json',
            ]);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));

            $response = curl_exec($ch);

            if (curl_errno($ch)) {
                throw new Exception(curl_error($ch));
            }

            return json_decode($response, true);
        };

        // Fetch the first set of data
        $data = $executeCurl($url, $payload);
        $totalResults = $data['totalResults'] ?? 0;

        // Fetch and collect all articles while there are more pages
        while ($page * $articlesPerRequest < $totalResults) {
            $payload['page'] = $page;
            $data = $executeCurl($url, $payload);

            if (!empty($data['articles'])) {
                $allArticles = array_merge($allArticles, $data['articles']);
            }

            $page++;
        }

        curl_close($ch);

        // Print all articles
        print_r($allArticles);
    } catch (Exception $e) {
        echo "Error fetching articles: " . $e->getMessage();
    }
}

// Call the function to fetch articles
fetchArticles($url, $payload);

?>

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

public class AthenaQuery {
    private static final String ATHENA_API_KEY = "your_api_key";
    private static final String URL = "https://app.runathena.com/api/v2/query";

    public static void main(String[] args) {
        try {
            fetchArticles();
        } catch (Exception e) {
            System.err.println("Error fetching articles: " + e.getMessage());
        }
    }

    public static void fetchArticles() throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        ObjectMapper objectMapper = new ObjectMapper();

        // Define the initial payload
        String payload = objectMapper.writeValueAsString(new Payload("donald trump", ATHENA_API_KEY, 0));
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(URL))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(payload))
                .build();

        // Send the initial request
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        JsonNode rootNode = objectMapper.readTree(response.body());

        int totalResults = rootNode.path("totalResults").asInt();
        int articlesPerRequest = 25;
        int page = 1;
        List<JsonNode> allArticles = new ArrayList<>();

        // Fetch and collect all articles while there are more pages
        while (page * articlesPerRequest < totalResults) {
            payload = objectMapper.writeValueAsString(new Payload("donald trump", ATHENA_API_KEY, page));
            request = HttpRequest.newBuilder()
                    .uri(URI.create(URL))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString(payload))
                    .build();

            response = client.send(request, HttpResponse.BodyHandlers.ofString());
            rootNode = objectMapper.readTree(response.body());

            if (rootNode.has("articles")) {
                for (JsonNode article : rootNode.path("articles")) {
                    allArticles.add(article);
                }
            }

            page++;
        }

        // Print all articles
        System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(allArticles));
    }

    // Helper class for the payload
    static class Payload {
        public String query;
        public String api_key;
        public int page;

        public Payload(String query, String api_key, int page) {
            this.query = query;
            this.api_key = api_key;
            this.page = page;
        }
    }
}

First define your ATHENA_API_KEY. The payload dictionary specifies the query parameters, including a search term ("donald trump"), your api_key, other configuration details to filter the results (for the sake of simplicity we are choosing to omit extra parameters — see for other options).

This example makes use of the /api/v2/auery endpoint, which is best geared for smaller searches. It's simpler to use, but is not meant to handle queries generating large results. See for more details.

This example makes use of the /api/v2/auery endpoint, which is best geared for smaller searches. Our /api/v2/query-async endpoint is suited for larger queries - see for more details.

API Reference
API Reference
API Reference
Example search for Tesla stock outlook