> ## 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.

# Get Event

> Fetches a single event by ID.

A merged or removed event returns 200 with the minimal tombstone shape (see the list endpoint's description) rather than 404. The id still resolves; it carries no content. An event with no live member articles at all returns 404. An event whose live members exist but are all outside your plan's age/source restrictions returns 403 with an upgrade problem, distinct from the plain 404.

Responses are cached with `ETag` and `Cache-Control: private, max-age=300`; send `If-None-Match` to receive a `304 Not Modified`. There is no `Last-Modified` here, for the same reason as `GET /api/v1/events`.



## OpenAPI

````yaml https://nordicfinancialnews.com/openapi/v1/openapi.yaml get /api/v1/events/{id}
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/events/{id}:
    parameters:
      - name: id
        in: path
        required: true
        description: The event ID, as returned in the `id` field of list responses.
        example: evt_volvoq3ma1
        schema:
          type: string
    get:
      tags:
        - Events
      summary: Get Event
      description: >-
        Fetches a single event by ID.


        A merged or removed event returns 200 with the minimal tombstone shape
        (see the list endpoint's description) rather than 404. The id still
        resolves; it carries no content. An event with no live member articles
        at all returns 404. An event whose live members exist but are all
        outside your plan's age/source restrictions returns 403 with an upgrade
        problem, distinct from the plain 404.


        Responses are cached with `ETag` and `Cache-Control: private,
        max-age=300`; send `If-None-Match` to receive a `304 Not Modified`.
        There is no `Last-Modified` here, for the same reason as `GET
        /api/v1/events`.
      parameters:
        - name: If-None-Match
          in: header
          required: false
          description: >-
            ETag value from a previous response. Returns `304 Not Modified` if
            the event has not changed.
          schema:
            type: string
        - name: include_peripheral
          in: query
          required: false
          description: >-
            When `true`, `company_ids` and `companies[]` also include companies
            with a peripheral role (advisor, speaker, or a passing mention).
            Default `false` lists companies with an active-involvement role only
            (subject, acquirer, target, investor, issuer, partner).
            `association_tier` is present on every `companies[]` entry
            regardless.
          schema:
            type: boolean
      responses:
        '200':
          description: Event retrieved
          content:
            application/json:
              examples:
                event_detail:
                  value:
                    event:
                      id: evt_volvoq3ma1
                      title: Volvo AB announces Q3 2026 results
                      status: active
                      significance: notable
                      event_type:
                        slug: earnings-report
                        label: Earnings Report
                        category: earnings
                      article_count: 3
                      first_reported_at: '2026-10-22T05:00:00.000Z'
                      last_article_at: '2026-10-23T09:15:00.000Z'
                      updated_at: '2026-10-23T09:20:00.000Z'
                      company_ids:
                        - uejazctgchj4
                      story_ids:
                        - story_volvo_q3
                      merged_into: null
                      related_to: null
                      summary: >-
                        Volvo AB reported Q3 2026 results, beating analyst
                        expectations on strong truck demand...
                      article_ids:
                        - art_abc123def
                        - art_def456ghi
                      primary_disclosure_article_id: art_abc123def
                      member_figures_disagree: false
                      figure_divergence: null
                      companies:
                        - id: uejazctgchj4
                          name: AB Volvo (Volvo Group)
                          ticker: VOLV-B
                          is_primary: true
                          association_tier: principal
              schema:
                type: object
                required:
                  - event
                properties:
                  event:
                    $ref: '#/components/schemas/EventDetail'
        '304':
          description: Not Modified
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/problem_details'
        '403':
          description: Event is outside this plan's access window
          content:
            application/json:
              examples:
                plan_limit_forbidden:
                  value:
                    type: >-
                      https://docs.nordicfinancialnews.com/problems/plan-limit-exceeded
                    title: Event not available on your plan
                    status: 403
                    detail: >-
                      This event's coverage falls outside your plan's access
                      window or is restricted to premium sources your plan
                      doesn't include.
                    instance: urn:request:a1b2c3
              schema:
                $ref: '#/components/schemas/problem_details'
        '404':
          description: Event not found
          content:
            application/json:
              examples:
                not_found:
                  value:
                    type: https://docs.nordicfinancialnews.com/problems/not-found
                    title: Not Found
                    status: 404
                    detail: The requested resource could not be found
                    instance: urn:request:a1b2c3
              schema:
                $ref: '#/components/schemas/problem_details'
      security:
        - bearer_auth: []
components:
  schemas:
    EventDetail:
      allOf:
        - $ref: '#/components/schemas/EventSummary'
        - type: object
          properties:
            summary:
              type: string
              nullable: true
              description: >-
                Event summary (omitted on a tombstone). Null when no summary has
                been generated for the event yet.
              example: >-
                Volvo AB reported Q3 2026 results, beating analyst expectations
                on strong truck demand...
            article_ids:
              type: array
              items:
                type: string
              description: >-
                IDs of this event's live articles that your plan can fetch,
                oldest first by publication time (omitted on a tombstone). May
                be shorter than `article_count` on a plan with age or source
                restrictions. That gap is not an error.
              example:
                - h4mzq918kxwc
                - q2fnk75dxzmv
            primary_disclosure_article_id:
              type: string
              nullable: true
              description: >-
                The primary disclosure among this event's live articles your
                plan can fetch: the earliest one from a primary-disclosure
                source (wire service, stock exchange feed, PR platform, or
                government body). Null when the event has none. Always an
                element of `article_ids`, or null; omitted on a tombstone. A
                plan with age or source restrictions may see a later official
                copy of the same disclosure, or null, instead of the true
                earliest one.
              example: h4mzq918kxwc
            member_figures_disagree:
              type: boolean
              description: >-
                True when this event's own member articles report divergent
                values for the same headline figure (e.g. one source reports
                operating profit as −2.2m, another as −2.4m). A signal that the
                single consolidated summary hides a source-level disagreement.
                Omitted on a tombstone.
              example: false
            figure_divergence:
              type: object
              nullable: true
              description: >-
                Detail behind `member_figures_disagree`: the specific metrics
                whose values disagree across member articles, with the
                per-source figures and range. Null when there is no
                disagreement; omitted on a tombstone.
              properties:
                groups:
                  type: array
                  description: One entry per disagreeing metric.
                  items:
                    type: object
                    properties:
                      concept:
                        type: string
                        description: The canonical measure that disagrees
                        example: operating_profit
                      basis:
                        type: string
                        description: >-
                          Whether the measure is as-reported or an
                          adjusted/alternative one
                        example: reported
                      role:
                        type: string
                        description: >-
                          Whether the figure is an outcome, forecast, or
                          comparative
                        example: actual
                      period:
                        type: string
                        description: The reporting period the figure covers
                        example: 2026-Q1
                      currency:
                        type: string
                        description: ISO currency of the figures
                        example: SEK
                      labels:
                        type: array
                        items:
                          type: string
                        description: The source's own wording(s) for the measure
                        example:
                          - Rörelseresultatet
                      min:
                        type: number
                        description: Smallest reported value (absolute base units)
                        example: 313000000
                      max:
                        type: number
                        description: Largest reported value (absolute base units)
                        example: 395000000
                      values:
                        type: array
                        description: The reported figure per member article.
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                              description: The reporting article's id
                              example: h4mzq918kxwc
                            source:
                              type: string
                              nullable: true
                              description: The reporting source's name
                              example: MFN
                            normalized_value:
                              type: number
                              description: The figure in absolute base units
                              example: 395000000
                            value:
                              type: string
                              description: The figure as originally stated
                              example: 395 MSEK
            companies:
              type: array
              description: >-
                The same companies as `company_ids`, with detail per company:
                name, ticker, primary flag, association tier. Primary company
                first; omitted on a tombstone.
              items:
                type: object
                required:
                  - id
                  - name
                  - is_primary
                  - association_tier
                properties:
                  id:
                    type: string
                    description: Unique company identifier
                    example: uejazctgchj4
                  name:
                    type: string
                    description: Company name
                    example: AB Volvo (Volvo Group)
                  ticker:
                    type: string
                    nullable: true
                    description: Primary stock ticker
                    example: VOLV-B
                  is_primary:
                    type: boolean
                    description: Whether this company is the primary subject of the event
                    example: true
                  association_tier:
                    type: string
                    enum:
                      - principal
                      - peripheral
                    description: >-
                      How the company relates to the event. `principal`
                      (subject, acquirer, target, investor, issuer, partner) is
                      the default set; `peripheral` (advisor, speaker, passing
                      mention) appears only when `include_peripheral=true`.
                      Always present.
                    example: principal
    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
    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
  securitySchemes:
    bearer_auth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: API Key authentication using Bearer token

````