Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.wokelo.ai/llms.txt

Use this file to discover all available pages before exploring further.

1. Overview

The Company News Monitoring API fetches the latest news articles for a given company, enriched with AI-generated summaries, structured event categories, sentiment classifications, publisher metadata, and scraped article text. Results are returned synchronously in the HTTP response — no job polling required. This is a synchronous GET API — you pass a company identifier and optional filters as URL parameters, and receive a paginated array of enriched news articles immediately. Each article in the response includes:
  • AI summary — a concise, machine-generated synopsis of the article’s key facts and implications
  • Event categorisation — a primary_tag and up to several secondary_tags drawn from Wokelo’s 86-category news taxonomy
  • Sentiment signalPositive, Neutral, or Negative classification at the article level
  • Newsworthiness impactHigh, Medium, or Low rating assessing the article’s strategic significance
  • Publisher and author metadata — source domain, author name, publication date, and original language
  • Company mentions — a structured array of all companies named in the article, with their resolved websites
  • Full article text — the complete scraped_text for downstream summarisation, embedding, or LLM processing
Common use cases:
  • Portfolio adverse signal monitoring — Filter for LEGAL AND COMPLIANCE, LAY-OFFS, FINANCIAL DISTRESS & RESTRUCTURING, or CYBERSECURITY INCIDENTS categories to catch early warning signals across a watchlist
  • Deal due diligence — Pull all news for a target company in the past 12 months, filter by MERGERS & ACQUISITIONS, REGULATORY APPROVALS & CERTIFICATIONS, and LEGAL PROCEEDINGS & LITIGATION to surface relevant deal context fast
  • Competitive intelligence — Monitor PRODUCT LAUNCHES & ENHANCEMENTS, PARTNERSHIPS & ALLIANCES, and GEOGRAPHIC EXPANSION categories for a set of competitors on a rolling basis
  • Executive monitoring — Track C-SUITE APPOINTMENTS & DEPARTURES, EXECUTIVE COMMENTARY & INTERVIEWS, and SUCCESSION PLANNING for key personnel across your coverage universe
  • LLM-powered research — Use the scraped_text field to feed full article content directly into your own summarisation or RAG pipeline, pre-filtered by category and date
This API is synchronous. Results are returned directly in the HTTP response — no job submission or polling required. See How Sync APIs work.

2. Quick Start

Step 1 — Make a simple request
curl --location 'https://api.wokelo.ai/api/enterprise/company/news/?company=tesla' \
  --header 'Authorization: Bearer <YOUR_API_TOKEN>' \
  --header 'Content-Type: application/json'
Step 2 — Filter by category and date range
response = requests.get(
    "https://api.wokelo.ai/api/enterprise/company/news/",
    headers={"Authorization": "Bearer <YOUR_API_TOKEN>"},
    params={
        "company": "tesla",
        "category": "MERGERS & ACQUISITIONS, PARTNERSHIPS & ALLIANCES",
        "start_date": "2025-01-01",
        "end_date": "2026-03-31",
        "limit": 50
    }
)
articles = response.json()["data"]
Step 3 — Work with the articles
for article in articles:
    print(f"[{article['primary_tag']}] {article['title']}")
    print(f"  {article['publisher']} | {article['published_date'][:10]} | {article.get('sentiment', 'N/A')}")
    print(f"  {article['ai_summary'][:120]}...")
    print()

3. Authentication

All requests must include a Bearer token in the Authorization HTTP header. No other authentication method is supported.
Authorization: Bearer <YOUR_API_TOKEN>
API tokens are issued from your Wokelo account. Navigate to Account Details → API Credentials in the Wokelo dashboard to get your client id and client secret. Contact support@wokelo.ai if you do not yet have API access.
Never expose your token in client-side code, browser requests, or public repositories. A missing or invalid token returns 401 Unauthorized. A valid token without sufficient plan permissions returns 403 Forbidden.

4. Request Reference

