openapi: 3.1.0
info:
  title: Firmadatabasen API
  version: "1.0.0"
  description: >-
    Offentlig REST-API for norsk selskapsdata fra Brønnøysundregistrene
    (~1,15 millioner selskaper) med regnskap og beregnede nøkkeltall.
    Data oppdateres nattlig. Kun GET-metoder. Alle /v1-kall krever API-nøkkel.
  contact:
    name: Raunic AS
    url: https://firmadatabasen.no/api
    email: salg@firmadatabasen.no
  license:
    name: Proprietær — krever abonnement
    url: https://firmadatabasen.no/vilkar
servers:
  - url: https://api.firmadatabasen.no
    description: Produksjon
security:
  - ApiKeyAuth: []
tags:
  - name: Selskap
  - name: Søk
  - name: System
paths:
  /health:
    get:
      tags: [System]
      summary: Helsesjekk
      description: Uautentisert helsesjekk.
      security: []
      responses:
        "200":
          description: Tjenesten er oppe
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  timestamp:
                    type: string
                    format: date-time
  /v1/company/{orgNumber}:
    get:
      tags: [Selskap]
      summary: Slå opp selskap på organisasjonsnummer
      description: >-
        Returnerer grunndata, adresse, kontaktinfo, inntil 5 siste regnskapsår
        og 5 beregnede nøkkeltall. Slettede selskaper får adresse og kontakt
        nullet (GDPR); kommune/fylke beholdes.
      parameters:
        - name: orgNumber
          in: path
          required: true
          description: Nøyaktig 9 sifre
          schema:
            type: string
            pattern: "^[0-9]{9}$"
            example: "924831723"
      responses:
        "200":
          description: Selskap funnet
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: "#/components/schemas/Company"
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "404":
          $ref: "#/components/responses/NotFound"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/ServerError"
  /v1/search:
    get:
      tags: [Søk]
      summary: Søk etter selskaper
      description: >-
        Minst én av q, municipality, industryCode, organizationForm,
        employeesMin eller employeesMax kreves. Cursor-paginering via nextCursor.
      parameters:
        - name: q
          in: query
          description: Firmanavn eller orgnr (9 sifre gir eksakt treff)
          schema:
            type: string
            minLength: 1
            maxLength: 200
        - name: municipality
          in: query
          description: Kommunenavn i store bokstaver
          schema:
            type: string
            maxLength: 100
            example: OSLO
        - name: industryCode
          in: query
          description: NACE-kode
          schema:
            type: string
            maxLength: 20
            example: "62.100"
        - name: organizationForm
          in: query
          schema:
            type: string
            maxLength: 20
            example: AS
        - name: employeesMin
          in: query
          schema:
            type: integer
            minimum: 0
        - name: employeesMax
          in: query
          schema:
            type: integer
            minimum: 0
        - name: limit
          in: query
          schema:
            type: integer
            minimum: 1
            maximum: 50
            default: 25
        - name: cursor
          in: query
          description: Verdien fra nextCursor i forrige respons
          schema:
            type: string
            maxLength: 50
      responses:
        "200":
          description: Søkeresultat
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/SearchResult"
                  nextCursor:
                    type: [string, "null"]
        "400":
          $ref: "#/components/responses/BadRequest"
        "401":
          $ref: "#/components/responses/Unauthorized"
        "429":
          $ref: "#/components/responses/RateLimited"
        "500":
          $ref: "#/components/responses/ServerError"
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: "API-nøkkel med prefiks fdb_. Alternativt Authorization: Bearer fdb_..."
  responses:
    BadRequest:
      description: Valideringsfeil
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    Unauthorized:
      description: Manglende, ugyldig eller revokert nøkkel
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    NotFound:
      description: Ukjent organisasjonsnummer eller rute
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    RateLimited:
      description: Rate limit eller månedskvote overskredet. Se Retry-After-headeren.
      headers:
        Retry-After:
          description: Sekunder til neste tillatte forsøk
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
    ServerError:
      description: Serverfeil
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
        details:
          type: array
          items:
            type: string
    Company:
      type: object
      properties:
        orgNumber:
          type: string
        name:
          type: [string, "null"]
        organizationForm:
          type: [string, "null"]
        industry:
          type: object
          properties:
            code:
              type: [string, "null"]
            description:
              type: [string, "null"]
        address:
          type: object
          properties:
            street:
              type: [string, "null"]
            postalCode:
              type: [string, "null"]
            city:
              type: [string, "null"]
            municipality:
              type: [string, "null"]
            municipalityNumber:
              type: [string, "null"]
            county:
              type: [string, "null"]
        contact:
          type: object
          properties:
            website:
              type: [string, "null"]
            email:
              type: [string, "null"]
            phone:
              type: [string, "null"]
        employees:
          type: [integer, "null"]
        dates:
          type: object
          properties:
            registered:
              type: [string, "null"]
              format: date-time
            founded:
              type: [string, "null"]
              format: date-time
            deleted:
              type: [string, "null"]
              format: date-time
        status:
          type: object
          properties:
            konkurs:
              type: boolean
            underAvvikling:
              type: boolean
            underTvangsavvikling:
              type: boolean
            mvaRegistered:
              type: boolean
        accounting:
          type: array
          items:
            $ref: "#/components/schemas/AccountingEntry"
        metrics:
          oneOf:
            - type: array
              items:
                $ref: "#/components/schemas/Metric"
            - type: "null"
    AccountingEntry:
      type: object
      properties:
        fiscalYear:
          type: integer
        type:
          type: [string, "null"]
        revenue:
          type: [number, "null"]
        operatingProfit:
          type: [number, "null"]
        netProfit:
          type: [number, "null"]
        totalAssets:
          type: [number, "null"]
        totalEquity:
          type: [number, "null"]
        totalDebt:
          type: [number, "null"]
    Metric:
      type: object
      properties:
        label:
          type: string
        desc:
          type: string
        value:
          type: [number, "null"]
        unit:
          type: string
        color:
          type: string
          enum: [green, amber, red]
        rating:
          type: string
        radar:
          type: number
    SearchResult:
      type: object
      properties:
        id:
          type: string
        orgNumber:
          type: string
        name:
          type: [string, "null"]
        organizationForm:
          type: [string, "null"]
        industryCode:
          type: [string, "null"]
        industryDescription:
          type: [string, "null"]
        municipality:
          type: [string, "null"]
        numberOfEmployees:
          type: [integer, "null"]
        konkurs:
          type: boolean
        underAvvikling:
          type: boolean
