> For the complete documentation index, see [llms.txt](https://docs.ns3.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ns3.ai/newscover-library.md).

# NewsCover Library

<figure><img src="/files/kzDzGLXFo6p9IzBz6w8B" alt=""><figcaption></figcaption></figure>

## NewsCover Library

### 1. Overview

**NewsCover Library** ("NewsCover") is a service that provides cover images that fit the news. Send a keyword or a headline, and it instantly returns matching covers from the library. The library currently holds roughly **3,000 entities** and **10,000 covers**, organized into the following categories.

<table data-search="false"><thead><tr><th>Category</th><th>Examples</th></tr></thead><tbody><tr><td>Crypto</td><td>Bitcoin, Ethereum, Solana</td></tr><tr><td>Corporate &#x26; Brands</td><td>Tesla, Apple, Binance</td></tr><tr><td>Nations</td><td>United States, Japan, South Korea</td></tr><tr><td>Currencies</td><td>Dollar, Yen, Euro</td></tr><tr><td>Commodities</td><td>Gold, Oil, Copper</td></tr><tr><td>People</td><td>Major politicians, CEOs, investors</td></tr><tr><td>Institutions · Indices · Regulation · Concepts</td><td>Fed, SEC, S&#x26;P 500, CPI</td></tr><tr><td>Other</td><td>Other entities frequent in crypto and economic news</td></tr></tbody></table>

It covers **every constituent of the CMC 500, Nasdaq 100, and S\&P 500**, plus most major global brands and the entities that appear most often in crypto and economic news.

**Built for precision.** The matching engine is designed to minimize wrong covers: *no cover is better than a wrong cover.* The engine was simulated against **5,000 real news headlines** for over-match and collision checks, then hardened accordingly.

**Standardized covers and the grid system.** The requirements for a cover image differ by platform and by story. A cover may be used alone or as two covers side by side, the subject must render correctly across the key ratios and platforms, and when two covers are rendered together in one space, visual mismatch must be minimal. To meet these requirements, every cover is produced as a high-quality image normalized by our grid system (person, symbol, wordmark, and object layouts), passes the grid check, and is deployed only after a final human review.

<div><figure><img src="/files/XPrfc5lrjAbCMNrlpLqs" alt=""><figcaption></figcaption></figure> <figure><img src="/files/zAPSIQ9UxC47ToZ6DvzA" alt=""><figcaption></figcaption></figure></div>

<div><figure><img src="/files/L5jRtpCihj27x9ZaXqVY" alt=""><figcaption></figcaption></figure> <figure><img src="/files/hXad2W1cGT8dIHFfey04" alt=""><figcaption></figcaption></figure></div>

#### **Two ways to use** (web & API):

| Mode                            | You send                                         | Best for                                                             |
| ------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------- |
| **Headline search** `headline=` | The raw headline text, unchanged                 | Automation and AI-rewriting pipelines (no keyword extraction needed) |
| **Keyword search** `q=`         | Keywords you selected (comma-separated, up to 4) | Editors composing covers exactly as intended                         |

Both modes use the same endpoint with a different query parameter and share **one response schema** (Section 7). **No authentication, no rate limit**, and **CORS enabled** (`Access-Control-Allow-Origin: *`), so you can call the API directly from browser front-ends as well as servers.

* Headline search: `GET https://api.ns3.ai/newscover?headline={headline text}`
* Keyword search: `GET https://api.ns3.ai/newscover?q={keyword1,keyword2,keyword3,keyword4}`

#### **Cover ratios and representative platforms**

<figure><img src="/files/UpKSRLjJXmXNs9aayegX" alt=""><figcaption></figcaption></figure>

| Ratio                            | Formats        | Representative use                                    |
| -------------------------------- | -------------- | ----------------------------------------------------- |
| **1.75:1** (original, 1750×1000) | Single · Split | X (Twitter) timeline image                            |
| **1:1**                          | Single         | Square thumbnails, in-app cards                       |
| **1.91:1**                       | Single · Split | OG image (social link preview), web standard 1200×630 |
| **2.5:1**                        | Single · Split | Wide news-feed banner                                 |

A Split cover places two entities' covers side by side as a single two-panel cover (the style widely used on X/Twitter). Because every cover passes the grid check, the subject stays correctly placed in both single and split layouts, with no visual mismatch between the two covers.

***

### 2. Choosing a Search Mode: `headline=` vs `q=`

|                       | `headline=` headline search              | `q=` keyword search                     |
| --------------------- | ---------------------------------------- | --------------------------------------- |
| **Input**             | The headline / breaking-news line, as-is | Keywords you extracted, comma-separated |
| **Entity extraction** | NewsCover library (automatic)            | Editor (manual)                         |
| **Matching**          | Strict: minimizes false matches          | Loose: favors discoverability           |
| **Editor workload**   | None: just forward the text              | Core-keyword selection needed           |
| **Fit**               | Automation, AI-rewritten feeds           | Human editing, clear keywords           |

**Headline search** derives covers straight from an existing headline, with no extra workflow. No-match and over-match can occur at a low rate, so a final human review is recommended to guarantee a complete result for readers.

**Keyword search** returns only the entities the editor selects, so covers are composed exactly as intended.

**The precision of headline search is structural.** Headline text cannot be controlled, so stricter matching is applied than in keyword search:

* **Tickers are case-sensitive; names are case-insensitive.** In "Bitcoin trades near record highs", lowercase `near` is just the word "near" and returns nothing, while uppercase `NEAR` matches the NEAR ticker. `Apple` or `apple` is a name and matches the company either way. (Therefore, send headlines as-is; do not change their casing.)
* **Edge-case handling is built in.** Over-match patterns identified by simulating thousands of real headlines are reflected in the engine and the keyword dictionary. For example, a currency used as an amount unit ("Raises Funding Worth 100 Million Yuan") does not trigger a cover.

`q=` mode is deliberately loose: because you chose the keywords on purpose, even lowercase `near` returns the NEAR cover.

> **Rule of thumb:** if a machine (or an AI rewriter) produces your feed, use `headline=`. If a person picks the keywords, either works.

***

### 3. Keyword Search Guide

Minor differences in spelling resolve to the same entity. Case, spaces, hyphens, and special characters do not affect matching:

| Input                                                 | Match           |
| ----------------------------------------------------- | --------------- |
| Polymarket / poly market / poly-market / POLY\_MARKET | Polymarket      |
| $BTC / btc                                            | BTC             |
| Bank of England / bankofengland                       | Bank of England |

**Tips for a higher match rate**

* Use proper entity names or tickers: `Bitcoin`, `BTC`, `Tesla`, `Fed`, `Japan`
* Generic nouns and descriptive phrases will not match: `crypto market crash`, `price surge`
* Keywords are supported in English only

When there is no match: the Web shows "No results found." and the API returns the mode-specific no-match response (see Sections 5 and 6).

***

### 4. NewsCover Web (for Editors)

URL: <https://ns3.ai/newscover>

1. Type a keyword or headline into the search box (English)
2. All images in the matched group are displayed
3. Check the ratio previews for each image: 1:1 square / 1.75:1 single·split / 1.91:1 single·split / 2.5:1 single·split / original ratio
4. Click the **Download Image** button to save the file, or click the copy icon to copy the image URL

Split previews show the two-panel split cover style widely used on X (Twitter) and similar platforms.

***

### 5. Headline Search API

Send the raw headline; the engine extracts the entities and returns a cover for each.

```
GET https://api.ns3.ai/newscover?headline={headline text}
GET https://api.ns3.ai/newscover?headline={headline text}&mode=extended
```

#### **Behavior**

* URL-encode the text (spaces as `%20` or `+`). Browsers and HTTP libraries do this automatically.
* The **first 250 characters** of the headline are scanned. (Longer input is accepted, but entities after the 250th character are not matched.)
* Up to **5 entities** are returned, in the order they appear in the headline. The first entity is most likely the primary subject, so use it when you need a single representative cover.
* Entity names of up to **three words** are matched ("Bank of England", "Ki Young Ju"). Punctuation is handled naturally: "Bitcoin (BTC)", "BTC," and "Trump's" all match their entities. A name and its ticker in the same headline merge into one result.
* `images` is an array. By default it holds one randomly assigned cover per matched entity group, so the same headline always returns the same entities but the specific cover image can differ between calls.
* Add **`mode=extended`** to return **all** covers the group holds in the `images` array. This gives you the same result as the web search via the API, so the editor can pick from all returned images.
* **When nothing matches, `results` is an empty array.** See the no-match example below.

#### Response example: two entities matched

`GET https://api.ns3.ai/newscover?headline=Bitcoin surges as SEC approves ETF`

```json
{
  "results": [
    {
      "matched": true,
      "input": "Bitcoin",
      "normalizedKeyword": "bitcoin",
      "name": "Bitcoin (BTC)",
      "category": "crypto",
      "images": [
        {
          "url": "https://assemble-ai-files.s3.amazonaws.com/2z4Lwzp9Mq...",
          "width": 1750,
          "height": 1000,
          "mimeType": "image/jpeg",
          "imageId": "2z4Lwzp9MqNT8mt7y7vunAd2Bs147XDpqgkTUeKCGyMM",
          "groupId": "68c028423b04413d9f9679c2"
        }
      ]
    },
    {
      "matched": true,
      "input": "SEC",
      "normalizedKeyword": "sec",
      "name": "U.S. Securities and Exchange Commission (SEC)",
      "category": "institutions",
      "images": [
        {
          "url": "https://assemble-ai-files.s3.amazonaws.com/6jMTXdrgPL...",
          "width": 1750,
          "height": 1000,
          "mimeType": "image/jpeg",
          "imageId": "6jMTXdrgPLXmZLcr9NgN2PKwqSRZrnrXeqg7STMxETGM",
          "groupId": "68c05a44c34f4a2bb67c4b44"
        }
      ]
    }
  ]
}
```

`input` echoes the entity form found in the headline. Identify which entity matched by `name` and `groupId`. `groupId` can also be used to check whether the same entity's cover repeats across articles.

#### Response example: no match

`GET https://api.ns3.ai/newscover?headline=The weather is nice today`

```json
{ "results": [] }
```

When no entity matches, the array is empty. (This differs from `q=`, which returns an explicit `matched: false` item per keyword. See Section 6.) Prepare your own fallback cover for this case.

***

### 6. Keyword Search API

Send keywords you extracted.

```
GET https://api.ns3.ai/newscover?q={keyword1,keyword2,...}
GET https://api.ns3.ai/newscover?q={keyword1,keyword2,...}&mode=extended
```

#### **Query rules**

* **Up to 4 keywords**, separated by commas. 5 or more returns **HTTP 400**.
* URL-encode keywords: spaces as `%20`/`+`, `&` as `%26`. An unencoded space fails the request, and an unencoded `&` silently truncates the query. *(Tip: sending keywords with no spaces, like `bankofengland`, sidesteps encoding entirely. Case is ignored in `q=`.)*
* `images` is an array holding one randomly assigned cover by default, so the same keyword may return a different image on each call.
* Add **`mode=extended`** to return **all** covers the group holds in the `images` array.

**Same-entity merging & backup keywords.** Keywords that resolve to the same entity merge into one result, so the response can have fewer items than the keywords you sent: always map by `input`. This enables a backup-keyword pattern: send several spellings of one entity (e.g. `?q=SamBankmanFried,BankmanFried,SBF`) and whichever is registered will match, you still get just one result, and there is no risk of receiving the same subject twice.

#### Response example: single keyword

`GET https://api.ns3.ai/newscover?q=bitcoin`

```json
{
  "results": [
    {
      "matched": true,
      "input": "bitcoin",
      "normalizedKeyword": "bitcoin",
      "name": "Bitcoin (BTC)",
      "category": "crypto",
      "images": [
        {
          "url": "https://assemble-ai-files.s3.amazonaws.com/7y9bQA7UG...",
          "width": 1750,
          "height": 1000,
          "mimeType": "image/jpeg",
          "imageId": "7y9bQA7UG2t5GCmGdsog3V366UAA1P8oKz8VbCuFHbC5",
          "groupId": "68c028423b04413d9f9679c2"
        }
      ]
    }
  ]
}
```

`results` is always an array, even for a single keyword.

#### Response example: no match

`GET https://api.ns3.ai/newscover?q=pemex`

```json
{
  "results": [
    {
      "matched": false,
      "input": "pemex",
      "normalizedKeyword": "pemex",
      "name": null,
      "category": null,
      "images": [],
      "message": "No matching image found"
    }
  ]
}
```

A no-match is also returned as **HTTP 200** with `matched: false`: a miss is not an error. When only some keywords match, matched and unmatched items appear together in the same array.

#### **HTTP status codes**

| Code | Meaning                                                                                                           |
| ---- | ----------------------------------------------------------------------------------------------------------------- |
| 200  | Successful lookup (including no-match)                                                                            |
| 400  | Malformed request. e.g. more than 4 keywords: `{ "error": "Too many keywords. Maximum 4 keywords per request." }` |

***

### 7. Response Field Reference (shared by both modes)

<table data-search="false"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>results</code></td><td>array</td><td>One item per matched entity. Always an array. <code>q=</code> also includes unmatched keywords as <code>matched: false</code> items; <code>headline=</code> returns matched entities only (empty array if none)</td></tr><tr><td><code>results[].matched</code></td><td>boolean</td><td>Whether this item matched</td></tr><tr><td><code>results[].input</code></td><td>string</td><td>The keyword / entity form found in the input</td></tr><tr><td><code>results[].normalizedKeyword</code></td><td>string</td><td>Normalized form (lowercased, special characters and spaces removed)</td></tr><tr><td><code>results[].name</code></td><td>string | null</td><td>Display name of the matched entity (e.g. "Bitcoin (BTC)"); <code>null</code> when there is no match</td></tr><tr><td><code>results[].category</code></td><td>string | null</td><td>Entity category slug, lowercase (<code>crypto</code>, <code>institutions</code>, <code>nations</code>, <code>currencies</code>, <code>commodities</code>, <code>people</code>, etc.); <code>null</code> when there is no match</td></tr><tr><td><code>results[].images</code></td><td>array</td><td>Cover images for the entity. One randomly assigned image by default; all of the group's images with <code>mode=extended</code>. Empty array when there is no match</td></tr><tr><td><code>results[].images[].url</code></td><td>string</td><td>Image URL (non-expiring; may change if the image is replaced or removed)</td></tr><tr><td><code>results[].images[].width</code></td><td>number</td><td>Width in px</td></tr><tr><td><code>results[].images[].height</code></td><td>number</td><td>Height in px</td></tr><tr><td><code>results[].images[].mimeType</code></td><td>string</td><td>Format (<code>image/jpeg</code>, <code>image/png</code>, etc.)</td></tr><tr><td><code>results[].images[].imageId</code></td><td>string</td><td>Unique image ID</td></tr><tr><td><code>results[].images[].groupId</code></td><td>string</td><td>ID of the entity's keyword group: use for entity-level deduplication across articles</td></tr><tr><td><code>results[].message</code></td><td>string</td><td>Reason for failure (present only when <code>matched: false</code>)</td></tr></tbody></table>

Images are delivered as the original file (**1750×1000**, 1.75:1).

***

### 8. Match Rate · Cover Composition · Fallback

#### **Cover composition strategies**

Same-entity keywords are merged server-side, so any two matched results are always two different entities: safe for split covers.

| Composition                                               | How                                                                                                                                                                                                                  |
| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Single image                                              | Compose the cover with one representative image only                                                                                                                                                                 |
| Two-image split                                           | Place two entities' images in a two-panel split cover (X/Twitter style)                                                                                                                                              |
| Adaptive <mark style="color:$primary;">(Recommend)</mark> | If two or more images match, split-cover the first two; if only one matches, use a single-image cover. If no images are returned, use your own fallback image or publish the story as text-only news without a cover |

#### **Fallback rules**

| Result                                                                    | Action                                                                             |
| ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| No match (`headline=` empty array, or all `q=` keywords `matched: false`) | use your own fallback cover or publish the story as text-only news without a cover |
| One or more matched                                                       | Compose the cover from the matched images                                          |

**A no-match check that works in both modes:** treat the response as a no-match when `results` contains zero items with `matched: true`. This single check behaves identically for `headline=` (empty array) and `q=` (which includes `matched: false` items).

**Reliability tip:** prepare a default fallback image, or a text-only news UI for stories without a cover.

#### **Match rate**

* **`headline=`**: We fed **5,000** real-world English news headlines directly into the API; about **89%** of headlines returned at least one cover.
* **`q=` (300 real news articles):** The match rate rises with keyword count: 79% with 1 keyword, 94% with 2, 98% with 3, and **99% with 4**. At the article level, **95%** of articles secured a cover.

The library expands continuously, so these figures keep improving.

***

### 9. Using NewsCover as an AI Tool (function calling)

If you re-edit external news with your own AI before publishing, register NewsCover as a tool for that AI. The rewriting model has already identified the article's entities. **With `headline=`, it simply passes the headline through**, so there is no keyword-extraction step at all.

#### **How it works**

1. Register the tool in your rewriting prompt.
2. While rewriting, the AI calls the tool once, passing the headline (`headline=`) or the core entities (`q=`).
3. The actual API call is made by your tool handler code, which injects the returned `url` into the output (e.g. a `coverImage` field).

**Example tool definition (`headline=`, recommended)**

```json
{
  "name": "get_news_cover",
  "description": "Returns news cover images for the entities in a news headline. Pass the article's headline text as-is; the service extracts entities and returns one cover per entity.",
  "parameters": {
    "type": "object",
    "properties": {
      "headline": {
        "type": "string",
        "description": "The article headline in English, unchanged."
      }
    },
    "required": ["headline"]
  }
}
```

#### **Example tool handler**

```js
async function get_news_cover(headline) {
  const res = await fetch(
    'https://api.ns3.ai/newscover?headline=' + encodeURIComponent(headline)
  );
  return await res.json();
}
```

*(To use `q=`, swap the parameter for comma-separated `keywords` and build the query the same way.)*

**Tips**

* Take the `url` directly from the tool response in your orchestrator code, not from text the model transcribed (URLs are long hash strings, so model transcription is error-prone). Alternatively, have the model output only the `imageId` and inject the URL in your code.
* Define in your system prompt what the AI should do on an empty response or `matched: false` (e.g. fall back to your default cover).
* The added cost is one tool call per article: the response is a few hundred tokens, negligible relative to the overall rewriting cost.

***

### 10. Image License & Quality Review

Images are sourced primarily from Wikimedia Commons and Wikipedia, and consist of **public-domain or openly licensed** works. They are provided for **editorial use**: identifying the company, asset, or person in news coverage.

* Within this purpose, publishing, cropping, resizing, and direct referencing (hotlinking) are allowed.
* Use outside news coverage (advertising, merchandise), resale or re-licensing to third parties, and redistribution as an image collection are not permitted.

Every image passes the following checks before registration:

* Individual license verification (public domain / open license)
* Grid-system normalization and optimization for the standard cover ratios (1:1, 1.75:1, 1.91:1, 2.5:1)
* A final human review before deployment

#### **Usage requirements**

* Covers must be credited to NS3. The standard form is **\[NewsCover by NS3]** alternative placements or formats can be agreed with the NS3 team.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ns3.ai/newscover-library.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