Endpoint
GET https://api.wokelo.ai/api/enterprise/company/news/
All parameters are passed as URL query parameters.
ParameterTypeRequiredDescription
companystringRequiredCompany permalink (e.g. "tesla") or a full company URL (e.g. "https://www.tesla.com/"). Use the Company Search API to resolve a company name to its permalink.
start_datestringOptionalStart of the date window for articles (YYYY-MM-DD). Inclusive.
end_datestringOptionalEnd of the date window for articles (YYYY-MM-DD). Inclusive.
categorystringOptionalComma-separated list of news categories to filter by. Returns only articles whose primary_tag or secondary_tags match. View all 86 supported categories. Example: "MERGERS & ACQUISITIONS, PRODUCT LAUNCHES & ENHANCEMENTS".
limitintegerOptionalMaximum number of articles to return. Default 100, max 1000.
offsetintegerOptionalNumber of articles to skip before returning results. Use with limit for pagination.
blacklistedstringOptionalComma-separated list of publisher domains to exclude. Include the full domain starting with https:// (e.g. "https://www.prnewswire.com/").
publishersstringOptionalComma-separated list of publisher domains to include exclusively. All other publishers are excluded.
Full request example:
curl --location 'https://api.wokelo.ai/api/enterprise/company/news/?company=tesla&start_date=2025-01-01&end_date=2026-03-15&category=PARTNERSHIPS%20%26%20ALLIANCES%2C%20MERGERS%20%26%20ACQUISITIONS&limit=100&offset=0&blacklisted=https%3A%2F%2Fwww.prnewswire.com%2F' \
  --header 'Authorization: Bearer <YOUR_API_TOKEN>' \
  --header 'Content-Type: application/json'

5. Response

Response structure

{
  "status": "success",
  "data": [ ...article objects... ],
  "count": 4,
  "total": 4,
  "limit": 100,
  "offset": 0
}
FieldTypeDescription
statusstring"success" when the request was processed successfully.
dataarrayArray of enriched article objects.
countintegerNumber of articles returned in this response.
totalintegerTotal number of matching articles available (before limit and offset are applied).
limitintegerThe limit value that was applied.
offsetintegerThe offset value that was applied.

Article object fields

Each object in the data array contains the following fields: Article content
FieldTypeDescription
titlestringHeadline of the article.
urlstringCanonical URL of the original article.
ai_summarystringAI-generated 2–4 sentence summary of the article’s key facts and implications.
scraped_textstringFull text content of the article as scraped from the source. Use this for downstream LLM processing, embeddings, or detailed analysis. May be empty for paywalled articles.
published_datestringPublication datetime in YYYY-MM-DD HH:MM:SS format (UTC).
original_languagestringISO 639-1 language code of the original article (e.g. "EN"). Empty string when not detected.
Publisher metadata
FieldTypeDescription
publisherstringDomain name of the publishing outlet (e.g. "bloomberg", "techcrunch").
authorstringAuthor name(s) as extracted from the article. May contain multiple names or be empty.
sourcestringWokelo’s internal signal source designation. Either "Wokelo" (directly indexed) or "Google" (sourced via search).
Categorisation
FieldTypeDescription
primary_tagstringThe single most relevant event category from Wokelo’s 86-category taxonomy. See supported categories. May be empty for older articles.
typestringAlias for primary_tag. Present in some responses; use primary_tag as the canonical field.
secondary_tagsstring[]Additional relevant categories from the taxonomy. Empty array when no secondary categories apply.
Signals
FieldTypeDescription
sentimentstringArticle-level sentiment: "Positive", "Neutral", or "Negative". Empty string when not yet classified.
newsworthiness_impactstringStrategic significance rating: "High", "Medium", or "Low". Empty string when not yet classified.
Geography & company mentions
FieldTypeDescription
countriesstring[]Array of ISO 3166-1 alpha-3 country codes relevant to the article (e.g. ["USA", "CHN"]). Empty array when not detected.
company_namestringThe company that was queried (mirrors the company parameter).
company_namesobject[]Structured array of all companies mentioned in the article. Each object contains name (string) and website (string). Useful for identifying deal counterparties, partners, and competitors referenced in the article.
The company_names array includes all entities mentioned in the article — not just the queried company. This makes it useful for surfacing deal counterparties, lead investors, named competitors, and co-signatories in regulatory filings without having to parse the article text.

Sentiment values

ValueMeaning
"Positive"Article conveys favourable news — growth, wins, new partnerships, positive earnings
"Neutral"Factual or mixed coverage with no clear directional bias
"Negative"Article conveys unfavourable news — regulatory action, layoffs, declining metrics, litigation
""Sentiment classification not yet available for this article

Newsworthiness impact values

ValueMeaning
"High"Material signal likely to affect strategic positioning, valuation, or stakeholder decisions
"Medium"Notable development worth tracking but not immediately actionable
"Low"Routine coverage, minor updates, or tangentially related content
""Impact rating not yet available for this article

Notes on empty fields

Several fields can be empty strings or empty arrays in valid responses:
  • sentiment, newsworthiness_impact, primary_tag, original_language — empty string when classification has not yet been applied to this article, particularly for older content
  • secondary_tags, countries, company_names — empty array when no values were detected
  • scraped_text — empty string for paywalled articles or pages that blocked scraping
  • author — empty string when the byline was not present or parseable

6. Examples

