Skip to main content

Official Python SDK for Firmaradar — enrichment platform for Norwegian company intelligence (KYC, AML, credit, ownership and risk).

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

firmaradar-0.1.0.tar.gz (33.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

firmaradar-0.1.0-py3-none-any.whl (28.2 kB view details)

Uploaded Python 3

File details

Details for the file firmaradar-0.1.0.tar.gz.

File metadata

  • Download URL: firmaradar-0.1.0.tar.gz
  • Upload date:
  • Size: 33.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.2

File hashes

Hashes for firmaradar-0.1.0.tar.gz
Algorithm Hash digest
SHA256 44a4d5cd23c39ecf7b7ac8ffb49148b9d3d09d3c18594d2e59e10262453f7d21
MD5 246687b1868fc16bbcadf65339dcf278
BLAKE2b-256 aae10470bebab01e1a63452bf2928287157013e958d1ebf67aecd3dc31687526

See more details on using hashes here.

File details

Details for the file firmaradar-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: firmaradar-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 28.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.2

File hashes

Hashes for firmaradar-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9eddedaafa05694119aa795c01282448e3ed43f12894404b07cdcc0ea1ab5d86
MD5 d3784bb88c9fc3d7d9cdddd2c29627fd
BLAKE2b-256 b7ef7d5eb3a58fab2947f7130795a005244a93e171444b9bfbc5a13dface5186

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page