> ## Documentation Index
> Fetch the complete documentation index at: https://docs.truscan.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Search the news

> The same recall with the clock turned up. Not a second search: it builds the same query and runs the same ranking, and differs in exactly three ways.

The freshness window defaults to a week rather than unbounded. An unbounded news search returns the best-ranked article on a subject, which is routinely years old.

Publishers can be filtered by list, with sources and exclude_sources.

sort_by=date is available and means what it says.

Sending category here is rejected rather than ignored, because overriding it silently would leave you believing the parameter did something.



## OpenAPI

````yaml /api-reference/search.json post /api/search/news
openapi: 3.1.0
info:
  title: Truscan search
  version: 1.0.0
  description: >-
    A web search API. One query is fanned out across many independent sources,
    then deduplicated, extracted, ranked, and returned with a score it will
    explain. Every response uses the {success, result, message} envelope except
    where noted.
servers:
  - url: https://api.truscan.co
    description: Production
security: []
paths:
  /api/search/news:
    post:
      summary: Search the news
      description: >-
        The same recall with the clock turned up. Not a second search: it builds
        the same query and runs the same ranking, and differs in exactly three
        ways.


        The freshness window defaults to a week rather than unbounded. An
        unbounded news search returns the best-ranked article on a subject,
        which is routinely years old.


        Publishers can be filtered by list, with sources and exclude_sources.


        sort_by=date is available and means what it says.


        Sending category here is rejected rather than ignored, because
        overriding it silently would leave you believing the parameter did
        something.
      operationId: news
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequest'
      responses:
        '200':
          description: Ranked results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchEnvelope'
              example:
                success: true
                message: Found 2 results.
                result:
                  id: srch_46b56d1ae8f127a8
                  query: how does TLS certificate pinning work
                  tier: instant
                  total: 2
                  format: json
                  results:
                    - rank: 1
                      url: https://www.ssl.com/blogs/what-is-certificate-pinning/
                      title: What Is Certificate Pinning? - SSL.com
                      snippet: >-
                        Certificate pinning is a security mechanism used in the
                        context of authenticating client-server connections.
                      domain: ssl.com
                      score: 0.6622
                      components:
                        consensus: 1
                        position: 1
                        lexical: 0.3553
                        proximity: 0.5556
                        authority: 0.5
                        freshness: 0
                      content:
                        text: >-
                          What Is Certificate Pinning? Certificate pinning is a
                          security mechanism...
                        markdown: |-
                          ## What Is Certificate Pinning?

                          Certificate pinning is a security mechanism...
                        excerpt: >-
                          What Is Certificate Pinning? SSL/TLS related content
                          explaining the mechanism.
                        words: 783
                        lang: en
                        site_name: SSL.com
                  stats:
                    took_ms: 2143
                    recall_ms: 1152
                    enrich_ms: 991
                    candidates: 46
                    deduped: 20
                    enriched: 2
                    cached: false
        '400':
          $ref: '#/components/responses/Failure'
        '422':
          $ref: '#/components/responses/Failure'
        '429':
          $ref: '#/components/responses/Failure'
        '502':
          $ref: '#/components/responses/Failure'