Portfolio adverse signal monitoring

Get all legal, compliance, layoff, and financial distress news for a portfolio company to catch early warning signals.
curl --location 'https://api.wokelo.ai/api/enterprise/company/news/?company=brex&category=LEGAL%20AND%20COMPLIANCE%2C%20LAY-OFFS%2C%20EXECUTIVE%20APPOINTMENT%20AND%20CHANGES%2C%20REGULATORY%20%26%20COMPLIANCE%2C%20FINANCIAL%20DISTRESS%20%26%20RESTRUCTURING%2C%20WORKFORCE%20REDUCTIONS' \
  --header 'Authorization: Bearer <YOUR_API_TOKEN>' \
  --header 'Content-Type: application/json'
Sample response (excerpt):
{
  "status": "success",
  "data": [
    {
      "ai_summary": "Brex CEO Pedro Franceschi discusses the rapid $5.15 billion deal with Capital One, highlighting the deal's significance in the fintech space, Brex's evolving valuation, and plans for aggressive market competition.",
      "type": "Mergers & Acquisitions",
      "url": "https://www.youtube.com/watch?v=3a3omxYXqK4",
      "title": "How Brex signed a $5.15B Deal in ~40 Days",
      "company_name": "Brex",
      "publisher": "Youtube",
      "published_date": "2026-01-30 00:00:00",
      "source": "Wokelo",
      "author": "",
      "countries": [],
      "sentiment": "",
      "company_names": [],
      "primary_tag": "Mergers & Acquisitions",
      "original_language": "",
      "secondary_tags": [],
      "newsworthiness_impact": "",
      "scraped_text": "..."
    }
  ],
  "count": 12,
  "total": 12,
  "limit": 100,
  "offset": 0
}

Deal due diligence — target company news sweep

Pull all news for an acquisition target over a defined period, prioritise by category, and exclude press release sources to focus on independent coverage.
import requests

HEADERS = {"Authorization": "Bearer <YOUR_API_TOKEN>"}

DD_CATEGORIES = ", ".join([
    "MERGERS & ACQUISITIONS",
    "LEGAL PROCEEDINGS & LITIGATION",
    "REGULATORY APPROVALS & CERTIFICATIONS",
    "FINANCIAL DISTRESS & RESTRUCTURING",
    "C-SUITE APPOINTMENTS & DEPARTURES",
    "EARNINGS RELEASES",
    "PARTNERSHIPS & ALLIANCES"
])

# Exclude wire services — focus on editorial coverage
BLACKLIST = ", ".join([
    "https://www.prnewswire.com/",
    "https://www.businesswire.com/",
    "https://www.globenewswire.com/"
])

response = requests.get(
    "https://api.wokelo.ai/api/enterprise/company/news/",
    headers=HEADERS,
    params={
        "company": "tesla",
        "category": DD_CATEGORIES,
        "start_date": "2024-01-01",
        "end_date": "2026-03-31",
        "blacklisted": BLACKLIST,
        "limit": 200
    }
)

data = response.json()
articles = data["data"]

print(f"Retrieved {data['count']} articles (total matching: {data['total']})\n")

# Group by primary tag
from collections import defaultdict
by_category = defaultdict(list)
for a in articles:
    tag = a.get("primary_tag") or "Uncategorised"
    by_category[tag].append(a)

for category, items in sorted(by_category.items(), key=lambda x: -len(x[1])):
    print(f"\n{'='*60}")
    print(f"{category} ({len(items)} articles)")
    print('='*60)
    for a in items[:3]:  # Show top 3 per category
        print(f"  [{a['published_date'][:10]}] {a['title']}")
        print(f"  {a['ai_summary'][:150]}...")

Competitive monitoring — product launches and partnerships

Track product and partnership news for a set of competitors over a rolling 90-day window.
import requests
from datetime import datetime, timedelta

HEADERS = {"Authorization": "Bearer <YOUR_API_TOKEN>"}

COMPETITORS = ["salesforce", "hubspot", "pipedrive", "zoho"]

end_date = datetime.today().strftime("%Y-%m-%d")
start_date = (datetime.today() - timedelta(days=90)).strftime("%Y-%m-%d")

INTEL_CATEGORIES = ", ".join([
    "PRODUCT LAUNCHES & ENHANCEMENTS",
    "PARTNERSHIPS & ALLIANCES",
    "GEOGRAPHIC EXPANSION",
    "MERGERS & ACQUISITIONS",
    "EQUITY FUND-RAISING"
])

all_articles = []

