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

# List Company Events

> Returns Events this company participates in, newest first. This is the same contract as `GET /api/v1/events`, scoped to a single company by the path. Plan gating, ordering, `updated_after` sync (including merge/removal tombstones for this company), and cursor semantics all match the flat resource; see its documentation for the full detail.

A tombstone respects the same event-grain filters as the flat resource, including `last_article_after`/`before`. A merged event's `last_article_at` freezes at merge time, so those filter a tombstone against that frozen value rather than against when the merge happened. `window` cannot be used for sync polling (mutually exclusive with `updated_after`).

Parameters that name or describe a different company or listing are rejected here with `400 invalid-parameter`: `company`, `ticker`, `watchlist`, `listed`, `exchange`, `market`, `domicile`, `index` and `sector`. The path already fixes the company; use `GET /api/v1/events` to filter the full collection by any of them. `watchlist=false` and `listed` with any value other than `true` remain inert. `mode` is rejected with `400 invalid-parameter`; use `GET /api/v1/events?company={company_id}&q={query}&mode=semantic` to search one company's events by meaning.

Responses carry an `ETag` and `Cache-Control: private, max-age=0, must-revalidate`; send the ETag back as `If-None-Match` to receive a `304 Not Modified`. There is no `Last-Modified`, so `If-Modified-Since` alone never revalidates. This is the same contract, and the same reason, as `GET /api/v1/events`. Requests carrying `q` or `updated_after` are not cached and return `Cache-Control: no-cache, no-store`.



## OpenAPI

