Build a News Dashboard with Article Counts
Use article counts grouped by category, country, publisher bias or another field. Group dates or numeric scores into intervals to build timeline and distribution charts.
Step 1: Count articles by field
Set facet=true and list up to 5 fields in facet.field. Counts are computed over everything that matches your filters, not just the current page.
curl "https://api.apitube.io/v1/news/everything?facet=true&facet.field=category.id,source.country.id,source.bias&facet.limit=10&per_page=1&api_key=YOUR_API_KEY"
import requests
response = requests.get(
"https://api.apitube.io/v1/news/everything",
params={
"facet": "true",
"facet.field": "category.id,source.country.id,source.bias",
"facet.limit": "10",
"per_page": "1",
"api_key": "YOUR_API_KEY",
},
)
print(response.json())
const params = new URLSearchParams({ "facet": "true", "facet.field": "category.id,source.country.id,source.bias", "facet.limit": "10", "per_page": "1", "api_key": "YOUR_API_KEY" });
const response = await fetch(`https://api.apitube.io/v1/news/everything?${params}`);
const data = await response.json();
console.log(data);
$query = http_build_query(["facet" => "true", "facet.field" => "category.id,source.country.id,source.bias", "facet.limit" => "10", "per_page" => "1", "api_key" => "YOUR_API_KEY"]);
$response = file_get_contents("https://api.apitube.io/v1/news/everything?$query");
$data = json_decode($response, true);
print_r($data);
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
u, _ := url.Parse("https://api.apitube.io/v1/news/everything")
q := u.Query()
q.Set("facet", "true")
q.Set("facet.field", "category.id,source.country.id,source.bias")
q.Set("facet.limit", "10")
q.Set("per_page", "1")
q.Set("api_key", "YOUR_API_KEY")
u.RawQuery = q.Encode()
resp, _ := http.Get(u.String())
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var data map[string]any
json.Unmarshal(body, &data)
fmt.Println(data)
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.apitube.io/v1/news/everything?facet=true&facet.field=category.id,source.country.id,source.bias&facet.limit=10&per_page=1&api_key=YOUR_API_KEY"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
Write a script in your preferred language that calls the APITube News API:
GET https://api.apitube.io/v1/news/everything?facet=true&facet.field=category.id,source.country.id,source.bias&facet.limit=10&per_page=1
Read the API key from an environment variable (do not hardcode it), handle request
errors, and print the key fields of each result.
Docs: https://docs.apitube.io/platform/news-api/everything
The response carries a facets object keyed by field name, each holding { value, count } pairs:
{
"facets": {
"source.bias": [
{ "value": 0, "count": 3809437 },
{ "value": 2, "count": 3746702 },
{ "value": 1, "count": 1868553 }
]
}
}- Pie or bar widget —
facets["category.id"], feed thevalueinto the category list to get a readable label. - Map widget —
facets["source.country.id"]. - Bias split —
facets["source.bias"], where0is left,1is center and2is right. Sources with no bias rating are returned under their own value — drop it before charting. - Hide rare values — raise
facet.mincountto exclude values that appear in only a few articles.
Step 2: Draw the publication timeline
Range facets group a date or number into intervals. For a publication timeline, set facet.range.field=published_at and choose a gap: 1HOUR, 1DAY or 1MONTH.
curl "https://api.apitube.io/v1/news/everything?facet.range=true&facet.range.field=published_at&facet.range.start=2026-07-20&facet.range.end=2026-07-27&facet.range.gap=1DAY&per_page=1&api_key=YOUR_API_KEY"
import requests
response = requests.get(
"https://api.apitube.io/v1/news/everything",
params={
"facet.range": "true",
"facet.range.field": "published_at",
"facet.range.start": "2026-07-20",
"facet.range.end": "2026-07-27",
"facet.range.gap": "1DAY",
"per_page": "1",
"api_key": "YOUR_API_KEY",
},
)
print(response.json())
const params = new URLSearchParams({ "facet.range": "true", "facet.range.field": "published_at", "facet.range.start": "2026-07-20", "facet.range.end": "2026-07-27", "facet.range.gap": "1DAY", "per_page": "1", "api_key": "YOUR_API_KEY" });
const response = await fetch(`https://api.apitube.io/v1/news/everything?${params}`);
const data = await response.json();
console.log(data);
$query = http_build_query(["facet.range" => "true", "facet.range.field" => "published_at", "facet.range.start" => "2026-07-20", "facet.range.end" => "2026-07-27", "facet.range.gap" => "1DAY", "per_page" => "1", "api_key" => "YOUR_API_KEY"]);
$response = file_get_contents("https://api.apitube.io/v1/news/everything?$query");
$data = json_decode($response, true);
print_r($data);
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
u, _ := url.Parse("https://api.apitube.io/v1/news/everything")
q := u.Query()
q.Set("facet.range", "true")
q.Set("facet.range.field", "published_at")
q.Set("facet.range.start", "2026-07-20")
q.Set("facet.range.end", "2026-07-27")
q.Set("facet.range.gap", "1DAY")
q.Set("per_page", "1")
q.Set("api_key", "YOUR_API_KEY")
u.RawQuery = q.Encode()
resp, _ := http.Get(u.String())
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var data map[string]any
json.Unmarshal(body, &data)
fmt.Println(data)
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.apitube.io/v1/news/everything?facet.range=true&facet.range.field=published_at&facet.range.start=2026-07-20&facet.range.end=2026-07-27&facet.range.gap=1DAY&per_page=1&api_key=YOUR_API_KEY"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
Write a script in your preferred language that calls the APITube News API:
GET https://api.apitube.io/v1/news/everything?facet.range=true&facet.range.field=published_at&facet.range.start=2026-07-20&facet.range.end=2026-07-27&facet.range.gap=1DAY&per_page=1
Read the API key from an environment variable (do not hardcode it), handle request
errors, and print the key fields of each result.
Docs: https://docs.apitube.io/platform/news-api/everything
Each interval appears under <field>_ranges with its start, end and article count. Plot these values directly:
{
"facets": {
"published_at_ranges": [
{ "range_start": "2026-07-24", "range_end": "2026-07-25", "count": 283467 },
{ "range_start": "2026-07-25", "range_end": "2026-07-26", "count": 174354 },
{ "range_start": "2026-07-26", "range_end": "2026-07-27", "count": 165699 }
]
}
}Step 3: Chart sentiment scores
The same approach works with numeric fields. sentiment.overall.score ranges from -1 to 1. An interval size of 0.25 divides the scores into eight groups, from very negative to very positive.
curl "https://api.apitube.io/v1/news/everything?facet.range=true&facet.range.field=sentiment.overall.score&facet.range.start=-1&facet.range.end=1&facet.range.gap=0.25&per_page=1&api_key=YOUR_API_KEY"
import requests
response = requests.get(
"https://api.apitube.io/v1/news/everything",
params={
"facet.range": "true",
"facet.range.field": "sentiment.overall.score",
"facet.range.start": "-1",
"facet.range.end": "1",
"facet.range.gap": "0.25",
"per_page": "1",
"api_key": "YOUR_API_KEY",
},
)
print(response.json())
const params = new URLSearchParams({ "facet.range": "true", "facet.range.field": "sentiment.overall.score", "facet.range.start": "-1", "facet.range.end": "1", "facet.range.gap": "0.25", "per_page": "1", "api_key": "YOUR_API_KEY" });
const response = await fetch(`https://api.apitube.io/v1/news/everything?${params}`);
const data = await response.json();
console.log(data);
$query = http_build_query(["facet.range" => "true", "facet.range.field" => "sentiment.overall.score", "facet.range.start" => "-1", "facet.range.end" => "1", "facet.range.gap" => "0.25", "per_page" => "1", "api_key" => "YOUR_API_KEY"]);
$response = file_get_contents("https://api.apitube.io/v1/news/everything?$query");
$data = json_decode($response, true);
print_r($data);
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
u, _ := url.Parse("https://api.apitube.io/v1/news/everything")
q := u.Query()
q.Set("facet.range", "true")
q.Set("facet.range.field", "sentiment.overall.score")
q.Set("facet.range.start", "-1")
q.Set("facet.range.end", "1")
q.Set("facet.range.gap", "0.25")
q.Set("per_page", "1")
q.Set("api_key", "YOUR_API_KEY")
u.RawQuery = q.Encode()
resp, _ := http.Get(u.String())
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var data map[string]any
json.Unmarshal(body, &data)
fmt.Println(data)
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.apitube.io/v1/news/everything?facet.range=true&facet.range.field=sentiment.overall.score&facet.range.start=-1&facet.range.end=1&facet.range.gap=0.25&per_page=1&api_key=YOUR_API_KEY"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
Write a script in your preferred language that calls the APITube News API:
GET https://api.apitube.io/v1/news/everything?facet.range=true&facet.range.field=sentiment.overall.score&facet.range.start=-1&facet.range.end=1&facet.range.gap=0.25&per_page=1
Read the API key from an environment variable (do not hardcode it), handle request
errors, and print the key fields of each result.
Docs: https://docs.apitube.io/platform/news-api/everything
You can also group read_time by intervals of 5, source.rank.opr by intervals of 2, or media.images.count by the number of images.
Filters apply before articles are counted. Add industry.id to limit the dashboard's counts to one industry:
import requests
def dashboard(api_key, **filters):
params = {
"facet": "true",
"facet.field": "category.id,source.country.id",
"facet.range": "true",
"facet.range.field": "published_at",
"facet.range.start": "2026-07-20",
"facet.range.end": "2026-07-27",
"facet.range.gap": "1DAY",
"per_page": 1,
"api_key": api_key,
**filters,
}
return requests.get("https://api.apitube.io/v1/news/everything", params=params).json()["facets"]Tip: set
per_page=1when you only need facet counts. Counts cover all matching articles, regardless of page size.