for company in COMPETITORS:
    response = requests.get(
        "https://api.wokelo.ai/api/enterprise/company/news/",
        headers=HEADERS,
        params={
            "company": company,
            "category": INTEL_CATEGORIES,
            "start_date": start_date,
            "end_date": end_date,
            "limit": 50
        }
    )
    articles = response.json().get("data", [])
    for a in articles:
        a["_queried_company"] = company
    all_articles.extend(articles)

# Sort all articles by date, most recent first
all_articles.sort(key=lambda x: x["published_date"], reverse=True)

print(f"\nCompetitive Intelligence Feed — {start_date} to {end_date}")
print(f"Total articles: {len(all_articles)}\n")

for a in all_articles[:20]:
    sentiment = a.get("sentiment") or "—"
    print(f"[{a['_queried_company'].upper()}] [{a['primary_tag']}] [{sentiment}]")
    print(f"  {a['title']}")
    print(f"  {a['publisher']} | {a['published_date'][:10]}")
    print()

Paginating through large result sets

When total exceeds limit, paginate using offset to retrieve all matching articles.
import requests

HEADERS = {"Authorization": "Bearer <YOUR_API_TOKEN>"}
PARAMS = {
    "company": "apple",
    "start_date": "2024-01-01",
    "limit": 100,
    "offset": 0
}

all_articles = []

while True:
    response = requests.get(
        "https://api.wokelo.ai/api/enterprise/company/news/",
        headers=HEADERS,
        params=PARAMS
    )
    data = response.json()
    batch = data.get("data", [])
    all_articles.extend(batch)

    print(f"Fetched {len(all_articles)} / {data['total']} articles")

    if len(all_articles) >= data["total"] or not batch:
        break

    PARAMS["offset"] += PARAMS["limit"]

print(f"\nTotal retrieved: {len(all_articles)}")

Extracting article text for LLM processing

Use scraped_text to feed full article content into a summarisation or classification pipeline.
import requests

HEADERS = {"Authorization": "Bearer <YOUR_API_TOKEN>"}

response = requests.get(
    "https://api.wokelo.ai/api/enterprise/company/news/",
    headers=HEADERS,
    params={
        "company": "openai",
        "category": "MERGERS & ACQUISITIONS, EQUITY FUND-RAISING",
        "start_date": "2025-01-01",
        "limit": 20
    }
)

articles = response.json()["data"]

# Filter to articles with scraped text available
with_text = [a for a in articles if a.get("scraped_text", "").strip()]
print(f"{len(with_text)} of {len(articles)} articles have full text\n")

for a in with_text[:3]:
    word_count = len(a["scraped_text"].split())
    print(f"Title: {a['title']}")
    print(f"Publisher: {a['publisher']} | Words: {word_count}")
    print(f"AI Summary: {a['ai_summary']}")
    print()
    # Pass a["scraped_text"] to your LLM pipeline here

JavaScript / Node.js

const fetch = require("node-fetch");

async function getCompanyNews(company, options = {}) {
  const params = new URLSearchParams({
    company,
    ...(options.startDate && { start_date: options.startDate }),
    ...(options.endDate   && { end_date:   options.endDate }),
    ...(options.category  && { category:   options.category }),
    limit:  options.limit  || 100,
    offset: options.offset || 0
  });

  const response = await fetch(
    `https://api.wokelo.ai/api/enterprise/company/news/?${params}`,
    {
      method: "GET",
      headers: {
        "Authorization": `Bearer ${process.env.WOKELO_API_KEY}`,
        "Content-Type": "application/json"
      }
    }
  );

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

  return response.json();
}

// Example: get M&A news for Tesla in 2025
getCompanyNews("tesla", {
  category: "MERGERS & ACQUISITIONS, PARTNERSHIPS & ALLIANCES",
  startDate: "2025-01-01",
  endDate:   "2025-12-31"
}).then(data => {
  console.log(`Found ${data.total} articles`);
  data.data.forEach(a => {
    console.log(`[${a.primary_tag}] ${a.title}${a.publisher}`);
  });
});

7. Error Handling

The API uses standard HTTP status codes. All error responses include a JSON body with a detail or message field.
StatusMeaningCause & Resolution
200 OKSuccessArticles returned successfully.
400 Bad RequestInvalid parametersA required parameter is missing or a value is invalid — e.g. missing company, malformed start_date, or unrecognised category string. Check the detail field.
401 UnauthorizedAuth failedThe Authorization header is missing, malformed, or contains an invalid token. Verify your key in Settings → API Keys.
403 ForbiddenInsufficient accessYour plan does not include access to this endpoint or company. Contact support@wokelo.ai to review your plan.
404 Not FoundCompany not foundThe company permalink could not be resolved. Use the Company Search API to verify the permalink before querying.
429 Too Many RequestsRate limit exceededImplement exponential back-off. The response includes a Retry-After header.
500 Internal Server ErrorServer errorRetry after a brief delay. If the issue persists, contact support@wokelo.ai.
Error response example:
{
  "status": "error",
  "detail": "Company permalink 'unknown-co' could not be resolved."
}
Retry logic with exponential back-off:
import time, requests

