---
title: "Bulk submit news articles for analysis"
method: POST
path: "/api/news/analyse"
tags: ["News"]
---

# Bulk submit news articles for analysis

`POST /api/news/analyse`

## Request

- Base URL: `https://api.sponsorunited.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.sponsorunited.com/api/news/analyse`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/sponsorunited/apis/sponsorunited-api/docs/api/news/analyse/post.ts> (a function with typed inputs; its response is checked against the schema)

Accepts either a plain `urls` array or an `articles` array carrying per-article data (news tags), creates CuratedNews records in pending status, syncs brand/property/agency relationships and any submitted tags, and dispatches each to the data-ingestion service for content extraction. Re-submitting a URL whose article previously failed returns it to pending and dispatches a fresh analysis; a URL already in the queue is reported as already_exists without dispatching anything, though any submitted tags are still attached.

## Headers

- `X-Agent-Name` string

## Request body

- AnalyseCuratedNewsRequest: Submit articles for analysis in one of two mutually exclusive shapes: the plain `urls` list, or `articles` when per-article data (news tags) travels with each URL. Exactly one of the two is required.
  - `urls` string[]: Article URLs with no per-article data. Mutually exclusive with `articles`.
  - `articles` AnalyseCuratedNewsArticle[]: Articles submitted with per-article data. Mutually exclusive with `urls`.
    - `url` string, url, required
    - `news_tag_ids` integer[]: News tags to attach to this article, by id. Resolve ids from GET /api/news-tags by name — they differ between environments, so never hardcode one. Attached additively: re-submitting an article never detaches a tag a scout added during review.
    - `funding` AnalyseCuratedNewsFunding: Structured funding data extracted by the submitting pipeline and passed through rather than re-derived from article text. Every field is optional: plenty of rounds disclose no valuation, and some report no round at all.
      - `company` string, nullable
      - `website` string, nullable
      - `amount_raised` AnalyseCuratedNewsFundingMoney: One money figure in three representations: as written in the article, parsed in its original currency, and normalized to USD by the submitter. There is no server-side currency conversion.
        - `raw` string, nullable: The figure as written in the article.
        - `value` number, float, nullable
        - `currency` string, nullable: ISO 4217 code.
        - `usd` number, float, nullable
      - `valuation` AnalyseCuratedNewsFundingMoney: One money figure in three representations: as written in the article, parsed in its original currency, and normalized to USD by the submitter. There is no server-side currency conversion.
        - `raw` string, nullable: The figure as written in the article.
        - `value` number, float, nullable
        - `currency` string, nullable: ISO 4217 code.
        - `usd` number, float, nullable
      - `funding_round` string, nullable: A named stage (Seed, Series A through E) or the catch-all form 'Others (…)', whose parenthetical is kept alongside the stored case. Anything else is rejected rather than stored as free text.
      - `investors` string[]: Investor names. Repeats within one payload collapse to a single record.
      - `market` string, nullable: The deal's business sector, e.g. 'Fintech'. Stored as `sector`: `market` already means geography elsewhere in this API, so the response spells it `sector`.
    - `contacts` AnalyseCuratedNewsContact[]: People the submitting pipeline already extracted from the article. Stored as extracted contacts so they go through the same resolve / match / add review as any other, and surface on the article analysis page. No platform contact is created at submission time — adding one stays a reviewer action.
      - `name` string, required
      - `role` string, nullable
      - `linkedin` string, nullable
  - `companies` integer[]
  - `agencies` integer[]
  - `teams` integer[]
  - `extract_entities` boolean: When true (default), entity extraction (brand/property/agency) runs in parallel with contact extraction.
  - `extract_contacts` boolean: When true (default), contact extraction runs after markdown conversion completes.
  - `extract_assets` boolean: When true (default), asset extraction runs after markdown conversion completes, in parallel with contact extraction.

## Response `201`

URLs submitted for analysis

- AnalyseCuratedNewsResultsResource
  - `results` AnalyseCuratedNewsResource[]
    - `url` string
    - `status` 'success' | 'already_exists' | 'failed': `success` = newly queued for analysis; `already_exists` = the article was already in the queue (the submitter is attached as a reporter, nothing re-dispatched); `failed` = could not be processed.
    - `is_new` boolean: True only when this submission created and queued a new article. False for `already_exists` and `failed`.
    - `curated_news` object, nullable
      - `id` integer
      - `url` string
      - `status` string
      - `reporter_id` integer
      - `ingestion_request_id` string, nullable
      - `created_at` string, date-time
    - `error` string, nullable

## Other responses

- `403`: Forbidden (missing news administration permission)
- `422`: Validation error

---

[API](https://skmtc.dev/sponsorunited/apis/sponsorunited-api.md) - [All operations](https://skmtc.dev/sponsorunited/apis/sponsorunited-api/llms.txt) - [OpenAPI document](https://skmtc.dev/sponsorunited/apis/sponsorunited-api/revisions/cbf1ca5bff8f?raw)