components:
  schemas:
    SearchRequest:
      type: object
      required:
        - query
      properties:
        query:
          type: string
          maxLength: 512
        q:
          type: string
          description: Accepted as an alias for query.
        tier:
          type: string
          enum:
            - instant
            - fast
            - auto
            - deep
            - deep_reasoning
          default: instant
          description: >-
            Search depth, which sets how many pages one search reads: instant up
            to 10, deep up to 50, deep_reasoning up to 100. The budget is
            absolute rather than a multiple of limit, and a search never reads
            more pages than it recalled.
        limit:
          type: integer
          minimum: 1
          maximum: 50
          default: 10
        enrich:
          type: boolean
          default: true
          description: >-
            Fetch and extract page bodies for the top results. Off is roughly
            ten times faster and returns engine snippets only.
        format:
          type: string
          enum:
            - json
            - markdown
            - text
          default: json
        site:
          type: string
          description: Restrict to one host.
        lang:
          type: string
        freshness:
          type: string
          enum:
            - any
            - day
            - week
            - month
            - year
        category:
          type: string
          enum:
            - general
            - news
            - science
            - images
            - videos
            - it
          default: general
        structured:
          type: boolean
          default: false
          description: >-
            Ask each enriched page for what it declares about itself: JSON-LD,
            OpenGraph, Twitter cards, microdata, feeds and contacts. Implies
            enrich, because there is nothing to read declarations off a page
            that was never fetched. Free: pages read is what is billed and the
            page was fetched either way.
        sources:
          type: array
          items:
            type: string
          description: >-
            Only these publishers. Accepts a bare hostname or a pasted URL, and
            matches subdomains. Unlike site, which goes upstream as a search
            operator, a list is applied after recall, because no engine accepts
            one as a single query.
          examples:
            - - reuters.com
              - apnews.com
        exclude_sources:
          type: array
          items:
            type: string
          description: Never these publishers. An exclude always beats an include.
        sort_by:
          type: string
          enum:
            - relevance
            - date
          default: relevance
          description: >-
            date orders newest first, applied after ranking and before the list
            is cut to the limit, so it means the newest of everything that
            matched rather than the newest of the handful already on top.
            Results with no date sink below dated ones rather than being
            dropped.
    SearchEnvelope:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        result:
          $ref: '#/components/schemas/SearchResponse'
    SearchResponse:
      type: object
      properties:
        id:
          type: string
        query:
          type: string
        corrected_query:
          type: string
          description: >-
            Present only when the original query matched nothing and these
            results came from a spelling correction. query keeps what was asked,
            so a client can show both and offer to search the original anyway.
        tier:
          type: string
          enum:
            - instant
            - deep
            - deep_reasoning
          description: >-
            The tier this search actually ran at, which is what billing charges
            for.
        total:
          type: integer
        format:
          type: string
          enum:
            - json
            - markdown
            - text
        rendered:
          type: string
          description: The markdown or text view. Empty for format=json.
        results:
          type: array
          items:
            $ref: '#/components/schemas/Result'
        stats:
          $ref: '#/components/schemas/Stats'
    Failure:
      type: object
      properties:
        success:
          type: boolean
          const: false
        message:
          type: string
          description: Written for a person.
        result:
          type: object
          properties:
            code:
              type: string
    Result:
      type: object
      properties:
        rank:
          type: integer
        url:
          type: string
          format: uri
        title:
          type: string
        snippet:
          type: string
        domain:
          type: string
        score:
          type: number
        components:
          $ref: '#/components/schemas/Components'
        published_at:
          type: string
          format: date-time
        content:
          $ref: '#/components/schemas/Content'
    Stats:
      type: object
      properties:
        took_ms:
          type: integer
        recall_ms:
          type: integer
        enrich_ms:
          type: integer
        candidates:
          type: integer
          description: How many hits recall produced, before dedupe and ranking.
        deduped:
          type: integer
          description: >-
            How many remain after merging the same page returned by several
            engines and collapsing syndicated copies of one story. The gap
            against candidates is what recall breadth bought.
        enriched:
          type: integer
          description: >-
            How many returned results carry extracted content. This is the
            number billed for extraction. Ranking may read more pages than this
            to place them, and that extra width is not charged.
        cached:
          type: boolean
    Components:
      type: object
      description: >-
        The score, itemised, so a caller can tune against real output instead of
        guessing.
      properties:
        consensus:
          type: number
          description: Independent engine agreement.
        position:
          type: number
          description: The upstream sources' own ranking.
        lexical:
          type: number
          description: BM25 over title, snippet and body.
        proximity:
          type: number
          description: How close the query terms sit to each other.
        authority:
          type: number
          description: An offline host-quality prior.
        freshness:
          type: number
          description: Age decay. Zero unless the query asked for recency.
    Content:
      type: object
      properties:
        text:
          type: string
          description: Readable prose with navigation, banners and footers removed.
        markdown:
          type: string
          description: The same content with headings, lists and links preserved.
        excerpt:
          type: string
        words:
          type: integer
        lang:
          type: string
        author:
          type: string
        site_name:
          type: string
        truncated:
          type: boolean
        error:
          type: string
          description: >-
            Why this page has no content. Present instead of an empty text
            field, which would be indistinguishable from a genuinely empty page.
        highlights:
          type: array
          items:
            $ref: '#/components/schemas/Highlight'
        links:
          type: array
          items:
            type: string
            format: uri
          description: Present only when links was requested.
        images:
          type: array
          items:
            type: string
            format: uri
          description: Present only when links was requested.
        structured:
          $ref: '#/components/schemas/Structured'
    Highlight:
      type: object
      description: >-
        A passage that matched, with its offsets into content.text, so a UI can
        render it without re-running the match.
      properties:
        text:
          type: string
        start:
          type: integer
        end:
          type: integer
        score:
          type: number
    Structured:
      type: object
      description: >-
        What the page declares about itself. Present only when structured was
        requested and the page declared something. Every value is reported as
        published: nothing is normalised, merged or inferred.
      properties:
        jsonld:
          type: array
          items:
            type: object
            additionalProperties: true
          description: >-
            Each ld+json entity. Top-level arrays and @graph containers are
            flattened because both are wrappers rather than data, and @context
            is carried down to any entity that does not declare its own. A block
            that will not parse is skipped rather than reported.
        opengraph:
          type: object
          additionalProperties:
            type: string
          description: >-
            og: meta tags with the prefix stripped. A repeated key keeps the
            first.
        twitter:
          type: object
          additionalProperties:
            type: string
          description: 'twitter: meta tags with the prefix stripped.'
        microdata:
          type: array
          items:
            $ref: '#/components/schemas/MicrodataItem'
        feeds:
          type: array
          items:
            $ref: '#/components/schemas/Feed'
          description: rel=alternate RSS and Atom links, resolved against the page.
        canonical:
          type: string
          format: uri
          description: >-
            The page's own statement of where it lives, which is often not the
            URL you fetched.
        emails:
          type: array
          items:
            type: string
          description: >-
            From mailto: hrefs only, lowercased and deduplicated. Never matched
            out of the prose, because a pattern over body text returns version
            numbers and dates as often as addresses.
        phones:
          type: array
          items:
            type: string
          description: 'From tel: hrefs only, exactly as written.'
    MicrodataItem:
      type: object
      description: >-
        One itemscope and the itemprops directly inside it. A nested itemscope
        is reported as its own entry rather than embedded, because microdata
        nests by reference as often as by containment and a half-resolved tree
        is worse than a flat list.
      properties:
        type:
          type: string
          description: The itemtype URL, when declared.
        properties:
          type: object
          additionalProperties:
            type: string
    Feed:
      type: object
      properties:
        title:
          type: string
        url:
          type: string
          format: uri
        type:
          type: string
          description: The declared MIME type, such as application/rss+xml.
  responses:
    Failure:
      description: >-
        The envelope with success false. result carries the machine-readable
        code and nothing else; the HTTP status line carries the real status.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Failure'

````