def fetch_news_with_retry(params, api_key, max_retries=3):
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    for attempt in range(max_retries):
        try:
            response = requests.get(
                "https://api.wokelo.ai/api/enterprise/company/news/",
                headers=headers,
                params=params,
                timeout=30
            )
            if response.status_code == 429:
                wait = 2 ** attempt   # 1s, 2s, 4s
                time.sleep(wait)
                continue
            response.raise_for_status()
            return response.json()
        except requests.exceptions.Timeout:
            if attempt == max_retries - 1:
                raise
            time.sleep(1)
    raise Exception(f"Failed after {max_retries} attempts")

8. Best Practices

Use the company permalink, not a display name The company parameter expects a permalink (e.g. "tesla", "brex") or a full URL. Passing a display name like "Tesla Inc." will not resolve correctly. Use the Company Search API to look up the permalink for any company:
# Resolve permalink first
search = requests.get(
    "https://api.wokelo.ai/api/enterprise/company/search/",
    headers=HEADERS,
    params={"query": "Tesla Inc"}
)
permalink = search.json()["results"][0]["permalink"]  # "tesla"
Filter by category to reduce noise — this is the highest-impact parameter Returning all news for a major company like Tesla or Apple can yield hundreds of articles, many of which are market data reports, stock price articles, or tangentially related coverage. Use the category filter aggressively to surface only the signal types relevant to your workflow. Combine multiple categories with a comma:
# For portfolio monitoring — adverse signals only
params["category"] = (
    "LEGAL PROCEEDINGS & LITIGATION, "
    "WORKFORCE REDUCTIONS, "
    "FINANCIAL DISTRESS & RESTRUCTURING, "
    "CYBERSECURITY INCIDENTS, "
    "C-SUITE APPOINTMENTS & DEPARTURES"
)
Exclude press release domains with blacklisted Wire service articles (prnewswire.com, businesswire.com, globenewswire.com) are often company-issued press releases that add volume without independent editorial perspective. Blacklist them for competitive intelligence and monitoring use cases where you want journalist-authored coverage:
params["blacklisted"] = (
    "https://www.prnewswire.com/, "
    "https://www.businesswire.com/, "
    "https://www.globenewswire.com/"
)
Use newsworthiness_impact to triage before reading When processing large result sets, filter to "High" impact articles first for executive briefings or urgent monitoring workflows. "Medium" and "Low" articles can be batch-processed later:
high_signal = [a for a in articles if a.get("newsworthiness_impact") == "High"]
Guard against empty classification fields primary_tag, sentiment, newsworthiness_impact, and original_language can be empty strings for older articles or articles still pending classification. Always use .get() with a default rather than direct key access:
# ❌ KeyError risk when field is present but empty
if article["sentiment"] == "Negative":
    ...

# ✅ Safe
if article.get("sentiment") == "Negative":
    ...
Use scraped_text for downstream LLM pipelines — but expect some gaps scraped_text contains the full article body and is ideal for passing to summarisation, classification, or embedding models. However, paywalled articles (Bloomberg, FT, WSJ) will often have empty or truncated scraped_text. Use ai_summary as a fallback:
content = article.get("scraped_text", "").strip()
if not content:
    content = article.get("ai_summary", "")
Paginate correctly when total exceeds limit The default limit is 100 and the maximum is 1000. For queries returning large result sets, check total against count and paginate using offset until all records are retrieved. Stop when count returns 0 or len(all_articles) >= total. Use company_names to map article networks The company_names array resolves all entity mentions in the article, not just the queried company. This lets you identify deal counterparties, named investors, or competitors without text parsing — useful for building relationship graphs across a coverage universe.

Industry News Monitoring

Monitor the latest news across an entire industry or sector, rather than a single company.

Newsfeed

Retrieve a curated, cross-company newsfeed based on a topic, theme, or portfolio watchlist.

Company Deep Intelligence

Generate a comprehensive AI intelligence report on any company — strategy, financials, and competitive position.

Company Instant Enrichment

Synchronously enrich firmographic and financial data for any company by permalink or URL.

Target Screening

Identify and score potential acquisition targets — AI-ranked with deal feasibility, synergy, and precedent scores.

Supporting APIs

Company Search, Request Status, and other utilities used alongside monitoring workflows.