Skip to main content

Python client for the Finansfatura e-invoice (e-Fatura / e-Arşiv) API

Project description

finansfatura

Python client for the Finansfatura e-invoice API (e-Fatura / e-Arşiv). Issue, list, download and cancel invoices with an API key — no WooCommerce required, this is the general external REST API.

Install

pip install finansfatura

Quickstart

import os
from finansfatura import FinansfaturaClient, build_earsiv_payload

ff = FinansfaturaClient(api_key=os.environ["FINANSFATURA_API_KEY"])  # ff_live_...

payload = build_earsiv_payload(
    recipient={"vkn_tckn": "11111111111", "title": "Ahmet Yılmaz",
               "email": "ahmet@example.com"},
    lines=[
        {"title": "Kablosuz Kulaklık", "product_code": "SKU-1042",
         "qty": 1, "unit_price": 100.0, "vat_rate": 0.20},
    ],
)

result = ff.issue_invoice(payload, idempotency_key="order-1042")
print(result["invoice_id"], result["status"])   # -> ... QUEUED

Typed inputs (optional)

Prefer autocomplete and early "missing field" errors over raw dicts? Pass Party / Line dataclasses instead — same result, no extra dependency:

from finansfatura import Party, Line, build_earsiv_payload

payload = build_earsiv_payload(
    recipient=Party(vkn_tckn="11111111111", title="Ahmet Yılmaz", email="ahmet@example.com"),
    lines=[Line(title="Kablosuz Kulaklık", qty=1, unit_price=100.0, vat_rate=0.20)],
)

Dicts and dataclasses are interchangeable everywhere; use whichever you like.

build_earsiv_payload computes totals from the lines (Decimal, no float drift) and applies the API's exact field casing for you: the outer layer is snake_case (document_type, canonical) but everything inside canonical is PascalCase (Recipient, Lines, Totals, VKNorTCKN). A snake_case key inside canonical is silently ignored by the server, so let the builder handle it.

Idempotency

idempotency_key is required and can be any unique string (use your order id). Retrying with the same key never double-issues — safe on timeout/retry.

Reading & lifecycle

ff.get_invoice(invoice_id)                 # poll while status is QUEUED
ff.list_invoices(page=1)
pdf_bytes = ff.download(invoice_id, "pdf")  # or "html" / "xml"
ff.cancel(invoice_id)                       # before GİB acceptance

Errors

Failed calls raise a typed exception carrying .status and .body:

Exception HTTP Meaning
AuthError 401 key missing/invalid/revoked/expired
InsufficientCredits 402 not enough credits (kontör)
ScopeError 403 key lacks the required scope
OnboardingRequired 412 e-invoice onboarding not completed
ProviderError 5xx transient upstream — retry same idempotency key
FinansfaturaError other base class
from finansfatura import FinansfaturaError, OnboardingRequired

try:
    ff.issue_invoice(payload, idempotency_key=f"order-{order.id}")
except OnboardingRequired as e:
    ...  # e.body -> {"error_code": ..., "message": ...}
except FinansfaturaError as e:
    log.error("issue failed [%s]: %s", e.status, e.body)

e-Fatura (registered recipients)

e-Arşiv targets final consumers (TCKN is fine). For a GİB-registered recipient use e-Fatura, which needs the recipient's mailbox alias:

from finansfatura import build_efatura_payload

payload = build_efatura_payload(
    recipient={"vkn_tckn": "1234567890", "title": "Kurum A.Ş."},
    lines=[...],
    recipient_alias="urn:mail:defaultpk@example.com",
)

Notes

  • Seller identity (Issuer) is filled server-side from your company profile — don't send it. Make sure the profile VKN is set, or issuing returns 503.
  • Keep the API key in an env var; never commit it.

Development

pip install -e ".[dev]"
python -m pytest        # or: python -m unittest discover tests

License

MIT

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

finansfatura-0.1.1.tar.gz (8.3 kB view details)

Uploaded Source

Built Distribution

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

finansfatura-0.1.1-py3-none-any.whl (9.0 kB view details)

Uploaded Python 3

File details

Details for the file finansfatura-0.1.1.tar.gz.

File metadata

  • Download URL: finansfatura-0.1.1.tar.gz
  • Upload date:
  • Size: 8.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for finansfatura-0.1.1.tar.gz
Algorithm Hash digest
SHA256 f8cf4ad480ab3d1f05c4e0850f0f70bf0df8fbc98d55b75a500ade55c516c8a3
MD5 56d4b15326c2e6e50738ece1b5e9acfe
BLAKE2b-256 bccc8c5c8e4ecea5240a56ca9ed60a8c614c79b9c47007b40da31cf034ede47a

See more details on using hashes here.

Provenance

The following attestation bundles were made for finansfatura-0.1.1.tar.gz:

Publisher: publish.yml on finansfatura/ff-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file finansfatura-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: finansfatura-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 9.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for finansfatura-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 af3aeca5c3add482607e0a6346f5793b69301e681b5884c55a48e1edf5aef0fd
MD5 303c05dc473e7845531152a6b1feeb03
BLAKE2b-256 9b45fc83887d09c7f09d332ce1844ffbaff8d08415f88df69d2be18b1bfc8c31

See more details on using hashes here.

Provenance

The following attestation bundles were made for finansfatura-0.1.1-py3-none-any.whl:

Publisher: publish.yml on finansfatura/ff-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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