````yaml https://nordicfinancialnews.com/openapi/v1/openapi.yaml get /api/v1/companies/{identifier}/events
openapi: 3.0.1
info:
  title: Nordic Financial News API
  version: v1.0
  description: >
    REST API for Nordic financial news. Each article is summarized in English
    (headline, short summary, and key points) with the original-language article
    linked via `article_url`. The full article body stays at the source.


    ## Authentication

    All endpoints require Bearer token authentication using an API key.

    Include the API key in the Authorization header:

    ```

    Authorization: Bearer YOUR_API_KEY

    ```


    ## Rate Limiting

    Rate limits apply per account, shared across every API key on that account —
    not per

    individual key:

    - **Free**: 100 requests/hour

    - **Plus**: 100 requests/hour

    - **Pro**: 5,000 requests/hour


    On Free and Plus, MCP tool calls have their own hourly and monthly allowance
    and do not

    count toward these REST limits. On Pro, REST requests and MCP tool calls
    share one allowance.


    Rate limit information is included in response headers:

    - `X-RateLimit-Limit`: Maximum requests per hour

    - `X-RateLimit-Remaining`: Requests remaining

    - `X-RateLimit-Reset`: Seconds until limit resets

    - `X-RateLimit-Policy`: Human-readable rate limit policy (e.g. `5000 per
    hour; fixed window`)


    A single client IP is additionally capped at 300 requests per 5-minute
    window, so

    reaching your account's full hourly allowance requires spreading requests
    across more

    than one source IP.


    The `/health` endpoint is exempt from rate limiting and does not return rate
    limit headers.


    ## Monthly Usage Limits

    Free and Plus accounts have a fixed monthly allowance that resets at the
    start of each

    calendar month, shared across every API key on the account:

    - **Free**: 100 requests/month

    - **Plus**: 100 requests/month


    Responses on these plans include:

    - `X-Monthly-Limit`: Maximum requests for the current month

    - `X-Monthly-Remaining`: Requests remaining this month

    - `X-Monthly-Reset`: ISO 8601 timestamp when the allowance resets


    When the allowance is exceeded, the API returns `429 Too Many Requests` with
    a `Retry-After` header.


    Pro has no hard limit. It includes 25,000 requests per billing cycle, with
    usage-based

    pricing beyond that, so requests are never blocked. Responses on Pro
    include:

    - `X-Monthly-Usage`: Requests used in the current billing cycle

    - `X-Monthly-Reset`: ISO 8601 timestamp when the current billing cycle ends


    A Pro billing cycle follows your subscription's billing period, which begins
    on the

    date you subscribed and is not necessarily a calendar month. Usage is
    counted by day,

    so the first day of a billing cycle is counted in full.


    ## Caching

    Every list and single-resource endpoint returns an `ETag`. Most also return

    `Last-Modified` (on lists, when the page is not empty); `GET /stories/{id}`
    and the

    Events endpoints do not. Send the ETag back as `If-None-Match`, or the date
    as

    `If-Modified-Since`, to receive `304 Not Modified` when nothing has changed.
    A 304

    has no body and does not count against the monthly request allowance.


    `GET /events`, `GET /events/{id}` and `GET /companies/{identifier}/events`
    return an

    `ETag` but no `Last-Modified`, so revalidate those routes with
    `If-None-Match`. An

    event's visible company and story membership, and its live article count,
    all change

    without moving its `updated_at`, so a date-based validator would report "not

    modified" across a change the `ETag` catches.


    Some requests are never cached and return `Cache-Control: no-cache,
    no-store` with

    no `ETag`: full-text search (`q`), `updated_after` sync requests, and `GET
    /search`.


    The `ETag` reflects the response as served, not only record timestamps. On
    articles

    and stories, including the company-scoped routes, and on `GET
    /calendar_events`, it

    changes when a plan limit alters the visible set, and on stories when a
    story's

    visible article set changes. A changed `ETag` does not necessarily mean a
    record was

    updated. On the Events endpoints the `ETag` additionally covers each event's
    visible

    company and story ids and its live article count, none of which move the
    event's

    `updated_at`.


    ## Pagination

    List endpoints support cursor-based pagination. Use the `cursor` parameter

    with the value from `pagination.next_cursor` in the response to fetch the
    next page.

    Paginated responses also include a `Link` header with `rel="next"` pointing
    to the next page URL.


    ## Incremental Sync

    To keep a local copy current, poll `updated_after`, not `published_after`.


    1. Request `?updated_after=<your last completed sync>`.

    2. Results are ordered by `updated_at` ascending and cursor-paginated.

    3. Follow `pagination.next_cursor`, resending the same `updated_after`,
    until it is `null`.

    4. Only then store the time the sync started, minus a small overlap, as your
    new
       watermark. A minute is plenty.

    Step 3 matters: a response is capped at `limit` (default 25, max 100), so a
    changed set

    larger than one page arrives across several. Advancing your watermark before
    draining

    every page skips the remainder.


    The overlap in step 4 matters for the same reason: a record's `updated_at`
    is set when

    the write happens, but it only becomes visible when that write commits a
    moment later.

    Without an overlap a record can be stamped just before your watermark and
    land just

    after it, and you would never ask for it again. Re-reading a minute of
    changes is

    cheap and idempotent.


    `published_at` is editorial time: when the news happened, not when the
    record reached

    this API. A record can therefore appear with a `published_at` older than one
    you already

    hold. Records are re-sent when they change, so reconcile by `id`.


    Removals are not signaled: an article withdrawn from the feed stops being
    returned.

    Incremental sync tells you what changed, not what disappeared, so treat a
    local mirror

    as append-and-update rather than an exact replica.


    ## Error Handling

    Errors follow the RFC 9457 Problem Details format with appropriate HTTP
    status codes.
  contact:
    name: API Support
    email: hello@nordicfinancialnews.com
servers:
  - url: https://nordicfinancialnews.com
    description: Production server
