Skip to main content

Firmaradar Python SDK

Official Python SDK for Firmaradar — the enrichment platform for Norwegian company intelligence. Firmaradar fuses data from multiple authoritative sources (Brønnøysundregistrene, Skatteetaten, foreign PEP/sanctions registers, public-grants registries) and adds proprietary enrichment on top — so a single call returns a decision-ready view for KYC, AML, credit, ownership and risk workflows, not a raw registry record.

The SDK is a thin, fully typed client over the Firmaradar REST API (httpx + Pydantic v2), with sync and async variants and optional LangChain / LlamaIndex tool wrappers for AI-agent stacks.

Installation

pip install firmaradar                # core SDK
pip install 'firmaradar[langchain]'   # + LangChain tool wrappers
pip install 'firmaradar[llamaindex]'  # + LlamaIndex tool spec
pip install 'firmaradar[all]'         # everything

From source (this repo):

pip install ./sdk/python              # or: pip install -e './sdk/python[all]'

Requires Python 3.10+.

Authentication

The SDK authenticates with a Firmaradar API key, sent as the X-API-Key header. Pass it explicitly or set the FIRMARADAR_API_KEY environment variable:

from firmaradar import Firmaradar

fr = Firmaradar(api_key="fr_...")   # or: export FIRMARADAR_API_KEY=fr_...

API keys are managed on your Firmaradar account at firmaradar.no.

Quickstart

from firmaradar import Firmaradar

fr = Firmaradar()  # reads FIRMARADAR_API_KEY

# Find a company, then pull its decision-ready profile
page = fr.companies.search("Equinor")
orgnr = page.items[0].orgnr

company = fr.companies.get(orgnr, fields=["group", "owners", "grants"])
print(company.navn, "-", company.summary)

# Ownership tree towards ultimate beneficial owners
tree = fr.companies.ownership(orgnr, direction="up", depth=5)
for owner in tree.owners:
    print(owner.navn, owner.eierandel_prosent)

# Transparent risk score with component breakdown
score = fr.risk.score(orgnr)
print(score.score, score.level, score.components)

Async

Every operation has an async twin. Either construct AsyncFirmaradar directly, or derive an async session from an existing client:

import asyncio
from firmaradar import Firmaradar

fr = Firmaradar()

async def screen(orgnrs: list[str]):
    async with fr.async_session() as session:
        return await asyncio.gather(*(session.companies.get(o) for o in orgnrs))

companies = asyncio.run(screen(["923609016", "914594685"]))

Async AML reports (submit → poll)

AML screening requires a signed DPA with Firmaradar. Calling start_report confirms the screening and records the purpose in the audit trail (60-month retention per Hvitvaskingsloven §35):

job = fr.aml.start_report("923609016", purpose="kyc_onboarding")

status = fr.aml.get_report(job.rapport_id)
while status.status in ("pending", "running"):
    time.sleep(5)
    status = fr.aml.get_report(job.rapport_id)

if status.status == "done":
    print(status.score, status.level, status.pdf_url)

Operations

Namespace Method What it returns
companies search(q, nace, kommune, limit, cursor) Paginated company search
companies get(orgnr, fields, owners, ...) Full enriched company profile
companies roles(orgnr, ...) BRREG roles (board, CEO, signature, auditor)
companies ownership(orgnr, direction, depth, ...) Ownership tree (down / up-UBO / both)
companies financials(orgnr, years, regnskapstype) Financial history per accounting year
companies announcements(orgnr) BRREG announcements (normalized categories)
risk score(orgnr) Risk score 0-100 + level + components
risk check_fiv(orgnr) Foretak-i-vanskeligheter (NUES a-e) assessment
aml start_report(orgnr, purpose) Start async AML report (DPA required)
aml get_report(report_id) Poll AML report status/result
monitoring add(orgnr, ip_alerts, categories) Add company to monitoring
monitoring remove(orgnr) Remove company from monitoring (idempotent)
monitoring list() List monitored companies

All responses are typed Pydantic models (firmaradar.models). Models tolerate additive API changes — unknown fields are kept, never fatal.

Error handling

Non-2xx responses raise typed exceptions mapped from the API's error contract (HTTP status + stable error_code):

from firmaradar import (
    AuthenticationError,     # 401 — bad/expired API key
    PermissionDeniedError,   # 403 — not authorized / compliance gate / DPA missing
    NotFoundError,           # 404 — unknown orgnr / report id
    ConflictError,           # 409 — e.g. company already monitored
    ValidationError,         # 400/422 — malformed parameters
    QuotaExceededError,      # 402/429 — quota or rate limit (see .retry_after_s)
    ServiceUnavailableError, # 5xx — transient; retry later
    APIConnectionError,      # network unreachable (APITimeoutError for timeouts)
)

try:
    fr.monitoring.add("923609016")
except ConflictError:
    pass  # already monitored — fine
except QuotaExceededError as exc:
    retry_in = exc.retry_after_s or 60
except PermissionDeniedError as exc:
    print(exc.status_code, exc.error_code, exc)  # e.g. 403 EXTENSION_NOT_ACTIVE

Malformed organisation numbers are rejected client-side (ValueError) before they cost an API call; "923 609 016"-style formatting is normalized automatically.

LangChain integration

from firmaradar.langchain import get_tools          # requires [langchain]
from langchain_anthropic import ChatAnthropic
from langchain.agents import create_tool_calling_agent

tools = get_tools(api_key="fr_...")   # list[StructuredTool], sync + async
agent = create_tool_calling_agent(ChatAnthropic(model="claude-sonnet-4-5"), tools, prompt)

LlamaIndex integration

from firmaradar.llamaindex import get_tool_spec     # requires [llamaindex]
from llama_index.core.agent import ReActAgent

agent = ReActAgent.from_tools(get_tool_spec(api_key="fr_...").to_tool_list())

Tool names, descriptions and argument schemas are shared between both integrations and mirror the Firmaradar MCP server — the same operations behave identically whether an agent reaches them over MCP, LangChain or LlamaIndex.

Configuration

Setting Argument Environment variable Default
API key api_key= FIRMARADAR_API_KEY — (required)
Base URL base_url= FIRMARADAR_BASE_URL https://firmaradar.no
Timeout (s) timeout= FIRMARADAR_TIMEOUT_S 30

Development

python3 -m pytest sdk/python/tests/ -q   # no network, no DB — httpx MockTransport
ruff check sdk/python

License

Apache License 2.0 — see the LICENSE file. © Firmaradar AS.

Release files for firmaradar 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for firmaradar 0.1.0
File Size Uploaded
firmaradar-0.1.0.tar.gz 33.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for firmaradar 0.1.0
File Interpreter ABI Platform
firmaradar-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 61.9 kB

Release files / firmaradar-0.1.0.tar.gz

Download URL firmaradar-0.1.0.tar.gz
Size 33.7 kB
Tags Source
SHA-256 checksum
How to use checksums
44a4d5cd23c39ecf7b7ac8ffb49148b9d3d09d3c18594d2e59e10262453f7d21
BLAKE2b-256 checksum
How to use checksums
aae10470bebab01e1a63452bf2928287157013e958d1ebf67aecd3dc31687526
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.2

Release files / firmaradar-0.1.0-py3-none-any.whl

Download URL firmaradar-0.1.0-py3-none-any.whl
Size 28.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9eddedaafa05694119aa795c01282448e3ed43f12894404b07cdcc0ea1ab5d86
BLAKE2b-256 checksum
How to use checksums
b7ef7d5eb3a58fab2947f7130795a005244a93e171444b9bfbc5a13dface5186
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.2

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page