FinBaze for Platforms

SDKs

pip install finbaze

Python 3.10 or newer. httpx does the HTTP (sync and async), pydantic v2 types every answer. The SDK is generated from the same GraphQL operations as the Node SDK, so the resources and names match; only the casing follows the language.

from finbaze import FinBaze

finbaze = FinBaze(secret_key="fb_sk_test_…")  # fb_*_test_ keys use the sandbox API

company = finbaze.platform.companies.create({"externalId": "acme-1", "registrationCountry": "NL", "registrationNumber": "00000001"})
user = finbaze.platform.users.upsert({"externalUserId": "user-42", "firstName": "Sam"})
finbaze.platform.users.set_access(user_id=user.id, company_id=company.company.id, role="admin")

session = finbaze.platform.embed_sessions.create(
    company=company.company.id, user={"id": user.id}, components={"vatReturn": {"enabled": True}},
)
return {"clientSecret": session.client_secret}

Async: from finbaze import AsyncFinBaze, the same names, await the calls and async for over auto_paging_iter(). with FinBaze(...) and async with AsyncFinBaze(...) close the connection pool.

Options: FinBaze(secret_key, api_base=…, version=…, max_retries=2, timeout=30.0, scopes=[…], app_info={"name": …}). You can also pass access_token= (a platform user token) or client_id=, client_secret= and profile_id=.

What the client does for you#

  • Exchanges the key for an access token (POST /v2/oauth2/token), caches it and refreshes it 60 seconds before it expires; a token the API rejects is dropped and exchanged again.
  • Sends FinBaze-Version (the API version this SDK was built for).
  • Puts an Idempotency-Key on every mutation that can be retried and keeps the same key on every attempt. Pass idempotency_key="…" to choose it, for example to tie a create to your own order id.
  • Retries network errors, HTTP 429 and 500/502/503/504 (not GraphQL errors) with jittered backoff; a Retry-After header is a floor. max_retries=0 turns retries off.

Webhooks#

event = finbaze.webhooks.construct_platform_event(raw_body, request.headers["X-FinBaze-Signature"], secret)

Pass the body exactly as received. secret may be a list ([new, old]) while you rotate. The check is constant-time and rejects timestamps more than 300 seconds off; failures raise SignatureVerificationError. generate_test_header(payload, secret) builds a valid header for your own tests. See events and webhooks.

Errors#

FinBazeError is the base class; every error carries code, status, param, doc_url and request_id.

ClassRaised for
AuthenticationErrorUNAUTHENTICATED, EMBED_SECRET_INVALID, EMBED_SESSION_REVOKED, HTTP 401
RateLimitErrorRATE_LIMITED, HTTP 429; retry_after_seconds
FeatureDisabledErrorFEATURE_DISABLED, EMBED_FEATURE_DISABLED, PLATFORM_HEADLESS_DISABLED
OperationNotAllowedErrorEMBED_OPERATION_NOT_ALLOWED, EMBED_COMPONENT_NOT_ALLOWED, FORBIDDEN_TOKEN_TYPE, FORBIDDEN
NotFoundErrorNOT_FOUND, *_NOT_FOUND, HTTP 404
ValidationErrorBAD_USER_INPUT, INVALID_PARAMETER, INVALID_INPUT; param names the argument
ApiErrorany other code (read code)
NetworkError, ServiceUnavailableErrorno answer, or HTTP 5xx after the retries

The mapping is the same in every server SDK; see errors for the codes.

Resources#

platform.companies, users, user_tokens, embed_sessions, features (and features.limits), usage, data_sources, bulk (NDJSON uploads over HTTP), messages (acknowledge) and step_up (challenge, and header for retrying with a signed assertion). Lists return a Page: page.data is one page, page.auto_paging_iter() walks them all.

finbaze.graphql is the typed client for every operation in the GraphQL reference that the SDK covers, for example finbaze.graphql.sdk_platform_company(external_id="acme-1"), returning pydantic models.

The same calls in all five languages are on server SDK snippets.