security: []
paths:
  /api/v1/companies/{identifier}/events:
    parameters:
      - name: identifier
        in: path
        required: true
        description: >-
          Company ID or ticker symbol. Accepts the exchange-suffixed form (e.g.
          `VOLV-B.ST`); former tickers resolve too. When a ticker is shared by
          more than one company, the company with a listing on a Nordic exchange
          is returned, then the one with an active listing, then the most
          recently listed. Use the company ID for an unambiguous lookup.
        schema:
          type: string
    get:
      tags:
        - Companies
      summary: List Company Events
      description: >-
        Returns Events this company participates in, newest first. This is the
        same contract as `GET /api/v1/events`, scoped to a single company by the
        path. Plan gating, ordering, `updated_after` sync (including
        merge/removal tombstones for this company), and cursor semantics all
        match the flat resource; see its documentation for the full detail.


        A tombstone respects the same event-grain filters as the flat resource,
        including `last_article_after`/`before`. A merged event's
        `last_article_at` freezes at merge time, so those filter a tombstone
        against that frozen value rather than against when the merge happened.
        `window` cannot be used for sync polling (mutually exclusive with
        `updated_after`).


        Parameters that name or describe a different company or listing are
        rejected here with `400 invalid-parameter`: `company`, `ticker`,
        `watchlist`, `listed`, `exchange`, `market`, `domicile`, `index` and
        `sector`. The path already fixes the company; use `GET /api/v1/events`
        to filter the full collection by any of them. `watchlist=false` and
        `listed` with any value other than `true` remain inert. `mode` is
        rejected with `400 invalid-parameter`; use `GET
        /api/v1/events?company={company_id}&q={query}&mode=semantic` to search
        one company's events by meaning.


        Responses carry an `ETag` and `Cache-Control: private, max-age=0,
        must-revalidate`; send the ETag back as `If-None-Match` to receive a
        `304 Not Modified`. There is no `Last-Modified`, so `If-Modified-Since`
        alone never revalidates. This is the same contract, and the same reason,
        as `GET /api/v1/events`. Requests carrying `q` or `updated_after` are
        not cached and return `Cache-Control: no-cache, no-store`.
      parameters:
        - name: limit
          in: query
          required: false
          description: Number of events to return per page (default 25, max 100).
          example: 25
          schema:
            type: integer
        - name: cursor
          in: query
          required: false
          description: >-
            Opaque pagination cursor from a previous response. Works with `q`
            too; `q` is a filter, not a separate search mode. When continuing an
            `updated_after` sync, resend the same `updated_after` value.
          schema:
            type: string
        - name: fields
          in: query
          required: false
          description: >-
            Comma-separated list of fields to include in the response. `id` is
            always included.
          example: title,status,article_count
          schema:
            type: string
        - name: updated_after
          in: query
          required: false
          description: >-
            ISO 8601 datetime. Returns only this company's events updated after
            this timestamp, including merge/removal tombstones. Use for
            incremental sync.
          example: '2026-03-01T00:00:00Z'
          schema:
            type: string
        - name: q
          in: query
          required: false
          description: >-
            Full-text filter over the event's own title and summary as well as
            its live member articles' indexed content (title, summary, key
            points, plus tagged company names and key facts), so an event can
            match on a company its coverage only tags. Matches stay in the
            default feed order (most recently reported first) and are
            cursor-paginated like any other request; combine with
            `window`/`last_article_after` for "latest on X".
          example: earnings
          schema:
            type: string
        - name: event_type
          in: query
          required: false
          description: >-
            Filter by event type slug, comma-separated. These are Events
            taxonomy slugs (hyphenated) from `GET /api/v1/event_types` and are
            the only values accepted here. The underscored calendar `event_type`
            values used by `GET /api/v1/calendar_events` are rejected. A few
            spellings overlap across the two vocabularies (e.g. `delisting`)
            while denoting different things. An unrecognized slug returns 400
            naming the bad slug(s).
          example: earnings-report
          schema:
            type: string
        - name: significance
          in: query
          required: false
          description: >-
            Editorial importance, the feed's materiality threshold,
            comma-separated (e.g. `notable,routine`). Valid values: `notable`
            (material, front-page-worthy events), `routine` (ledger records:
            routine filings, scheduled disclosures), `commentary`
            (opinion/analysis pieces). Use `significance=notable` to restrict
            the feed to material events. An unrecognized value returns 400
            naming the bad value(s).
          example: notable
          schema:
            type: string
        - name: sort
          in: query
          required: false
          description: >-
            Sort order. `latest` (default) sorts most recently reported first,
            the unfiltered feed order. `significance` groups events into 3
            coarse editorial tiers (`notable`, then `routine`, then
            `commentary`), most recently reported first within each tier; expect
            large ties within a tier. A mid-walk `routine`→`notable` escalation
            may be skipped, since the ordering is a best-effort snapshot. For a
            broad importance filter, prefer `significance=notable` with the
            default sort; page 1 is identical. Mutually exclusive with
            `updated_after` (an unrecognized value, or either sort value
            combined with `updated_after`, returns 400).
          example: significance
          schema:
            type: string
        - name: country
          in: query
          required: false
          description: >-
            Filter to events with a live member article from this country (ISO
            3166-1 alpha-2, comma-separated). Applied at the article grain, so
            sync tombstones do not respect it.
          example: SE
          schema:
            type: string
        - name: category
          in: query
          required: false
          description: >-
            Filter to events with a live member article in any of these
            categories, by their `id` (comma-separated; unknown ids are
            ignored). Applied at the article grain, so sync tombstones do not
            respect it.
          example: cat_earnings1
          schema:
            type: string
        - name: sources
          in: query
          required: false
          description: >-
            Filter to events with a live member article from these sources, by
            their `id` (comma-separated, max 25). Applied at the article grain,
            so sync tombstones do not respect it.
          example: src123456789
          schema:
            type: string
        - name: first_reported_after
          in: query
          required: false
          description: ISO 8601 datetime. Only events first reported at or after this time.
          example: '2026-01-01T00:00:00Z'
          schema:
            type: string
        - name: first_reported_before
          in: query
          required: false
          description: ISO 8601 datetime. Only events first reported before this time.
          example: '2026-12-31T23:59:59Z'
          schema:
            type: string
        - name: last_article_after
          in: query
          required: false
          description: >-
            ISO 8601 datetime. Only events whose most recent activity
            (`last_article_at`, or `first_reported_at` when that is null) is at
            or after this time. Mutually exclusive with `window`.
          example: '2026-03-01T00:00:00Z'
          schema:
            type: string
        - name: last_article_before
          in: query
          required: false
          description: >-
            ISO 8601 datetime. Only events whose most recent activity is before
            this time. Mutually exclusive with `window`.
          example: '2026-03-02T00:00:00Z'
          schema:
            type: string
        - name: window
          in: query
          required: false
          description: >-
            Relative shorthand for `last_article_after`, e.g. `8h`, `24h`, `7d`
            (hours or days only, max 365d equivalent). Evaluated per request
            against the server clock. Mutually exclusive with
            `last_article_after`, `last_article_before`, and `updated_after`.
          example: 24h
          schema:
            type: string
        - name: source_type
          in: query
          required: false
          description: >-
            Filter to events with a live member article from this source type,
            comma-separated. Valid values: `news_publication`, `wire_service`,
            `press_release`, `government`, `trade_publication`, `blog`,
            `stock_exchange`, `research`. Articles from disabled sources are
            excluded. Applied at the article grain, so sync tombstones do not
            respect it. An unrecognized value returns 400 naming the bad
            value(s).
          example: stock_exchange
          schema:
            type: string
        - name: content_type
          in: query
          required: false
          description: >-
            Filter to events with a live member article of this content type,
            comma-separated. Valid values: `news`, `analysis`, `press_release`,
            `market_commentary`, `market_news`, `trading_halt`, `trading_event`,
            `other`. Applied at the article grain, so sync tombstones do not
            respect it. An unrecognized value returns 400 naming the bad
            value(s). Content type is an AI-assigned label per article. To find
            events with a member article from a primary disclosure source,
            filter on `source_type` (`wire_service`, `stock_exchange`,
            `press_release`, `government`) instead.
          example: press_release
          schema:
            type: string
        - name: related_to
          in: query
          required: false
          description: >-
            Filter to commentary events that comment on or react to the factual
            event with this `id`. Unresolvable `id` returns an empty result set,
            not an error.
          example: evtcorswg01
          schema:
            type: string
        - name: include_peripheral
          in: query
          required: false
          description: >-
            When `true`, widen this feed, and the `company_ids` returned on each
            event, to events where this company has a peripheral role (advisor,
            speaker, or a passing mention) as well. Default `false` restricts to
            an active-involvement role (subject, acquirer, target, investor,
            issuer, partner).
          schema:
            type: boolean
        - name: If-None-Match
          in: header
          required: false
          description: >-
            ETag value from a previous response. Returns `304 Not Modified` if
            data has not changed.
          schema:
            type: string
      responses:
        '200':
          description: Company events retrieved successfully
          content:
            application/json:
              schema:
                type: object
                required:
                  - events
                  - pagination
                properties:
                  events:
                    type: array
                    items:
                      $ref: '#/components/schemas/EventSummary'
                  pagination:
                    type: object
                    properties:
                      count:
                        type: integer
                      next_cursor:
                        type: string
                        nullable: true
                  plan_limited:
                    type: boolean
                    description: >-
                      Present and `true` when your plan capped what this
                      endpoint can return. Absent when your plan applies no cap.
                    example: true
        '304':
          description: Not Modified
        '400':
          description: Invalid parameter
          content:
            application/json:
              examples:
                company_scoped_mode:
                  value:
                    type: >-
                      https://docs.nordicfinancialnews.com/problems/invalid-parameter
                    title: Invalid parameter
                    status: 400
                    detail: >-
                      mode is not supported on this endpoint. Use GET
                      /api/v1/events?company={company_id}&q={query}&mode=semantic
                      to search a single company's events by meaning.
                    instance: urn:request:a1b2c3
                    parameter: mode
              schema:
                $ref: '#/components/schemas/problem_details'
      security:
        - bearer_auth: []
components:
  schemas:
    EventSummary:
      type: object
      required:
        - id
        - status
        - updated_at
      description: >-
        An event: one real-world development, grouping the articles that report
        it. A `merged` or `removed` event (see `status`) returns only the
        minimal tombstone fields (`id`, `status`, `merged_into`, `updated_at`).
        Title, significance, event_type, counts, and every id array are omitted,
        never null-but-present, so a tombstone carries no content.
      properties:
        id:
          type: string
          description: Unique event identifier
          example: k3n8vdczq1mp
        title:
          type: string
          description: Event title (omitted on a tombstone)
          example: Volvo AB announces Q3 2026 results
        status:
          type: string
          description: >-
            Lifecycle status. `active`/`closed` are live (closed = coverage
            window lapsed but the event stays visible and can reopen). `merged`
            = absorbed into another event (see `merged_into`); `removed` =
            withdrawn from the feed (no live articles remain, or it was found to
            be incorrect). `merged`/`removed` never appear in the default list
            and carry only the tombstone fields.
          enum:
            - active
            - closed
            - merged
            - removed
          example: active
        significance:
          type: string
          description: >-
            Editorial importance (omitted on a tombstone). `notable` =
            front-page-worthy; `routine` = factual ledger record; `commentary` =
            single-article opinion/analysis.
          enum:
            - notable
            - routine
            - commentary
          example: notable
        event_type:
          type: object
          nullable: true
          description: The kind of event (omitted on a tombstone)
          properties:
            slug:
              type: string
              example: earnings-report
            label:
              type: string
              example: Earnings Report
            category:
              type: string
              example: earnings
        article_count:
          type: integer
          description: >-
            Number of live articles reporting this event (omitted on a
            tombstone). This is the total count. Your plan's age and source
            restrictions do not reduce it; use GET on the event to see which of
            them your plan can fetch.
          example: 3
        first_reported_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            When this event was first reported (ISO 8601, omitted on a
            tombstone): the earliest known publication time among this event's
            member articles. Falls back to `last_article_at` for ordering when
            null. This is editorial time, not the time the record reached this
            API.
          example: '2026-10-22T05:00:00.000Z'
        last_article_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            Publication time of the newest article reporting this event (ISO
            8601, omitted on a tombstone).
          example: '2026-10-23T09:15:00.000Z'
        updated_at:
          type: string
          format: date-time
          description: >-
            When this record last changed (ISO 8601). This is the clock
            incremental sync runs on. Pass your last completed sync time as
            `updated_after`, drain every page via `pagination.next_cursor`, and
            only then advance your stored timestamp.
          example: '2026-10-23T09:20:00.000Z'
        company_ids:
          type: array
          items:
            type: string
          description: >-
            IDs of companies associated with this event, verified and visible
            only (omitted on a tombstone). Restricted to companies with an
            active-involvement role (subject, acquirer, target, investor,
            issuer, partner) unless `include_peripheral=true`.
          example:
            - uejazctgchj4
        story_ids:
          type: array
          items:
            type: string
          description: >-
            IDs of published stories generated from this event, if any (omitted
            on a tombstone)
          example:
            - 8fzq2rmtnk5c
        merged_into:
          type: string
          nullable: true
          description: >-
            ID of the surviving event this one was merged into. Present only
            when `status` is `merged`; null for every other status, including
            `removed` and on some older merged events.
          example: v3xdq8fmz1kn
        related_to:
          type: string
          nullable: true
          description: >-
            Commentary-only metadata: the `id` of the factual event this
            commentary event comments on or reacts to, when the piece is about a
            specific factual event. Always null for non-commentary events, and
            often null for commentary events too (the piece may not be about a
            specific event). Filter with `related_to=<id>` to find commentary
            reacting to a given event.
          example: v3xdq8fmz1kn
    problem_details:
      type: object
      required:
        - type
        - title
        - status
        - detail
        - instance
      properties:
        type:
          type: string
          description: URI that identifies the problem type
        title:
          type: string
          description: Short human-readable summary
        status:
          type: integer
          description: HTTP status code
        detail:
          type: string
          description: Human-readable explanation
        instance:
          type: string
          description: URI that identifies the specific occurrence
  securitySchemes:
    bearer_auth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: API Key authentication using Bearer token

````